From 1a625c0908d0648cc106236bb221a2e90078ead7 Mon Sep 17 00:00:00 2001 From: Love Hornquist Astrand Date: Thu, 1 Jul 2010 10:51:29 -0700 Subject: [PATCH] ltm-0.41 --- lib/hcrypto/libtommath/LICENSE | 4 + lib/hcrypto/libtommath/VERSION | 1 + lib/hcrypto/libtommath/bn.ilg | 6 + lib/hcrypto/libtommath/bn.ind | 82 + lib/hcrypto/libtommath/bn.pdf | Bin 0 -> 345714 bytes lib/hcrypto/libtommath/bn.tex | 1835 +++ lib/hcrypto/libtommath/bn_error.c | 47 + lib/hcrypto/libtommath/bn_fast_mp_invmod.c | 148 + .../libtommath/bn_fast_mp_montgomery_reduce.c | 172 + .../libtommath/bn_fast_s_mp_mul_digs.c | 107 + .../libtommath/bn_fast_s_mp_mul_high_digs.c | 98 + lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c | 114 + lib/hcrypto/libtommath/bn_mp_2expt.c | 48 + lib/hcrypto/libtommath/bn_mp_abs.c | 43 + lib/hcrypto/libtommath/bn_mp_add.c | 53 + lib/hcrypto/libtommath/bn_mp_add_d.c | 112 + lib/hcrypto/libtommath/bn_mp_addmod.c | 41 + lib/hcrypto/libtommath/bn_mp_and.c | 57 + lib/hcrypto/libtommath/bn_mp_clamp.c | 44 + lib/hcrypto/libtommath/bn_mp_clear.c | 44 + lib/hcrypto/libtommath/bn_mp_clear_multi.c | 34 + lib/hcrypto/libtommath/bn_mp_cmp.c | 43 + lib/hcrypto/libtommath/bn_mp_cmp_d.c | 44 + lib/hcrypto/libtommath/bn_mp_cmp_mag.c | 55 + lib/hcrypto/libtommath/bn_mp_cnt_lsb.c | 53 + lib/hcrypto/libtommath/bn_mp_copy.c | 68 + lib/hcrypto/libtommath/bn_mp_count_bits.c | 45 + lib/hcrypto/libtommath/bn_mp_div.c | 292 + lib/hcrypto/libtommath/bn_mp_div_2.c | 68 + lib/hcrypto/libtommath/bn_mp_div_2d.c | 97 + lib/hcrypto/libtommath/bn_mp_div_3.c | 79 + lib/hcrypto/libtommath/bn_mp_div_d.c | 115 + lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c | 43 + lib/hcrypto/libtommath/bn_mp_dr_reduce.c | 94 + lib/hcrypto/libtommath/bn_mp_dr_setup.c | 32 + lib/hcrypto/libtommath/bn_mp_exch.c | 34 + lib/hcrypto/libtommath/bn_mp_expt_d.c | 57 + lib/hcrypto/libtommath/bn_mp_exptmod.c | 112 + lib/hcrypto/libtommath/bn_mp_exptmod_fast.c | 321 + lib/hcrypto/libtommath/bn_mp_exteuclid.c | 82 + lib/hcrypto/libtommath/bn_mp_fread.c | 67 + lib/hcrypto/libtommath/bn_mp_fwrite.c | 52 + lib/hcrypto/libtommath/bn_mp_gcd.c | 105 + lib/hcrypto/libtommath/bn_mp_get_int.c | 45 + lib/hcrypto/libtommath/bn_mp_grow.c | 57 + lib/hcrypto/libtommath/bn_mp_init.c | 46 + lib/hcrypto/libtommath/bn_mp_init_copy.c | 32 + lib/hcrypto/libtommath/bn_mp_init_multi.c | 59 + lib/hcrypto/libtommath/bn_mp_init_set.c | 32 + lib/hcrypto/libtommath/bn_mp_init_set_int.c | 31 + lib/hcrypto/libtommath/bn_mp_init_size.c | 48 + lib/hcrypto/libtommath/bn_mp_invmod.c | 43 + lib/hcrypto/libtommath/bn_mp_invmod_slow.c | 175 + lib/hcrypto/libtommath/bn_mp_is_square.c | 109 + lib/hcrypto/libtommath/bn_mp_jacobi.c | 105 + lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c | 167 + lib/hcrypto/libtommath/bn_mp_karatsuba_sqr.c | 121 + lib/hcrypto/libtommath/bn_mp_lcm.c | 60 + lib/hcrypto/libtommath/bn_mp_lshd.c | 67 + lib/hcrypto/libtommath/bn_mp_mod.c | 48 + lib/hcrypto/libtommath/bn_mp_mod_2d.c | 55 + lib/hcrypto/libtommath/bn_mp_mod_d.c | 27 + .../bn_mp_montgomery_calc_normalization.c | 59 + .../libtommath/bn_mp_montgomery_reduce.c | 118 + .../libtommath/bn_mp_montgomery_setup.c | 59 + lib/hcrypto/libtommath/bn_mp_mul.c | 66 + lib/hcrypto/libtommath/bn_mp_mul_2.c | 82 + lib/hcrypto/libtommath/bn_mp_mul_2d.c | 85 + lib/hcrypto/libtommath/bn_mp_mul_d.c | 79 + lib/hcrypto/libtommath/bn_mp_mulmod.c | 40 + lib/hcrypto/libtommath/bn_mp_n_root.c | 132 + lib/hcrypto/libtommath/bn_mp_neg.c | 40 + lib/hcrypto/libtommath/bn_mp_or.c | 50 + lib/hcrypto/libtommath/bn_mp_prime_fermat.c | 62 + .../libtommath/bn_mp_prime_is_divisible.c | 50 + lib/hcrypto/libtommath/bn_mp_prime_is_prime.c | 83 + .../libtommath/bn_mp_prime_miller_rabin.c | 103 + .../libtommath/bn_mp_prime_next_prime.c | 170 + .../bn_mp_prime_rabin_miller_trials.c | 52 + .../libtommath/bn_mp_prime_random_ex.c | 125 + lib/hcrypto/libtommath/bn_mp_radix_size.c | 78 + lib/hcrypto/libtommath/bn_mp_radix_smap.c | 24 + lib/hcrypto/libtommath/bn_mp_rand.c | 55 + lib/hcrypto/libtommath/bn_mp_read_radix.c | 85 + .../libtommath/bn_mp_read_signed_bin.c | 41 + .../libtommath/bn_mp_read_unsigned_bin.c | 55 + lib/hcrypto/libtommath/bn_mp_reduce.c | 100 + lib/hcrypto/libtommath/bn_mp_reduce_2k.c | 61 + lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c | 62 + .../libtommath/bn_mp_reduce_2k_setup.c | 47 + .../libtommath/bn_mp_reduce_2k_setup_l.c | 44 + lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c | 52 + lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c | 44 + lib/hcrypto/libtommath/bn_mp_reduce_setup.c | 34 + lib/hcrypto/libtommath/bn_mp_rshd.c | 72 + lib/hcrypto/libtommath/bn_mp_set.c | 29 + lib/hcrypto/libtommath/bn_mp_set_int.c | 48 + lib/hcrypto/libtommath/bn_mp_shrink.c | 35 + .../libtommath/bn_mp_signed_bin_size.c | 27 + lib/hcrypto/libtommath/bn_mp_sqr.c | 58 + lib/hcrypto/libtommath/bn_mp_sqrmod.c | 41 + lib/hcrypto/libtommath/bn_mp_sqrt.c | 81 + lib/hcrypto/libtommath/bn_mp_sub.c | 59 + lib/hcrypto/libtommath/bn_mp_sub_d.c | 93 + lib/hcrypto/libtommath/bn_mp_submod.c | 42 + lib/hcrypto/libtommath/bn_mp_to_signed_bin.c | 33 + .../libtommath/bn_mp_to_signed_bin_n.c | 31 + .../libtommath/bn_mp_to_unsigned_bin.c | 48 + .../libtommath/bn_mp_to_unsigned_bin_n.c | 31 + lib/hcrypto/libtommath/bn_mp_toom_mul.c | 284 + lib/hcrypto/libtommath/bn_mp_toom_sqr.c | 226 + lib/hcrypto/libtommath/bn_mp_toradix.c | 75 + lib/hcrypto/libtommath/bn_mp_toradix_n.c | 88 + .../libtommath/bn_mp_unsigned_bin_size.c | 28 + lib/hcrypto/libtommath/bn_mp_xor.c | 51 + lib/hcrypto/libtommath/bn_mp_zero.c | 36 + lib/hcrypto/libtommath/bn_prime_tab.c | 61 + lib/hcrypto/libtommath/bn_reverse.c | 39 + lib/hcrypto/libtommath/bn_s_mp_add.c | 109 + lib/hcrypto/libtommath/bn_s_mp_exptmod.c | 252 + lib/hcrypto/libtommath/bn_s_mp_mul_digs.c | 90 + .../libtommath/bn_s_mp_mul_high_digs.c | 81 + lib/hcrypto/libtommath/bn_s_mp_sqr.c | 84 + lib/hcrypto/libtommath/bn_s_mp_sub.c | 89 + lib/hcrypto/libtommath/bncore.c | 36 + lib/hcrypto/libtommath/booker.pl | 265 + lib/hcrypto/libtommath/callgraph.txt | 11913 ++++++++++++++++ lib/hcrypto/libtommath/changes.txt | 397 + lib/hcrypto/libtommath/demo/demo.c | 740 + lib/hcrypto/libtommath/demo/timing.c | 319 + lib/hcrypto/libtommath/dep.pl | 123 + lib/hcrypto/libtommath/etc/2kprime.1 | 2 + lib/hcrypto/libtommath/etc/2kprime.c | 84 + lib/hcrypto/libtommath/etc/drprime.c | 64 + lib/hcrypto/libtommath/etc/drprimes.28 | 25 + lib/hcrypto/libtommath/etc/drprimes.txt | 9 + lib/hcrypto/libtommath/etc/makefile | 50 + lib/hcrypto/libtommath/etc/makefile.icc | 67 + lib/hcrypto/libtommath/etc/makefile.msvc | 23 + lib/hcrypto/libtommath/etc/mersenne.c | 144 + lib/hcrypto/libtommath/etc/mont.c | 50 + lib/hcrypto/libtommath/etc/pprime.c | 400 + lib/hcrypto/libtommath/etc/prime.1024 | 414 + lib/hcrypto/libtommath/etc/prime.512 | 205 + lib/hcrypto/libtommath/etc/timer.asm | 37 + lib/hcrypto/libtommath/etc/tune.c | 142 + lib/hcrypto/libtommath/gen.pl | 17 + lib/hcrypto/libtommath/libtommath.dsp | 572 + lib/hcrypto/libtommath/logs/README | 13 + lib/hcrypto/libtommath/logs/add.log | 16 + lib/hcrypto/libtommath/logs/addsub.png | Bin 0 -> 6254 bytes lib/hcrypto/libtommath/logs/expt.log | 7 + lib/hcrypto/libtommath/logs/expt.png | Bin 0 -> 6605 bytes lib/hcrypto/libtommath/logs/expt_2k.log | 5 + lib/hcrypto/libtommath/logs/expt_2kl.log | 4 + lib/hcrypto/libtommath/logs/expt_dr.log | 7 + lib/hcrypto/libtommath/logs/graphs.dem | 17 + lib/hcrypto/libtommath/logs/index.html | 27 + lib/hcrypto/libtommath/logs/invmod.log | 0 lib/hcrypto/libtommath/logs/invmod.png | Bin 0 -> 4918 bytes lib/hcrypto/libtommath/logs/mult.log | 84 + lib/hcrypto/libtommath/logs/mult.png | Bin 0 -> 6770 bytes lib/hcrypto/libtommath/logs/mult_kara.log | 84 + lib/hcrypto/libtommath/logs/sqr.log | 84 + lib/hcrypto/libtommath/logs/sqr_kara.log | 84 + lib/hcrypto/libtommath/logs/sub.log | 16 + lib/hcrypto/libtommath/makefile | 186 + lib/hcrypto/libtommath/makefile.bcc | 44 + lib/hcrypto/libtommath/makefile.cygwin_dll | 55 + lib/hcrypto/libtommath/makefile.icc | 116 + lib/hcrypto/libtommath/makefile.msvc | 40 + lib/hcrypto/libtommath/makefile.shared | 102 + lib/hcrypto/libtommath/mess.sh | 4 + lib/hcrypto/libtommath/mtest/logtab.h | 24 + lib/hcrypto/libtommath/mtest/mpi-config.h | 90 + lib/hcrypto/libtommath/mtest/mpi-types.h | 20 + lib/hcrypto/libtommath/mtest/mpi.c | 3985 ++++++ lib/hcrypto/libtommath/mtest/mpi.h | 231 + lib/hcrypto/libtommath/mtest/mtest.c | 308 + .../libtommath/pics/design_process.sxd | Bin 0 -> 6950 bytes .../libtommath/pics/design_process.tif | Bin 0 -> 79042 bytes lib/hcrypto/libtommath/pics/expt_state.sxd | Bin 0 -> 6869 bytes lib/hcrypto/libtommath/pics/expt_state.tif | Bin 0 -> 87542 bytes lib/hcrypto/libtommath/pics/makefile | 35 + lib/hcrypto/libtommath/pics/primality.tif | Bin 0 -> 85514 bytes lib/hcrypto/libtommath/pics/radix.sxd | Bin 0 -> 6181 bytes .../libtommath/pics/sliding_window.sxd | Bin 0 -> 6787 bytes .../libtommath/pics/sliding_window.tif | Bin 0 -> 53880 bytes lib/hcrypto/libtommath/poster.out | 0 lib/hcrypto/libtommath/poster.pdf | Bin 0 -> 37821 bytes lib/hcrypto/libtommath/poster.tex | 35 + lib/hcrypto/libtommath/pre_gen/mpi.c | 9519 ++++++++++++ lib/hcrypto/libtommath/pretty.build | 66 + lib/hcrypto/libtommath/tombc/grammar.txt | 35 + lib/hcrypto/libtommath/tommath.h | 584 + lib/hcrypto/libtommath/tommath.out | 139 + lib/hcrypto/libtommath/tommath.pdf | Bin 0 -> 1183099 bytes lib/hcrypto/libtommath/tommath.src | 6350 ++++++++ lib/hcrypto/libtommath/tommath.tex | 6691 +++++++++ lib/hcrypto/libtommath/tommath_class.h | 999 ++ lib/hcrypto/libtommath/tommath_superclass.h | 76 + 201 files changed, 57213 insertions(+) create mode 100644 lib/hcrypto/libtommath/LICENSE create mode 100644 lib/hcrypto/libtommath/VERSION create mode 100644 lib/hcrypto/libtommath/bn.ilg create mode 100644 lib/hcrypto/libtommath/bn.ind create mode 100644 lib/hcrypto/libtommath/bn.pdf create mode 100644 lib/hcrypto/libtommath/bn.tex create mode 100644 lib/hcrypto/libtommath/bn_error.c create mode 100644 lib/hcrypto/libtommath/bn_fast_mp_invmod.c create mode 100644 lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c create mode 100644 lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c create mode 100644 lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c create mode 100644 lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c create mode 100644 lib/hcrypto/libtommath/bn_mp_2expt.c create mode 100644 lib/hcrypto/libtommath/bn_mp_abs.c create mode 100644 lib/hcrypto/libtommath/bn_mp_add.c create mode 100644 lib/hcrypto/libtommath/bn_mp_add_d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_addmod.c create mode 100644 lib/hcrypto/libtommath/bn_mp_and.c create mode 100644 lib/hcrypto/libtommath/bn_mp_clamp.c create mode 100644 lib/hcrypto/libtommath/bn_mp_clear.c create mode 100644 lib/hcrypto/libtommath/bn_mp_clear_multi.c create mode 100644 lib/hcrypto/libtommath/bn_mp_cmp.c create mode 100644 lib/hcrypto/libtommath/bn_mp_cmp_d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_cmp_mag.c create mode 100644 lib/hcrypto/libtommath/bn_mp_cnt_lsb.c create mode 100644 lib/hcrypto/libtommath/bn_mp_copy.c create mode 100644 lib/hcrypto/libtommath/bn_mp_count_bits.c create mode 100644 lib/hcrypto/libtommath/bn_mp_div.c create mode 100644 lib/hcrypto/libtommath/bn_mp_div_2.c create mode 100644 lib/hcrypto/libtommath/bn_mp_div_2d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_div_3.c create mode 100644 lib/hcrypto/libtommath/bn_mp_div_d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c create mode 100644 lib/hcrypto/libtommath/bn_mp_dr_reduce.c create mode 100644 lib/hcrypto/libtommath/bn_mp_dr_setup.c create mode 100644 lib/hcrypto/libtommath/bn_mp_exch.c create mode 100644 lib/hcrypto/libtommath/bn_mp_expt_d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_exptmod.c create mode 100644 lib/hcrypto/libtommath/bn_mp_exptmod_fast.c create mode 100644 lib/hcrypto/libtommath/bn_mp_exteuclid.c create mode 100644 lib/hcrypto/libtommath/bn_mp_fread.c create mode 100644 lib/hcrypto/libtommath/bn_mp_fwrite.c create mode 100644 lib/hcrypto/libtommath/bn_mp_gcd.c create mode 100644 lib/hcrypto/libtommath/bn_mp_get_int.c create mode 100644 lib/hcrypto/libtommath/bn_mp_grow.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_copy.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_multi.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_set.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_set_int.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_size.c create mode 100644 lib/hcrypto/libtommath/bn_mp_invmod.c create mode 100644 lib/hcrypto/libtommath/bn_mp_invmod_slow.c create mode 100644 lib/hcrypto/libtommath/bn_mp_is_square.c create mode 100644 lib/hcrypto/libtommath/bn_mp_jacobi.c create mode 100644 lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c create mode 100644 lib/hcrypto/libtommath/bn_mp_karatsuba_sqr.c create mode 100644 lib/hcrypto/libtommath/bn_mp_lcm.c create mode 100644 lib/hcrypto/libtommath/bn_mp_lshd.c create mode 100644 lib/hcrypto/libtommath/bn_mp_mod.c create mode 100644 lib/hcrypto/libtommath/bn_mp_mod_2d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_mod_d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c create mode 100644 lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c create mode 100644 lib/hcrypto/libtommath/bn_mp_montgomery_setup.c create mode 100644 lib/hcrypto/libtommath/bn_mp_mul.c create mode 100644 lib/hcrypto/libtommath/bn_mp_mul_2.c create mode 100644 lib/hcrypto/libtommath/bn_mp_mul_2d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_mul_d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_mulmod.c create mode 100644 lib/hcrypto/libtommath/bn_mp_n_root.c create mode 100644 lib/hcrypto/libtommath/bn_mp_neg.c create mode 100644 lib/hcrypto/libtommath/bn_mp_or.c create mode 100644 lib/hcrypto/libtommath/bn_mp_prime_fermat.c create mode 100644 lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c create mode 100644 lib/hcrypto/libtommath/bn_mp_prime_is_prime.c create mode 100644 lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c create mode 100644 lib/hcrypto/libtommath/bn_mp_prime_next_prime.c create mode 100644 lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c create mode 100644 lib/hcrypto/libtommath/bn_mp_prime_random_ex.c create mode 100644 lib/hcrypto/libtommath/bn_mp_radix_size.c create mode 100644 lib/hcrypto/libtommath/bn_mp_radix_smap.c create mode 100644 lib/hcrypto/libtommath/bn_mp_rand.c create mode 100644 lib/hcrypto/libtommath/bn_mp_read_radix.c create mode 100644 lib/hcrypto/libtommath/bn_mp_read_signed_bin.c create mode 100644 lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c create mode 100644 lib/hcrypto/libtommath/bn_mp_reduce.c create mode 100644 lib/hcrypto/libtommath/bn_mp_reduce_2k.c create mode 100644 lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c create mode 100644 lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c create mode 100644 lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c create mode 100644 lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c create mode 100644 lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c create mode 100644 lib/hcrypto/libtommath/bn_mp_reduce_setup.c create mode 100644 lib/hcrypto/libtommath/bn_mp_rshd.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set_int.c create mode 100644 lib/hcrypto/libtommath/bn_mp_shrink.c create mode 100644 lib/hcrypto/libtommath/bn_mp_signed_bin_size.c create mode 100644 lib/hcrypto/libtommath/bn_mp_sqr.c create mode 100644 lib/hcrypto/libtommath/bn_mp_sqrmod.c create mode 100644 lib/hcrypto/libtommath/bn_mp_sqrt.c create mode 100644 lib/hcrypto/libtommath/bn_mp_sub.c create mode 100644 lib/hcrypto/libtommath/bn_mp_sub_d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_submod.c create mode 100644 lib/hcrypto/libtommath/bn_mp_to_signed_bin.c create mode 100644 lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c create mode 100644 lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c create mode 100644 lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c create mode 100644 lib/hcrypto/libtommath/bn_mp_toom_mul.c create mode 100644 lib/hcrypto/libtommath/bn_mp_toom_sqr.c create mode 100644 lib/hcrypto/libtommath/bn_mp_toradix.c create mode 100644 lib/hcrypto/libtommath/bn_mp_toradix_n.c create mode 100644 lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c create mode 100644 lib/hcrypto/libtommath/bn_mp_xor.c create mode 100644 lib/hcrypto/libtommath/bn_mp_zero.c create mode 100644 lib/hcrypto/libtommath/bn_prime_tab.c create mode 100644 lib/hcrypto/libtommath/bn_reverse.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_add.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_exptmod.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_mul_digs.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_sqr.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_sub.c create mode 100644 lib/hcrypto/libtommath/bncore.c create mode 100644 lib/hcrypto/libtommath/booker.pl create mode 100644 lib/hcrypto/libtommath/callgraph.txt create mode 100644 lib/hcrypto/libtommath/changes.txt create mode 100644 lib/hcrypto/libtommath/demo/demo.c create mode 100644 lib/hcrypto/libtommath/demo/timing.c create mode 100644 lib/hcrypto/libtommath/dep.pl create mode 100644 lib/hcrypto/libtommath/etc/2kprime.1 create mode 100644 lib/hcrypto/libtommath/etc/2kprime.c create mode 100644 lib/hcrypto/libtommath/etc/drprime.c create mode 100644 lib/hcrypto/libtommath/etc/drprimes.28 create mode 100644 lib/hcrypto/libtommath/etc/drprimes.txt create mode 100644 lib/hcrypto/libtommath/etc/makefile create mode 100644 lib/hcrypto/libtommath/etc/makefile.icc create mode 100644 lib/hcrypto/libtommath/etc/makefile.msvc create mode 100644 lib/hcrypto/libtommath/etc/mersenne.c create mode 100644 lib/hcrypto/libtommath/etc/mont.c create mode 100644 lib/hcrypto/libtommath/etc/pprime.c create mode 100644 lib/hcrypto/libtommath/etc/prime.1024 create mode 100644 lib/hcrypto/libtommath/etc/prime.512 create mode 100644 lib/hcrypto/libtommath/etc/timer.asm create mode 100644 lib/hcrypto/libtommath/etc/tune.c create mode 100644 lib/hcrypto/libtommath/gen.pl create mode 100644 lib/hcrypto/libtommath/libtommath.dsp create mode 100644 lib/hcrypto/libtommath/logs/README create mode 100644 lib/hcrypto/libtommath/logs/add.log create mode 100644 lib/hcrypto/libtommath/logs/addsub.png create mode 100644 lib/hcrypto/libtommath/logs/expt.log create mode 100644 lib/hcrypto/libtommath/logs/expt.png create mode 100644 lib/hcrypto/libtommath/logs/expt_2k.log create mode 100644 lib/hcrypto/libtommath/logs/expt_2kl.log create mode 100644 lib/hcrypto/libtommath/logs/expt_dr.log create mode 100644 lib/hcrypto/libtommath/logs/graphs.dem create mode 100644 lib/hcrypto/libtommath/logs/index.html create mode 100644 lib/hcrypto/libtommath/logs/invmod.log create mode 100644 lib/hcrypto/libtommath/logs/invmod.png create mode 100644 lib/hcrypto/libtommath/logs/mult.log create mode 100644 lib/hcrypto/libtommath/logs/mult.png create mode 100644 lib/hcrypto/libtommath/logs/mult_kara.log create mode 100644 lib/hcrypto/libtommath/logs/sqr.log create mode 100644 lib/hcrypto/libtommath/logs/sqr_kara.log create mode 100644 lib/hcrypto/libtommath/logs/sub.log create mode 100644 lib/hcrypto/libtommath/makefile create mode 100644 lib/hcrypto/libtommath/makefile.bcc create mode 100644 lib/hcrypto/libtommath/makefile.cygwin_dll create mode 100644 lib/hcrypto/libtommath/makefile.icc create mode 100644 lib/hcrypto/libtommath/makefile.msvc create mode 100644 lib/hcrypto/libtommath/makefile.shared create mode 100644 lib/hcrypto/libtommath/mess.sh create mode 100644 lib/hcrypto/libtommath/mtest/logtab.h create mode 100644 lib/hcrypto/libtommath/mtest/mpi-config.h create mode 100644 lib/hcrypto/libtommath/mtest/mpi-types.h create mode 100644 lib/hcrypto/libtommath/mtest/mpi.c create mode 100644 lib/hcrypto/libtommath/mtest/mpi.h create mode 100644 lib/hcrypto/libtommath/mtest/mtest.c create mode 100644 lib/hcrypto/libtommath/pics/design_process.sxd create mode 100644 lib/hcrypto/libtommath/pics/design_process.tif create mode 100644 lib/hcrypto/libtommath/pics/expt_state.sxd create mode 100644 lib/hcrypto/libtommath/pics/expt_state.tif create mode 100644 lib/hcrypto/libtommath/pics/makefile create mode 100644 lib/hcrypto/libtommath/pics/primality.tif create mode 100644 lib/hcrypto/libtommath/pics/radix.sxd create mode 100644 lib/hcrypto/libtommath/pics/sliding_window.sxd create mode 100644 lib/hcrypto/libtommath/pics/sliding_window.tif create mode 100644 lib/hcrypto/libtommath/poster.out create mode 100644 lib/hcrypto/libtommath/poster.pdf create mode 100644 lib/hcrypto/libtommath/poster.tex create mode 100644 lib/hcrypto/libtommath/pre_gen/mpi.c create mode 100644 lib/hcrypto/libtommath/pretty.build create mode 100644 lib/hcrypto/libtommath/tombc/grammar.txt create mode 100644 lib/hcrypto/libtommath/tommath.h create mode 100644 lib/hcrypto/libtommath/tommath.out create mode 100644 lib/hcrypto/libtommath/tommath.pdf create mode 100644 lib/hcrypto/libtommath/tommath.src create mode 100644 lib/hcrypto/libtommath/tommath.tex create mode 100644 lib/hcrypto/libtommath/tommath_class.h create mode 100644 lib/hcrypto/libtommath/tommath_superclass.h diff --git a/lib/hcrypto/libtommath/LICENSE b/lib/hcrypto/libtommath/LICENSE new file mode 100644 index 000000000..5baa792a6 --- /dev/null +++ b/lib/hcrypto/libtommath/LICENSE @@ -0,0 +1,4 @@ +LibTomMath is hereby released into the Public Domain. + +-- Tom St Denis + diff --git a/lib/hcrypto/libtommath/VERSION b/lib/hcrypto/libtommath/VERSION new file mode 100644 index 000000000..a7d6788f4 --- /dev/null +++ b/lib/hcrypto/libtommath/VERSION @@ -0,0 +1 @@ +0.41 diff --git a/lib/hcrypto/libtommath/bn.ilg b/lib/hcrypto/libtommath/bn.ilg new file mode 100644 index 000000000..3c859f034 --- /dev/null +++ b/lib/hcrypto/libtommath/bn.ilg @@ -0,0 +1,6 @@ +This is makeindex, version 2.14 [02-Oct-2002] (kpathsea + Thai support). +Scanning input file bn.idx....done (79 entries accepted, 0 rejected). +Sorting entries....done (511 comparisons). +Generating output file bn.ind....done (82 lines written, 0 warnings). +Output written in bn.ind. +Transcript written in bn.ilg. diff --git a/lib/hcrypto/libtommath/bn.ind b/lib/hcrypto/libtommath/bn.ind new file mode 100644 index 000000000..c099b521d --- /dev/null +++ b/lib/hcrypto/libtommath/bn.ind @@ -0,0 +1,82 @@ +\begin{theindex} + + \item mp\_add, \hyperpage{31} + \item mp\_add\_d, \hyperpage{56} + \item mp\_and, \hyperpage{31} + \item mp\_clear, \hyperpage{12} + \item mp\_clear\_multi, \hyperpage{13} + \item mp\_cmp, \hyperpage{25} + \item mp\_cmp\_d, \hyperpage{26} + \item mp\_cmp\_mag, \hyperpage{23} + \item mp\_div, \hyperpage{32} + \item mp\_div\_2, \hyperpage{28} + \item mp\_div\_2d, \hyperpage{30} + \item mp\_div\_d, \hyperpage{56} + \item mp\_dr\_reduce, \hyperpage{45} + \item mp\_dr\_setup, \hyperpage{45} + \item MP\_EQ, \hyperpage{23} + \item mp\_error\_to\_string, \hyperpage{9} + \item mp\_expt\_d, \hyperpage{47} + \item mp\_exptmod, \hyperpage{47} + \item mp\_exteuclid, \hyperpage{55} + \item mp\_gcd, \hyperpage{55} + \item mp\_get\_int, \hyperpage{20} + \item mp\_grow, \hyperpage{17} + \item MP\_GT, \hyperpage{23} + \item mp\_init, \hyperpage{11} + \item mp\_init\_copy, \hyperpage{14} + \item mp\_init\_multi, \hyperpage{13} + \item mp\_init\_set, \hyperpage{21} + \item mp\_init\_set\_int, \hyperpage{21} + \item mp\_init\_size, \hyperpage{15} + \item mp\_int, \hyperpage{10} + \item mp\_invmod, \hyperpage{56} + \item mp\_jacobi, \hyperpage{56} + \item mp\_lcm, \hyperpage{56} + \item mp\_lshd, \hyperpage{30} + \item MP\_LT, \hyperpage{23} + \item MP\_MEM, \hyperpage{9} + \item mp\_mod, \hyperpage{39} + \item mp\_mod\_d, \hyperpage{56} + \item mp\_montgomery\_calc\_normalization, \hyperpage{42} + \item mp\_montgomery\_reduce, \hyperpage{42} + \item mp\_montgomery\_setup, \hyperpage{42} + \item mp\_mul, \hyperpage{33} + \item mp\_mul\_2, \hyperpage{28} + \item mp\_mul\_2d, \hyperpage{29} + \item mp\_mul\_d, \hyperpage{56} + \item mp\_n\_root, \hyperpage{48} + \item mp\_neg, \hyperpage{31, 32} + \item MP\_NO, \hyperpage{9} + \item MP\_OKAY, \hyperpage{9} + \item mp\_or, \hyperpage{31} + \item mp\_prime\_fermat, \hyperpage{49} + \item mp\_prime\_is\_divisible, \hyperpage{49} + \item mp\_prime\_is\_prime, \hyperpage{51} + \item mp\_prime\_miller\_rabin, \hyperpage{50} + \item mp\_prime\_next\_prime, \hyperpage{51} + \item mp\_prime\_rabin\_miller\_trials, \hyperpage{50} + \item mp\_prime\_random, \hyperpage{51} + \item mp\_prime\_random\_ex, \hyperpage{52} + \item mp\_radix\_size, \hyperpage{53} + \item mp\_read\_radix, \hyperpage{53} + \item mp\_read\_unsigned\_bin, \hyperpage{54} + \item mp\_reduce, \hyperpage{40} + \item mp\_reduce\_2k, \hyperpage{46} + \item mp\_reduce\_2k\_setup, \hyperpage{46} + \item mp\_reduce\_setup, \hyperpage{40} + \item mp\_rshd, \hyperpage{30} + \item mp\_set, \hyperpage{19} + \item mp\_set\_int, \hyperpage{20} + \item mp\_shrink, \hyperpage{16} + \item mp\_sqr, \hyperpage{35} + \item mp\_sub, \hyperpage{31} + \item mp\_sub\_d, \hyperpage{56} + \item mp\_to\_unsigned\_bin, \hyperpage{54} + \item mp\_toradix, \hyperpage{53} + \item mp\_unsigned\_bin\_size, \hyperpage{54} + \item MP\_VAL, \hyperpage{9} + \item mp\_xor, \hyperpage{31} + \item MP\_YES, \hyperpage{9} + +\end{theindex} diff --git a/lib/hcrypto/libtommath/bn.pdf b/lib/hcrypto/libtommath/bn.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5be712382b4447dfbb6d73768722026852f8c585 GIT binary patch literal 345714 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 z%0A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®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

={U3u#5 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

y=bH&1vO%a25Bdj(SJEZTs}A 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%0AjQ*5J{$ck0z0>9M(fRWl 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

j1#w9gd^)i0Hh!6ZWnRVUF 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 literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/bn.tex b/lib/hcrypto/libtommath/bn.tex new file mode 100644 index 000000000..9017860e7 --- /dev/null +++ b/lib/hcrypto/libtommath/bn.tex @@ -0,0 +1,1835 @@ +\documentclass[synpaper]{book} +\usepackage{hyperref} +\usepackage{makeidx} +\usepackage{amssymb} +\usepackage{color} +\usepackage{alltt} +\usepackage{graphicx} +\usepackage{layout} +\def\union{\cup} +\def\intersect{\cap} +\def\getsrandom{\stackrel{\rm R}{\gets}} +\def\cross{\times} +\def\cat{\hspace{0.5em} \| \hspace{0.5em}} +\def\catn{$\|$} +\def\divides{\hspace{0.3em} | \hspace{0.3em}} +\def\nequiv{\not\equiv} +\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}} +\def\lcm{{\rm lcm}} +\def\gcd{{\rm gcd}} +\def\log{{\rm log}} +\def\ord{{\rm ord}} +\def\abs{{\mathit abs}} +\def\rep{{\mathit rep}} +\def\mod{{\mathit\ mod\ }} +\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})} +\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor} +\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil} +\def\Or{{\rm\ or\ }} +\def\And{{\rm\ and\ }} +\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}} +\def\implies{\Rightarrow} +\def\undefined{{\rm ``undefined"}} +\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}} +\let\oldphi\phi +\def\phi{\varphi} +\def\Pr{{\rm Pr}} +\newcommand{\str}[1]{{\mathbf{#1}}} +\def\F{{\mathbb F}} +\def\N{{\mathbb N}} +\def\Z{{\mathbb Z}} +\def\R{{\mathbb R}} +\def\C{{\mathbb C}} +\def\Q{{\mathbb Q}} +\definecolor{DGray}{gray}{0.5} +\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}} +\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}} +\def\gap{\vspace{0.5ex}} +\makeindex +\begin{document} +\frontmatter +\pagestyle{empty} +\title{LibTomMath User Manual \\ v0.41} +\author{Tom St Denis \\ tomstdenis@gmail.com} +\maketitle +This text, the library and the accompanying textbook are all hereby placed in the public domain. This book has been +formatted for B5 [176x250] paper using the \LaTeX{} {\em book} macro package. + +\vspace{10cm} + +\begin{flushright}Open Source. Open Academia. Open Minds. + +\mbox{ } + +Tom St Denis, + +Ontario, Canada +\end{flushright} + +\tableofcontents +\listoffigures +\mainmatter +\pagestyle{headings} +\chapter{Introduction} +\section{What is LibTomMath?} +LibTomMath is a library of source code which provides a series of efficient and carefully written functions for manipulating +large integer numbers. It was written in portable ISO C source code so that it will build on any platform with a conforming +C compiler. + +In a nutshell the library was written from scratch with verbose comments to help instruct computer science students how +to implement ``bignum'' math. However, the resulting code has proven to be very useful. It has been used by numerous +universities, commercial and open source software developers. It has been used on a variety of platforms ranging from +Linux and Windows based x86 to ARM based Gameboys and PPC based MacOS machines. + +\section{License} +As of the v0.25 the library source code has been placed in the public domain with every new release. As of the v0.28 +release the textbook ``Implementing Multiple Precision Arithmetic'' has been placed in the public domain with every new +release as well. This textbook is meant to compliment the project by providing a more solid walkthrough of the development +algorithms used in the library. + +Since both\footnote{Note that the MPI files under mtest/ are copyrighted by Michael Fromberger. They are not required to use LibTomMath.} are in the +public domain everyone is entitled to do with them as they see fit. + +\section{Building LibTomMath} + +LibTomMath is meant to be very ``GCC friendly'' as it comes with a makefile well suited for GCC. However, the library will +also build in MSVC, Borland C out of the box. For any other ISO C compiler a makefile will have to be made by the end +developer. + +\subsection{Static Libraries} +To build as a static library for GCC issue the following +\begin{alltt} +make +\end{alltt} + +command. This will build the library and archive the object files in ``libtommath.a''. Now you link against +that and include ``tommath.h'' within your programs. Alternatively to build with MSVC issue the following +\begin{alltt} +nmake -f makefile.msvc +\end{alltt} + +This will build the library and archive the object files in ``tommath.lib''. This has been tested with MSVC +version 6.00 with service pack 5. + +\subsection{Shared Libraries} +To build as a shared library for GCC issue the following +\begin{alltt} +make -f makefile.shared +\end{alltt} +This requires the ``libtool'' package (common on most Linux/BSD systems). It will build LibTomMath as both shared +and static then install (by default) into /usr/lib as well as install the header files in /usr/include. The shared +library (resource) will be called ``libtommath.la'' while the static library called ``libtommath.a''. Generally +you use libtool to link your application against the shared object. + +There is limited support for making a ``DLL'' in windows via the ``makefile.cygwin\_dll'' makefile. It requires +Cygwin to work with since it requires the auto-export/import functionality. The resulting DLL and import library +``libtommath.dll.a'' can be used to link LibTomMath dynamically to any Windows program using Cygwin. + +\subsection{Testing} +To build the library and the test harness type + +\begin{alltt} +make test +\end{alltt} + +This will build the library, ``test'' and ``mtest/mtest''. The ``test'' program will accept test vectors and verify the +results. ``mtest/mtest'' will generate test vectors using the MPI library by Michael Fromberger\footnote{A copy of MPI +is included in the package}. Simply pipe mtest into test using + +\begin{alltt} +mtest/mtest | test +\end{alltt} + +If you do not have a ``/dev/urandom'' style RNG source you will have to write your own PRNG and simply pipe that into +mtest. For example, if your PRNG program is called ``myprng'' simply invoke + +\begin{alltt} +myprng | mtest/mtest | test +\end{alltt} + +This will output a row of numbers that are increasing. Each column is a different test (such as addition, multiplication, etc) +that is being performed. The numbers represent how many times the test was invoked. If an error is detected the program +will exit with a dump of the relevent numbers it was working with. + +\section{Build Configuration} +LibTomMath can configured at build time in three phases we shall call ``depends'', ``tweaks'' and ``trims''. +Each phase changes how the library is built and they are applied one after another respectively. + +To make the system more powerful you can tweak the build process. Classes are defined in the file +``tommath\_superclass.h''. By default, the symbol ``LTM\_ALL'' shall be defined which simply +instructs the system to build all of the functions. This is how LibTomMath used to be packaged. This will give you +access to every function LibTomMath offers. + +However, there are cases where such a build is not optional. For instance, you want to perform RSA operations. You +don't need the vast majority of the library to perform these operations. Aside from LTM\_ALL there is +another pre--defined class ``SC\_RSA\_1'' which works in conjunction with the RSA from LibTomCrypt. Additional +classes can be defined base on the need of the user. + +\subsection{Build Depends} +In the file tommath\_class.h you will see a large list of C ``defines'' followed by a series of ``ifdefs'' +which further define symbols. All of the symbols (technically they're macros $\ldots$) represent a given C source +file. For instance, BN\_MP\_ADD\_C represents the file ``bn\_mp\_add.c''. When a define has been enabled the +function in the respective file will be compiled and linked into the library. Accordingly when the define +is absent the file will not be compiled and not contribute any size to the library. + +You will also note that the header tommath\_class.h is actually recursively included (it includes itself twice). +This is to help resolve as many dependencies as possible. In the last pass the symbol LTM\_LAST will be defined. +This is useful for ``trims''. + +\subsection{Build Tweaks} +A tweak is an algorithm ``alternative''. For example, to provide tradeoffs (usually between size and space). +They can be enabled at any pass of the configuration phase. + +\begin{small} +\begin{center} +\begin{tabular}{|l|l|} +\hline \textbf{Define} & \textbf{Purpose} \\ +\hline BN\_MP\_DIV\_SMALL & Enables a slower, smaller and equally \\ + & functional mp\_div() function \\ +\hline +\end{tabular} +\end{center} +\end{small} + +\subsection{Build Trims} +A trim is a manner of removing functionality from a function that is not required. For instance, to perform +RSA cryptography you only require exponentiation with odd moduli so even moduli support can be safely removed. +Build trims are meant to be defined on the last pass of the configuration which means they are to be defined +only if LTM\_LAST has been defined. + +\subsubsection{Moduli Related} +\begin{small} +\begin{center} +\begin{tabular}{|l|l|} +\hline \textbf{Restriction} & \textbf{Undefine} \\ +\hline Exponentiation with odd moduli only & BN\_S\_MP\_EXPTMOD\_C \\ + & BN\_MP\_REDUCE\_C \\ + & BN\_MP\_REDUCE\_SETUP\_C \\ + & BN\_S\_MP\_MUL\_HIGH\_DIGS\_C \\ + & BN\_FAST\_S\_MP\_MUL\_HIGH\_DIGS\_C \\ +\hline Exponentiation with random odd moduli & (The above plus the following) \\ + & BN\_MP\_REDUCE\_2K\_C \\ + & BN\_MP\_REDUCE\_2K\_SETUP\_C \\ + & BN\_MP\_REDUCE\_IS\_2K\_C \\ + & BN\_MP\_DR\_IS\_MODULUS\_C \\ + & BN\_MP\_DR\_REDUCE\_C \\ + & BN\_MP\_DR\_SETUP\_C \\ +\hline Modular inverse odd moduli only & BN\_MP\_INVMOD\_SLOW\_C \\ +\hline Modular inverse (both, smaller/slower) & BN\_FAST\_MP\_INVMOD\_C \\ +\hline +\end{tabular} +\end{center} +\end{small} + +\subsubsection{Operand Size Related} +\begin{small} +\begin{center} +\begin{tabular}{|l|l|} +\hline \textbf{Restriction} & \textbf{Undefine} \\ +\hline Moduli $\le 2560$ bits & BN\_MP\_MONTGOMERY\_REDUCE\_C \\ + & BN\_S\_MP\_MUL\_DIGS\_C \\ + & BN\_S\_MP\_MUL\_HIGH\_DIGS\_C \\ + & BN\_S\_MP\_SQR\_C \\ +\hline Polynomial Schmolynomial & BN\_MP\_KARATSUBA\_MUL\_C \\ + & BN\_MP\_KARATSUBA\_SQR\_C \\ + & BN\_MP\_TOOM\_MUL\_C \\ + & BN\_MP\_TOOM\_SQR\_C \\ + +\hline +\end{tabular} +\end{center} +\end{small} + + +\section{Purpose of LibTomMath} +Unlike GNU MP (GMP) Library, LIP, OpenSSL or various other commercial kits (Miracl), LibTomMath was not written with +bleeding edge performance in mind. First and foremost LibTomMath was written to be entirely open. Not only is the +source code public domain (unlike various other GPL/etc licensed code), not only is the code freely downloadable but the +source code is also accessible for computer science students attempting to learn ``BigNum'' or multiple precision +arithmetic techniques. + +LibTomMath was written to be an instructive collection of source code. This is why there are many comments, only one +function per source file and often I use a ``middle-road'' approach where I don't cut corners for an extra 2\% speed +increase. + +Source code alone cannot really teach how the algorithms work which is why I also wrote a textbook that accompanies +the library (beat that!). + +So you may be thinking ``should I use LibTomMath?'' and the answer is a definite maybe. Let me tabulate what I think +are the pros and cons of LibTomMath by comparing it to the math routines from GnuPG\footnote{GnuPG v1.2.3 versus LibTomMath v0.28}. + +\newpage\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{|l|c|c|l|} +\hline \textbf{Criteria} & \textbf{Pro} & \textbf{Con} & \textbf{Notes} \\ +\hline Few lines of code per file & X & & GnuPG $ = 300.9$, LibTomMath $ = 71.97$ \\ +\hline Commented function prototypes & X && GnuPG function names are cryptic. \\ +\hline Speed && X & LibTomMath is slower. \\ +\hline Totally free & X & & GPL has unfavourable restrictions.\\ +\hline Large function base & X & & GnuPG is barebones. \\ +\hline Five modular reduction algorithms & X & & Faster modular exponentiation for a variety of moduli. \\ +\hline Portable & X & & GnuPG requires configuration to build. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{LibTomMath Valuation} +\end{figure} + +It may seem odd to compare LibTomMath to GnuPG since the math in GnuPG is only a small portion of the entire application. +However, LibTomMath was written with cryptography in mind. It provides essentially all of the functions a cryptosystem +would require when working with large integers. + +So it may feel tempting to just rip the math code out of GnuPG (or GnuMP where it was taken from originally) in your +own application but I think there are reasons not to. While LibTomMath is slower than libraries such as GnuMP it is +not normally significantly slower. On x86 machines the difference is normally a factor of two when performing modular +exponentiations. It depends largely on the processor, compiler and the moduli being used. + +Essentially the only time you wouldn't use LibTomMath is when blazing speed is the primary concern. However, +on the other side of the coin LibTomMath offers you a totally free (public domain) well structured math library +that is very flexible, complete and performs well in resource contrained environments. Fast RSA for example can +be performed with as little as 8KB of ram for data (again depending on build options). + +\chapter{Getting Started with LibTomMath} +\section{Building Programs} +In order to use LibTomMath you must include ``tommath.h'' and link against the appropriate library file (typically +libtommath.a). There is no library initialization required and the entire library is thread safe. + +\section{Return Codes} +There are three possible return codes a function may return. + +\index{MP\_OKAY}\index{MP\_YES}\index{MP\_NO}\index{MP\_VAL}\index{MP\_MEM} +\begin{figure}[here!] +\begin{center} +\begin{small} +\begin{tabular}{|l|l|} +\hline \textbf{Code} & \textbf{Meaning} \\ +\hline MP\_OKAY & The function succeeded. \\ +\hline MP\_VAL & The function input was invalid. \\ +\hline MP\_MEM & Heap memory exhausted. \\ +\hline &\\ +\hline MP\_YES & Response is yes. \\ +\hline MP\_NO & Response is no. \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Return Codes} +\end{figure} + +The last two codes listed are not actually ``return'ed'' by a function. They are placed in an integer (the caller must +provide the address of an integer it can store to) which the caller can access. To convert one of the three return codes +to a string use the following function. + +\index{mp\_error\_to\_string} +\begin{alltt} +char *mp_error_to_string(int code); +\end{alltt} + +This will return a pointer to a string which describes the given error code. It will not work for the return codes +MP\_YES and MP\_NO. + +\section{Data Types} +The basic ``multiple precision integer'' type is known as the ``mp\_int'' within LibTomMath. This data type is used to +organize all of the data required to manipulate the integer it represents. Within LibTomMath it has been prototyped +as the following. + +\index{mp\_int} +\begin{alltt} +typedef struct \{ + int used, alloc, sign; + mp_digit *dp; +\} mp_int; +\end{alltt} + +Where ``mp\_digit'' is a data type that represents individual digits of the integer. By default, an mp\_digit is the +ISO C ``unsigned long'' data type and each digit is $28-$bits long. The mp\_digit type can be configured to suit other +platforms by defining the appropriate macros. + +All LTM functions that use the mp\_int type will expect a pointer to mp\_int structure. You must allocate memory to +hold the structure itself by yourself (whether off stack or heap it doesn't matter). The very first thing that must be +done to use an mp\_int is that it must be initialized. + +\section{Function Organization} + +The arithmetic functions of the library are all organized to have the same style prototype. That is source operands +are passed on the left and the destination is on the right. For instance, + +\begin{alltt} +mp_add(&a, &b, &c); /* c = a + b */ +mp_mul(&a, &a, &c); /* c = a * a */ +mp_div(&a, &b, &c, &d); /* c = [a/b], d = a mod b */ +\end{alltt} + +Another feature of the way the functions have been implemented is that source operands can be destination operands as well. +For instance, + +\begin{alltt} +mp_add(&a, &b, &b); /* b = a + b */ +mp_div(&a, &b, &a, &c); /* a = [a/b], c = a mod b */ +\end{alltt} + +This allows operands to be re-used which can make programming simpler. + +\section{Initialization} +\subsection{Single Initialization} +A single mp\_int can be initialized with the ``mp\_init'' function. + +\index{mp\_init} +\begin{alltt} +int mp_init (mp_int * a); +\end{alltt} + +This function expects a pointer to an mp\_int structure and will initialize the members of the structure so the mp\_int +represents the default integer which is zero. If the functions returns MP\_OKAY then the mp\_int is ready to be used +by the other LibTomMath functions. + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number; + int result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the number */ + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +\subsection{Single Free} +When you are finished with an mp\_int it is ideal to return the heap it used back to the system. The following function +provides this functionality. + +\index{mp\_clear} +\begin{alltt} +void mp_clear (mp_int * a); +\end{alltt} + +The function expects a pointer to a previously initialized mp\_int structure and frees the heap it uses. It sets the +pointer\footnote{The ``dp'' member.} within the mp\_int to \textbf{NULL} which is used to prevent double free situations. +Is is legal to call mp\_clear() twice on the same mp\_int in a row. + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number; + int result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the number */ + + /* We're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +\subsection{Multiple Initializations} +Certain algorithms require more than one large integer. In these instances it is ideal to initialize all of the mp\_int +variables in an ``all or nothing'' fashion. That is, they are either all initialized successfully or they are all +not initialized. + +The mp\_init\_multi() function provides this functionality. + +\index{mp\_init\_multi} \index{mp\_clear\_multi} +\begin{alltt} +int mp_init_multi(mp_int *mp, ...); +\end{alltt} + +It accepts a \textbf{NULL} terminated list of pointers to mp\_int structures. It will attempt to initialize them all +at once. If the function returns MP\_OKAY then all of the mp\_int variables are ready to use, otherwise none of them +are available for use. A complementary mp\_clear\_multi() function allows multiple mp\_int variables to be free'd +from the heap at the same time. + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int num1, num2, num3; + int result; + + if ((result = mp_init_multi(&num1, + &num2, + &num3, NULL)) != MP\_OKAY) \{ + printf("Error initializing the numbers. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the numbers */ + + /* We're done with them. */ + mp_clear_multi(&num1, &num2, &num3, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +\subsection{Other Initializers} +To initialized and make a copy of an mp\_int the mp\_init\_copy() function has been provided. + +\index{mp\_init\_copy} +\begin{alltt} +int mp_init_copy (mp_int * a, mp_int * b); +\end{alltt} + +This function will initialize $a$ and make it a copy of $b$ if all goes well. + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int num1, num2; + int result; + + /* initialize and do work on num1 ... */ + + /* We want a copy of num1 in num2 now */ + if ((result = mp_init_copy(&num2, &num1)) != MP_OKAY) \{ + printf("Error initializing the copy. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now num2 is ready and contains a copy of num1 */ + + /* We're done with them. */ + mp_clear_multi(&num1, &num2, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +Another less common initializer is mp\_init\_size() which allows the user to initialize an mp\_int with a given +default number of digits. By default, all initializers allocate \textbf{MP\_PREC} digits. This function lets +you override this behaviour. + +\index{mp\_init\_size} +\begin{alltt} +int mp_init_size (mp_int * a, int size); +\end{alltt} + +The $size$ parameter must be greater than zero. If the function succeeds the mp\_int $a$ will be initialized +to have $size$ digits (which are all initially zero). + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number; + int result; + + /* we need a 60-digit number */ + if ((result = mp_init_size(&number, 60)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the number */ + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +\section{Maintenance Functions} + +\subsection{Reducing Memory Usage} +When an mp\_int is in a state where it won't be changed again\footnote{A Diffie-Hellman modulus for instance.} excess +digits can be removed to return memory to the heap with the mp\_shrink() function. + +\index{mp\_shrink} +\begin{alltt} +int mp_shrink (mp_int * a); +\end{alltt} + +This will remove excess digits of the mp\_int $a$. If the operation fails the mp\_int should be intact without the +excess digits being removed. Note that you can use a shrunk mp\_int in further computations, however, such operations +will require heap operations which can be slow. It is not ideal to shrink mp\_int variables that you will further +modify in the system (unless you are seriously low on memory). + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number; + int result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the number [e.g. pre-computation] */ + + /* We're done with it for now. */ + if ((result = mp_shrink(&number)) != MP_OKAY) \{ + printf("Error shrinking the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use it .... */ + + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +\subsection{Adding additional digits} + +Within the mp\_int structure are two parameters which control the limitations of the array of digits that represent +the integer the mp\_int is meant to equal. The \textit{used} parameter dictates how many digits are significant, that is, +contribute to the value of the mp\_int. The \textit{alloc} parameter dictates how many digits are currently available in +the array. If you need to perform an operation that requires more digits you will have to mp\_grow() the mp\_int to +your desired size. + +\index{mp\_grow} +\begin{alltt} +int mp_grow (mp_int * a, int size); +\end{alltt} + +This will grow the array of digits of $a$ to $size$. If the \textit{alloc} parameter is already bigger than +$size$ the function will not do anything. + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number; + int result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the number */ + + /* We need to add 20 digits to the number */ + if ((result = mp_grow(&number, number.alloc + 20)) != MP_OKAY) \{ + printf("Error growing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + + /* use the number */ + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +\chapter{Basic Operations} +\section{Small Constants} +Setting mp\_ints to small constants is a relatively common operation. To accomodate these instances there are two +small constant assignment functions. The first function is used to set a single digit constant while the second sets +an ISO C style ``unsigned long'' constant. The reason for both functions is efficiency. Setting a single digit is quick but the +domain of a digit can change (it's always at least $0 \ldots 127$). + +\subsection{Single Digit} + +Setting a single digit can be accomplished with the following function. + +\index{mp\_set} +\begin{alltt} +void mp_set (mp_int * a, mp_digit b); +\end{alltt} + +This will zero the contents of $a$ and make it represent an integer equal to the value of $b$. Note that this +function has a return type of \textbf{void}. It cannot cause an error so it is safe to assume the function +succeeded. + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number; + int result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number to 5 */ + mp_set(&number, 5); + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +\subsection{Long Constants} + +To set a constant that is the size of an ISO C ``unsigned long'' and larger than a single digit the following function +can be used. + +\index{mp\_set\_int} +\begin{alltt} +int mp_set_int (mp_int * a, unsigned long b); +\end{alltt} + +This will assign the value of the 32-bit variable $b$ to the mp\_int $a$. Unlike mp\_set() this function will always +accept a 32-bit input regardless of the size of a single digit. However, since the value may span several digits +this function can fail if it runs out of heap memory. + +To get the ``unsigned long'' copy of an mp\_int the following function can be used. + +\index{mp\_get\_int} +\begin{alltt} +unsigned long mp_get_int (mp_int * a); +\end{alltt} + +This will return the 32 least significant bits of the mp\_int $a$. + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number; + int result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number to 654321 (note this is bigger than 127) */ + if ((result = mp_set_int(&number, 654321)) != MP_OKAY) \{ + printf("Error setting the value of the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + printf("number == \%lu", mp_get_int(&number)); + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +This should output the following if the program succeeds. + +\begin{alltt} +number == 654321 +\end{alltt} + +\subsection{Initialize and Setting Constants} +To both initialize and set small constants the following two functions are available. +\index{mp\_init\_set} \index{mp\_init\_set\_int} +\begin{alltt} +int mp_init_set (mp_int * a, mp_digit b); +int mp_init_set_int (mp_int * a, unsigned long b); +\end{alltt} + +Both functions work like the previous counterparts except they first mp\_init $a$ before setting the values. + +\begin{alltt} +int main(void) +\{ + mp_int number1, number2; + int result; + + /* initialize and set a single digit */ + if ((result = mp_init_set(&number1, 100)) != MP_OKAY) \{ + printf("Error setting number1: \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* initialize and set a long */ + if ((result = mp_init_set_int(&number2, 1023)) != MP_OKAY) \{ + printf("Error setting number2: \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* display */ + printf("Number1, Number2 == \%lu, \%lu", + mp_get_int(&number1), mp_get_int(&number2)); + + /* clear */ + mp_clear_multi(&number1, &number2, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} + +If this program succeeds it shall output. +\begin{alltt} +Number1, Number2 == 100, 1023 +\end{alltt} + +\section{Comparisons} + +Comparisons in LibTomMath are always performed in a ``left to right'' fashion. There are three possible return codes +for any comparison. + +\index{MP\_GT} \index{MP\_EQ} \index{MP\_LT} +\begin{figure}[here] +\begin{center} +\begin{tabular}{|c|c|} +\hline \textbf{Result Code} & \textbf{Meaning} \\ +\hline MP\_GT & $a > b$ \\ +\hline MP\_EQ & $a = b$ \\ +\hline MP\_LT & $a < b$ \\ +\hline +\end{tabular} +\end{center} +\caption{Comparison Codes for $a, b$} +\label{fig:CMP} +\end{figure} + +In figure \ref{fig:CMP} two integers $a$ and $b$ are being compared. In this case $a$ is said to be ``to the left'' of +$b$. + +\subsection{Unsigned comparison} + +An unsigned comparison considers only the digits themselves and not the associated \textit{sign} flag of the +mp\_int structures. This is analogous to an absolute comparison. The function mp\_cmp\_mag() will compare two +mp\_int variables based on their digits only. + +\index{mp\_cmp\_mag} +\begin{alltt} +int mp_cmp_mag(mp_int * a, mp_int * b); +\end{alltt} +This will compare $a$ to $b$ placing $a$ to the left of $b$. This function cannot fail and will return one of the +three compare codes listed in figure \ref{fig:CMP}. + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number1, number2; + int result; + + if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{ + printf("Error initializing the numbers. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number1 to 5 */ + mp_set(&number1, 5); + + /* set the number2 to -6 */ + mp_set(&number2, 6); + if ((result = mp_neg(&number2, &number2)) != MP_OKAY) \{ + printf("Error negating number2. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + switch(mp_cmp_mag(&number1, &number2)) \{ + case MP_GT: printf("|number1| > |number2|"); break; + case MP_EQ: printf("|number1| = |number2|"); break; + case MP_LT: printf("|number1| < |number2|"); break; + \} + + /* we're done with it. */ + mp_clear_multi(&number1, &number2, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +If this program\footnote{This function uses the mp\_neg() function which is discussed in section \ref{sec:NEG}.} completes +successfully it should print the following. + +\begin{alltt} +|number1| < |number2| +\end{alltt} + +This is because $\vert -6 \vert = 6$ and obviously $5 < 6$. + +\subsection{Signed comparison} + +To compare two mp\_int variables based on their signed value the mp\_cmp() function is provided. + +\index{mp\_cmp} +\begin{alltt} +int mp_cmp(mp_int * a, mp_int * b); +\end{alltt} + +This will compare $a$ to the left of $b$. It will first compare the signs of the two mp\_int variables. If they +differ it will return immediately based on their signs. If the signs are equal then it will compare the digits +individually. This function will return one of the compare conditions codes listed in figure \ref{fig:CMP}. + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number1, number2; + int result; + + if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{ + printf("Error initializing the numbers. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number1 to 5 */ + mp_set(&number1, 5); + + /* set the number2 to -6 */ + mp_set(&number2, 6); + if ((result = mp_neg(&number2, &number2)) != MP_OKAY) \{ + printf("Error negating number2. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + switch(mp_cmp(&number1, &number2)) \{ + case MP_GT: printf("number1 > number2"); break; + case MP_EQ: printf("number1 = number2"); break; + case MP_LT: printf("number1 < number2"); break; + \} + + /* we're done with it. */ + mp_clear_multi(&number1, &number2, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +If this program\footnote{This function uses the mp\_neg() function which is discussed in section \ref{sec:NEG}.} completes +successfully it should print the following. + +\begin{alltt} +number1 > number2 +\end{alltt} + +\subsection{Single Digit} + +To compare a single digit against an mp\_int the following function has been provided. + +\index{mp\_cmp\_d} +\begin{alltt} +int mp_cmp_d(mp_int * a, mp_digit b); +\end{alltt} + +This will compare $a$ to the left of $b$ using a signed comparison. Note that it will always treat $b$ as +positive. This function is rather handy when you have to compare against small values such as $1$ (which often +comes up in cryptography). The function cannot fail and will return one of the tree compare condition codes +listed in figure \ref{fig:CMP}. + + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number; + int result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number to 5 */ + mp_set(&number, 5); + + switch(mp_cmp_d(&number, 7)) \{ + case MP_GT: printf("number > 7"); break; + case MP_EQ: printf("number = 7"); break; + case MP_LT: printf("number < 7"); break; + \} + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +If this program functions properly it will print out the following. + +\begin{alltt} +number < 7 +\end{alltt} + +\section{Logical Operations} + +Logical operations are operations that can be performed either with simple shifts or boolean operators such as +AND, XOR and OR directly. These operations are very quick. + +\subsection{Multiplication by two} + +Multiplications and divisions by any power of two can be performed with quick logical shifts either left or +right depending on the operation. + +When multiplying or dividing by two a special case routine can be used which are as follows. +\index{mp\_mul\_2} \index{mp\_div\_2} +\begin{alltt} +int mp_mul_2(mp_int * a, mp_int * b); +int mp_div_2(mp_int * a, mp_int * b); +\end{alltt} + +The former will assign twice $a$ to $b$ while the latter will assign half $a$ to $b$. These functions are fast +since the shift counts and maskes are hardcoded into the routines. + +\begin{small} \begin{alltt} +int main(void) +\{ + mp_int number; + int result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number to 5 */ + mp_set(&number, 5); + + /* multiply by two */ + if ((result = mp\_mul\_2(&number, &number)) != MP_OKAY) \{ + printf("Error multiplying the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + switch(mp_cmp_d(&number, 7)) \{ + case MP_GT: printf("2*number > 7"); break; + case MP_EQ: printf("2*number = 7"); break; + case MP_LT: printf("2*number < 7"); break; + \} + + /* now divide by two */ + if ((result = mp\_div\_2(&number, &number)) != MP_OKAY) \{ + printf("Error dividing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + switch(mp_cmp_d(&number, 7)) \{ + case MP_GT: printf("2*number/2 > 7"); break; + case MP_EQ: printf("2*number/2 = 7"); break; + case MP_LT: printf("2*number/2 < 7"); break; + \} + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} \end{small} + +If this program is successful it will print out the following text. + +\begin{alltt} +2*number > 7 +2*number/2 < 7 +\end{alltt} + +Since $10 > 7$ and $5 < 7$. To multiply by a power of two the following function can be used. + +\index{mp\_mul\_2d} +\begin{alltt} +int mp_mul_2d(mp_int * a, int b, mp_int * c); +\end{alltt} + +This will multiply $a$ by $2^b$ and store the result in ``c''. If the value of $b$ is less than or equal to +zero the function will copy $a$ to ``c'' without performing any further actions. + +To divide by a power of two use the following. + +\index{mp\_div\_2d} +\begin{alltt} +int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d); +\end{alltt} +Which will divide $a$ by $2^b$, store the quotient in ``c'' and the remainder in ``d'. If $b \le 0$ then the +function simply copies $a$ over to ``c'' and zeroes $d$. The variable $d$ may be passed as a \textbf{NULL} +value to signal that the remainder is not desired. + +\subsection{Polynomial Basis Operations} + +Strictly speaking the organization of the integers within the mp\_int structures is what is known as a +``polynomial basis''. This simply means a field element is stored by divisions of a radix. For example, if +$f(x) = \sum_{i=0}^{k} y_ix^k$ for any vector $\vec y$ then the array of digits in $\vec y$ are said to be +the polynomial basis representation of $z$ if $f(\beta) = z$ for a given radix $\beta$. + +To multiply by the polynomial $g(x) = x$ all you have todo is shift the digits of the basis left one place. The +following function provides this operation. + +\index{mp\_lshd} +\begin{alltt} +int mp_lshd (mp_int * a, int b); +\end{alltt} + +This will multiply $a$ in place by $x^b$ which is equivalent to shifting the digits left $b$ places and inserting zeroes +in the least significant digits. Similarly to divide by a power of $x$ the following function is provided. + +\index{mp\_rshd} +\begin{alltt} +void mp_rshd (mp_int * a, int b) +\end{alltt} +This will divide $a$ in place by $x^b$ and discard the remainder. This function cannot fail as it performs the operations +in place and no new digits are required to complete it. + +\subsection{AND, OR and XOR Operations} + +While AND, OR and XOR operations are not typical ``bignum functions'' they can be useful in several instances. The +three functions are prototyped as follows. + +\index{mp\_or} \index{mp\_and} \index{mp\_xor} +\begin{alltt} +int mp_or (mp_int * a, mp_int * b, mp_int * c); +int mp_and (mp_int * a, mp_int * b, mp_int * c); +int mp_xor (mp_int * a, mp_int * b, mp_int * c); +\end{alltt} + +Which compute $c = a \odot b$ where $\odot$ is one of OR, AND or XOR. + +\section{Addition and Subtraction} + +To compute an addition or subtraction the following two functions can be used. + +\index{mp\_add} \index{mp\_sub} +\begin{alltt} +int mp_add (mp_int * a, mp_int * b, mp_int * c); +int mp_sub (mp_int * a, mp_int * b, mp_int * c) +\end{alltt} + +Which perform $c = a \odot b$ where $\odot$ is one of signed addition or subtraction. The operations are fully sign +aware. + +\section{Sign Manipulation} +\subsection{Negation} +\label{sec:NEG} +Simple integer negation can be performed with the following. + +\index{mp\_neg} +\begin{alltt} +int mp_neg (mp_int * a, mp_int * b); +\end{alltt} + +Which assigns $-a$ to $b$. + +\subsection{Absolute} +Simple integer absolutes can be performed with the following. + +\index{mp\_neg} +\begin{alltt} +int mp_abs (mp_int * a, mp_int * b); +\end{alltt} + +Which assigns $\vert a \vert$ to $b$. + +\section{Integer Division and Remainder} +To perform a complete and general integer division with remainder use the following function. + +\index{mp\_div} +\begin{alltt} +int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +\end{alltt} + +This divides $a$ by $b$ and stores the quotient in $c$ and $d$. The signed quotient is computed such that +$bc + d = a$. Note that either of $c$ or $d$ can be set to \textbf{NULL} if their value is not required. If +$b$ is zero the function returns \textbf{MP\_VAL}. + + +\chapter{Multiplication and Squaring} +\section{Multiplication} +A full signed integer multiplication can be performed with the following. +\index{mp\_mul} +\begin{alltt} +int mp_mul (mp_int * a, mp_int * b, mp_int * c); +\end{alltt} +Which assigns the full signed product $ab$ to $c$. This function actually breaks into one of four cases which are +specific multiplication routines optimized for given parameters. First there are the Toom-Cook multiplications which +should only be used with very large inputs. This is followed by the Karatsuba multiplications which are for moderate +sized inputs. Then followed by the Comba and baseline multipliers. + +Fortunately for the developer you don't really need to know this unless you really want to fine tune the system. mp\_mul() +will determine on its own\footnote{Some tweaking may be required.} what routine to use automatically when it is called. + +\begin{alltt} +int main(void) +\{ + mp_int number1, number2; + int result; + + /* Initialize the numbers */ + if ((result = mp_init_multi(&number1, + &number2, NULL)) != MP_OKAY) \{ + printf("Error initializing the numbers. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the terms */ + if ((result = mp_set_int(&number, 257)) != MP_OKAY) \{ + printf("Error setting number1. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + if ((result = mp_set_int(&number2, 1023)) != MP_OKAY) \{ + printf("Error setting number2. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* multiply them */ + if ((result = mp_mul(&number1, &number2, + &number1)) != MP_OKAY) \{ + printf("Error multiplying terms. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* display */ + printf("number1 * number2 == \%lu", mp_get_int(&number1)); + + /* free terms and return */ + mp_clear_multi(&number1, &number2, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} + +If this program succeeds it shall output the following. + +\begin{alltt} +number1 * number2 == 262911 +\end{alltt} + +\section{Squaring} +Since squaring can be performed faster than multiplication it is performed it's own function instead of just using +mp\_mul(). + +\index{mp\_sqr} +\begin{alltt} +int mp_sqr (mp_int * a, mp_int * b); +\end{alltt} + +Will square $a$ and store it in $b$. Like the case of multiplication there are four different squaring +algorithms all which can be called from mp\_sqr(). It is ideal to use mp\_sqr over mp\_mul when squaring terms because +of the speed difference. + +\section{Tuning Polynomial Basis Routines} + +Both of the Toom-Cook and Karatsuba multiplication algorithms are faster than the traditional $O(n^2)$ approach that +the Comba and baseline algorithms use. At $O(n^{1.464973})$ and $O(n^{1.584962})$ running times respectively they require +considerably less work. For example, a 10000-digit multiplication would take roughly 724,000 single precision +multiplications with Toom-Cook or 100,000,000 single precision multiplications with the standard Comba (a factor +of 138). + +So why not always use Karatsuba or Toom-Cook? The simple answer is that they have so much overhead that they're not +actually faster than Comba until you hit distinct ``cutoff'' points. For Karatsuba with the default configuration, +GCC 3.3.1 and an Athlon XP processor the cutoff point is roughly 110 digits (about 70 for the Intel P4). That is, at +110 digits Karatsuba and Comba multiplications just about break even and for 110+ digits Karatsuba is faster. + +Toom-Cook has incredible overhead and is probably only useful for very large inputs. So far no known cutoff points +exist and for the most part I just set the cutoff points very high to make sure they're not called. + +A demo program in the ``etc/'' directory of the project called ``tune.c'' can be used to find the cutoff points. This +can be built with GCC as follows + +\begin{alltt} +make XXX +\end{alltt} +Where ``XXX'' is one of the following entries from the table \ref{fig:tuning}. + +\begin{figure}[here] +\begin{center} +\begin{small} +\begin{tabular}{|l|l|} +\hline \textbf{Value of XXX} & \textbf{Meaning} \\ +\hline tune & Builds portable tuning application \\ +\hline tune86 & Builds x86 (pentium and up) program for COFF \\ +\hline tune86c & Builds x86 program for Cygwin \\ +\hline tune86l & Builds x86 program for Linux (ELF format) \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Build Names for Tuning Programs} +\label{fig:tuning} +\end{figure} + +When the program is running it will output a series of measurements for different cutoff points. It will first find +good Karatsuba squaring and multiplication points. Then it proceeds to find Toom-Cook points. Note that the Toom-Cook +tuning takes a very long time as the cutoff points are likely to be very high. + +\chapter{Modular Reduction} + +Modular reduction is process of taking the remainder of one quantity divided by another. Expressed +as (\ref{eqn:mod}) the modular reduction is equivalent to the remainder of $b$ divided by $c$. + +\begin{equation} +a \equiv b \mbox{ (mod }c\mbox{)} +\label{eqn:mod} +\end{equation} + +Of particular interest to cryptography are reductions where $b$ is limited to the range $0 \le b < c^2$ since particularly +fast reduction algorithms can be written for the limited range. + +Note that one of the four optimized reduction algorithms are automatically chosen in the modular exponentiation +algorithm mp\_exptmod when an appropriate modulus is detected. + +\section{Straight Division} +In order to effect an arbitrary modular reduction the following algorithm is provided. + +\index{mp\_mod} +\begin{alltt} +int mp_mod(mp_int *a, mp_int *b, mp_int *c); +\end{alltt} + +This reduces $a$ modulo $b$ and stores the result in $c$. The sign of $c$ shall agree with the sign +of $b$. This algorithm accepts an input $a$ of any range and is not limited by $0 \le a < b^2$. + +\section{Barrett Reduction} + +Barrett reduction is a generic optimized reduction algorithm that requires pre--computation to achieve +a decent speedup over straight division. First a $\mu$ value must be precomputed with the following function. + +\index{mp\_reduce\_setup} +\begin{alltt} +int mp_reduce_setup(mp_int *a, mp_int *b); +\end{alltt} + +Given a modulus in $b$ this produces the required $\mu$ value in $a$. For any given modulus this only has to +be computed once. Modular reduction can now be performed with the following. + +\index{mp\_reduce} +\begin{alltt} +int mp_reduce(mp_int *a, mp_int *b, mp_int *c); +\end{alltt} + +This will reduce $a$ in place modulo $b$ with the precomputed $\mu$ value in $c$. $a$ must be in the range +$0 \le a < b^2$. + +\begin{alltt} +int main(void) +\{ + mp_int a, b, c, mu; + int result; + + /* initialize a,b to desired values, mp_init mu, + * c and set c to 1...we want to compute a^3 mod b + */ + + /* get mu value */ + if ((result = mp_reduce_setup(&mu, b)) != MP_OKAY) \{ + printf("Error getting mu. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* square a to get c = a^2 */ + if ((result = mp_sqr(&a, &c)) != MP_OKAY) \{ + printf("Error squaring. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now reduce `c' modulo b */ + if ((result = mp_reduce(&c, &b, &mu)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* multiply a to get c = a^3 */ + if ((result = mp_mul(&a, &c, &c)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now reduce `c' modulo b */ + if ((result = mp_reduce(&c, &b, &mu)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* c now equals a^3 mod b */ + + return EXIT_SUCCESS; +\} +\end{alltt} + +This program will calculate $a^3 \mbox{ mod }b$ if all the functions succeed. + +\section{Montgomery Reduction} + +Montgomery is a specialized reduction algorithm for any odd moduli. Like Barrett reduction a pre--computation +step is required. This is accomplished with the following. + +\index{mp\_montgomery\_setup} +\begin{alltt} +int mp_montgomery_setup(mp_int *a, mp_digit *mp); +\end{alltt} + +For the given odd moduli $a$ the precomputation value is placed in $mp$. The reduction is computed with the +following. + +\index{mp\_montgomery\_reduce} +\begin{alltt} +int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); +\end{alltt} +This reduces $a$ in place modulo $m$ with the pre--computed value $mp$. $a$ must be in the range +$0 \le a < b^2$. + +Montgomery reduction is faster than Barrett reduction for moduli smaller than the ``comba'' limit. With the default +setup for instance, the limit is $127$ digits ($3556$--bits). Note that this function is not limited to +$127$ digits just that it falls back to a baseline algorithm after that point. + +An important observation is that this reduction does not return $a \mbox{ mod }m$ but $aR^{-1} \mbox{ mod }m$ +where $R = \beta^n$, $n$ is the n number of digits in $m$ and $\beta$ is radix used (default is $2^{28}$). + +To quickly calculate $R$ the following function was provided. + +\index{mp\_montgomery\_calc\_normalization} +\begin{alltt} +int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); +\end{alltt} +Which calculates $a = R$ for the odd moduli $b$ without using multiplication or division. + +The normal modus operandi for Montgomery reductions is to normalize the integers before entering the system. For +example, to calculate $a^3 \mbox { mod }b$ using Montgomery reduction the value of $a$ can be normalized by +multiplying it by $R$. Consider the following code snippet. + +\begin{alltt} +int main(void) +\{ + mp_int a, b, c, R; + mp_digit mp; + int result; + + /* initialize a,b to desired values, + * mp_init R, c and set c to 1.... + */ + + /* get normalization */ + if ((result = mp_montgomery_calc_normalization(&R, b)) != MP_OKAY) \{ + printf("Error getting norm. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* get mp value */ + if ((result = mp_montgomery_setup(&c, &mp)) != MP_OKAY) \{ + printf("Error setting up montgomery. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* normalize `a' so now a is equal to aR */ + if ((result = mp_mulmod(&a, &R, &b, &a)) != MP_OKAY) \{ + printf("Error computing aR. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* square a to get c = a^2R^2 */ + if ((result = mp_sqr(&a, &c)) != MP_OKAY) \{ + printf("Error squaring. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now reduce `c' back down to c = a^2R^2 * R^-1 == a^2R */ + if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* multiply a to get c = a^3R^2 */ + if ((result = mp_mul(&a, &c, &c)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now reduce `c' back down to c = a^3R^2 * R^-1 == a^3R */ + if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now reduce (again) `c' back down to c = a^3R * R^-1 == a^3 */ + if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* c now equals a^3 mod b */ + + return EXIT_SUCCESS; +\} +\end{alltt} + +This particular example does not look too efficient but it demonstrates the point of the algorithm. By +normalizing the inputs the reduced results are always of the form $aR$ for some variable $a$. This allows +a single final reduction to correct for the normalization and the fast reduction used within the algorithm. + +For more details consider examining the file \textit{bn\_mp\_exptmod\_fast.c}. + +\section{Restricted Dimminished Radix} + +``Dimminished Radix'' reduction refers to reduction with respect to moduli that are ameniable to simple +digit shifting and small multiplications. In this case the ``restricted'' variant refers to moduli of the +form $\beta^k - p$ for some $k \ge 0$ and $0 < p < \beta$ where $\beta$ is the radix (default to $2^{28}$). + +As in the case of Montgomery reduction there is a pre--computation phase required for a given modulus. + +\index{mp\_dr\_setup} +\begin{alltt} +void mp_dr_setup(mp_int *a, mp_digit *d); +\end{alltt} + +This computes the value required for the modulus $a$ and stores it in $d$. This function cannot fail +and does not return any error codes. After the pre--computation a reduction can be performed with the +following. + +\index{mp\_dr\_reduce} +\begin{alltt} +int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp); +\end{alltt} + +This reduces $a$ in place modulo $b$ with the pre--computed value $mp$. $b$ must be of a restricted +dimminished radix form and $a$ must be in the range $0 \le a < b^2$. Dimminished radix reductions are +much faster than both Barrett and Montgomery reductions as they have a much lower asymtotic running time. + +Since the moduli are restricted this algorithm is not particularly useful for something like Rabin, RSA or +BBS cryptographic purposes. This reduction algorithm is useful for Diffie-Hellman and ECC where fixed +primes are acceptable. + +Note that unlike Montgomery reduction there is no normalization process. The result of this function is +equal to the correct residue. + +\section{Unrestricted Dimminshed Radix} + +Unrestricted reductions work much like the restricted counterparts except in this case the moduli is of the +form $2^k - p$ for $0 < p < \beta$. In this sense the unrestricted reductions are more flexible as they +can be applied to a wider range of numbers. + +\index{mp\_reduce\_2k\_setup} +\begin{alltt} +int mp_reduce_2k_setup(mp_int *a, mp_digit *d); +\end{alltt} + +This will compute the required $d$ value for the given moduli $a$. + +\index{mp\_reduce\_2k} +\begin{alltt} +int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); +\end{alltt} + +This will reduce $a$ in place modulo $n$ with the pre--computed value $d$. From my experience this routine is +slower than mp\_dr\_reduce but faster for most moduli sizes than the Montgomery reduction. + +\chapter{Exponentiation} +\section{Single Digit Exponentiation} +\index{mp\_expt\_d} +\begin{alltt} +int mp_expt_d (mp_int * a, mp_digit b, mp_int * c) +\end{alltt} +This computes $c = a^b$ using a simple binary left-to-right algorithm. It is faster than repeated multiplications by +$a$ for all values of $b$ greater than three. + +\section{Modular Exponentiation} +\index{mp\_exptmod} +\begin{alltt} +int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +\end{alltt} +This computes $Y \equiv G^X \mbox{ (mod }P\mbox{)}$ using a variable width sliding window algorithm. This function +will automatically detect the fastest modular reduction technique to use during the operation. For negative values of +$X$ the operation is performed as $Y \equiv (G^{-1} \mbox{ mod }P)^{\vert X \vert} \mbox{ (mod }P\mbox{)}$ provided that +$gcd(G, P) = 1$. + +This function is actually a shell around the two internal exponentiation functions. This routine will automatically +detect when Barrett, Montgomery, Restricted and Unrestricted Dimminished Radix based exponentiation can be used. Generally +moduli of the a ``restricted dimminished radix'' form lead to the fastest modular exponentiations. Followed by Montgomery +and the other two algorithms. + +\section{Root Finding} +\index{mp\_n\_root} +\begin{alltt} +int mp_n_root (mp_int * a, mp_digit b, mp_int * c) +\end{alltt} +This computes $c = a^{1/b}$ such that $c^b \le a$ and $(c+1)^b > a$. The implementation of this function is not +ideal for values of $b$ greater than three. It will work but become very slow. So unless you are working with very small +numbers (less than 1000 bits) I'd avoid $b > 3$ situations. Will return a positive root only for even roots and return +a root with the sign of the input for odd roots. For example, performing $4^{1/2}$ will return $2$ whereas $(-8)^{1/3}$ +will return $-2$. + +This algorithm uses the ``Newton Approximation'' method and will converge on the correct root fairly quickly. Since +the algorithm requires raising $a$ to the power of $b$ it is not ideal to attempt to find roots for large +values of $b$. If particularly large roots are required then a factor method could be used instead. For example, +$a^{1/16}$ is equivalent to $\left (a^{1/4} \right)^{1/4}$ or simply +$\left ( \left ( \left ( a^{1/2} \right )^{1/2} \right )^{1/2} \right )^{1/2}$ + +\chapter{Prime Numbers} +\section{Trial Division} +\index{mp\_prime\_is\_divisible} +\begin{alltt} +int mp_prime_is_divisible (mp_int * a, int *result) +\end{alltt} +This will attempt to evenly divide $a$ by a list of primes\footnote{Default is the first 256 primes.} and store the +outcome in ``result''. That is if $result = 0$ then $a$ is not divisible by the primes, otherwise it is. Note that +if the function does not return \textbf{MP\_OKAY} the value in ``result'' should be considered undefined\footnote{Currently +the default is to set it to zero first.}. + +\section{Fermat Test} +\index{mp\_prime\_fermat} +\begin{alltt} +int mp_prime_fermat (mp_int * a, mp_int * b, int *result) +\end{alltt} +Performs a Fermat primality test to the base $b$. That is it computes $b^a \mbox{ mod }a$ and tests whether the value is +equal to $b$ or not. If the values are equal then $a$ is probably prime and $result$ is set to one. Otherwise $result$ +is set to zero. + +\section{Miller-Rabin Test} +\index{mp\_prime\_miller\_rabin} +\begin{alltt} +int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result) +\end{alltt} +Performs a Miller-Rabin test to the base $b$ of $a$. This test is much stronger than the Fermat test and is very hard to +fool (besides with Carmichael numbers). If $a$ passes the test (therefore is probably prime) $result$ is set to one. +Otherwise $result$ is set to zero. + +Note that is suggested that you use the Miller-Rabin test instead of the Fermat test since all of the failures of +Miller-Rabin are a subset of the failures of the Fermat test. + +\subsection{Required Number of Tests} +Generally to ensure a number is very likely to be prime you have to perform the Miller-Rabin with at least a half-dozen +or so unique bases. However, it has been proven that the probability of failure goes down as the size of the input goes up. +This is why a simple function has been provided to help out. + +\index{mp\_prime\_rabin\_miller\_trials} +\begin{alltt} +int mp_prime_rabin_miller_trials(int size) +\end{alltt} +This returns the number of trials required for a $2^{-96}$ (or lower) probability of failure for a given ``size'' expressed +in bits. This comes in handy specially since larger numbers are slower to test. For example, a 512-bit number would +require ten tests whereas a 1024-bit number would only require four tests. + +You should always still perform a trial division before a Miller-Rabin test though. + +\section{Primality Testing} +\index{mp\_prime\_is\_prime} +\begin{alltt} +int mp_prime_is_prime (mp_int * a, int t, int *result) +\end{alltt} +This will perform a trial division followed by $t$ rounds of Miller-Rabin tests on $a$ and store the result in $result$. +If $a$ passes all of the tests $result$ is set to one, otherwise it is set to zero. Note that $t$ is bounded by +$1 \le t < PRIME\_SIZE$ where $PRIME\_SIZE$ is the number of primes in the prime number table (by default this is $256$). + +\section{Next Prime} +\index{mp\_prime\_next\_prime} +\begin{alltt} +int mp_prime_next_prime(mp_int *a, int t, int bbs_style) +\end{alltt} +This finds the next prime after $a$ that passes mp\_prime\_is\_prime() with $t$ tests. Set $bbs\_style$ to one if you +want only the next prime congruent to $3 \mbox{ mod } 4$, otherwise set it to zero to find any next prime. + +\section{Random Primes} +\index{mp\_prime\_random} +\begin{alltt} +int mp_prime_random(mp_int *a, int t, int size, int bbs, + ltm_prime_callback cb, void *dat) +\end{alltt} +This will find a prime greater than $256^{size}$ which can be ``bbs\_style'' or not depending on $bbs$ and must pass +$t$ rounds of tests. The ``ltm\_prime\_callback'' is a typedef for + +\begin{alltt} +typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); +\end{alltt} + +Which is a function that must read $len$ bytes (and return the amount stored) into $dst$. The $dat$ variable is simply +copied from the original input. It can be used to pass RNG context data to the callback. The function +mp\_prime\_random() is more suitable for generating primes which must be secret (as in the case of RSA) since there +is no skew on the least significant bits. + +\textit{Note:} As of v0.30 of the LibTomMath library this function has been deprecated. It is still available +but users are encouraged to use the new mp\_prime\_random\_ex() function instead. + +\subsection{Extended Generation} +\index{mp\_prime\_random\_ex} +\begin{alltt} +int mp_prime_random_ex(mp_int *a, int t, + int size, int flags, + ltm_prime_callback cb, void *dat); +\end{alltt} +This will generate a prime in $a$ using $t$ tests of the primality testing algorithms. The variable $size$ +specifies the bit length of the prime desired. The variable $flags$ specifies one of several options available +(see fig. \ref{fig:primeopts}) which can be OR'ed together. The callback parameters are used as in +mp\_prime\_random(). + +\begin{figure}[here] +\begin{center} +\begin{small} +\begin{tabular}{|r|l|} +\hline \textbf{Flag} & \textbf{Meaning} \\ +\hline LTM\_PRIME\_BBS & Make the prime congruent to $3$ modulo $4$ \\ +\hline LTM\_PRIME\_SAFE & Make a prime $p$ such that $(p - 1)/2$ is also prime. \\ + & This option implies LTM\_PRIME\_BBS as well. \\ +\hline LTM\_PRIME\_2MSB\_OFF & Makes sure that the bit adjacent to the most significant bit \\ + & Is forced to zero. \\ +\hline LTM\_PRIME\_2MSB\_ON & Makes sure that the bit adjacent to the most significant bit \\ + & Is forced to one. \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Primality Generation Options} +\label{fig:primeopts} +\end{figure} + +\chapter{Input and Output} +\section{ASCII Conversions} +\subsection{To ASCII} +\index{mp\_toradix} +\begin{alltt} +int mp_toradix (mp_int * a, char *str, int radix); +\end{alltt} +This still store $a$ in ``str'' as a base-``radix'' string of ASCII chars. This function appends a NUL character +to terminate the string. Valid values of ``radix'' line in the range $[2, 64]$. To determine the size (exact) required +by the conversion before storing any data use the following function. + +\index{mp\_radix\_size} +\begin{alltt} +int mp_radix_size (mp_int * a, int radix, int *size) +\end{alltt} +This stores in ``size'' the number of characters (including space for the NUL terminator) required. Upon error this +function returns an error code and ``size'' will be zero. + +\subsection{From ASCII} +\index{mp\_read\_radix} +\begin{alltt} +int mp_read_radix (mp_int * a, char *str, int radix); +\end{alltt} +This will read the base-``radix'' NUL terminated string from ``str'' into $a$. It will stop reading when it reads a +character it does not recognize (which happens to include th NUL char... imagine that...). A single leading $-$ sign +can be used to denote a negative number. + +\section{Binary Conversions} + +Converting an mp\_int to and from binary is another keen idea. + +\index{mp\_unsigned\_bin\_size} +\begin{alltt} +int mp_unsigned_bin_size(mp_int *a); +\end{alltt} + +This will return the number of bytes (octets) required to store the unsigned copy of the integer $a$. + +\index{mp\_to\_unsigned\_bin} +\begin{alltt} +int mp_to_unsigned_bin(mp_int *a, unsigned char *b); +\end{alltt} +This will store $a$ into the buffer $b$ in big--endian format. Fortunately this is exactly what DER (or is it ASN?) +requires. It does not store the sign of the integer. + +\index{mp\_read\_unsigned\_bin} +\begin{alltt} +int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c); +\end{alltt} +This will read in an unsigned big--endian array of bytes (octets) from $b$ of length $c$ into $a$. The resulting +integer $a$ will always be positive. + +For those who acknowledge the existence of negative numbers (heretic!) there are ``signed'' versions of the +previous functions. + +\begin{alltt} +int mp_signed_bin_size(mp_int *a); +int mp_read_signed_bin(mp_int *a, unsigned char *b, int c); +int mp_to_signed_bin(mp_int *a, unsigned char *b); +\end{alltt} +They operate essentially the same as the unsigned copies except they prefix the data with zero or non--zero +byte depending on the sign. If the sign is zpos (e.g. not negative) the prefix is zero, otherwise the prefix +is non--zero. + +\chapter{Algebraic Functions} +\section{Extended Euclidean Algorithm} +\index{mp\_exteuclid} +\begin{alltt} +int mp_exteuclid(mp_int *a, mp_int *b, + mp_int *U1, mp_int *U2, mp_int *U3); +\end{alltt} + +This finds the triple U1/U2/U3 using the Extended Euclidean algorithm such that the following equation holds. + +\begin{equation} +a \cdot U1 + b \cdot U2 = U3 +\end{equation} + +Any of the U1/U2/U3 paramters can be set to \textbf{NULL} if they are not desired. + +\section{Greatest Common Divisor} +\index{mp\_gcd} +\begin{alltt} +int mp_gcd (mp_int * a, mp_int * b, mp_int * c) +\end{alltt} +This will compute the greatest common divisor of $a$ and $b$ and store it in $c$. + +\section{Least Common Multiple} +\index{mp\_lcm} +\begin{alltt} +int mp_lcm (mp_int * a, mp_int * b, mp_int * c) +\end{alltt} +This will compute the least common multiple of $a$ and $b$ and store it in $c$. + +\section{Jacobi Symbol} +\index{mp\_jacobi} +\begin{alltt} +int mp_jacobi (mp_int * a, mp_int * p, int *c) +\end{alltt} +This will compute the Jacobi symbol for $a$ with respect to $p$. If $p$ is prime this essentially computes the Legendre +symbol. The result is stored in $c$ and can take on one of three values $\lbrace -1, 0, 1 \rbrace$. If $p$ is prime +then the result will be $-1$ when $a$ is not a quadratic residue modulo $p$. The result will be $0$ if $a$ divides $p$ +and the result will be $1$ if $a$ is a quadratic residue modulo $p$. + +\section{Modular Inverse} +\index{mp\_invmod} +\begin{alltt} +int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +\end{alltt} +Computes the multiplicative inverse of $a$ modulo $b$ and stores the result in $c$ such that $ac \equiv 1 \mbox{ (mod }b\mbox{)}$. + +\section{Single Digit Functions} + +For those using small numbers (\textit{snicker snicker}) there are several ``helper'' functions + +\index{mp\_add\_d} \index{mp\_sub\_d} \index{mp\_mul\_d} \index{mp\_div\_d} \index{mp\_mod\_d} +\begin{alltt} +int mp_add_d(mp_int *a, mp_digit b, mp_int *c); +int mp_sub_d(mp_int *a, mp_digit b, mp_int *c); +int mp_mul_d(mp_int *a, mp_digit b, mp_int *c); +int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d); +int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c); +\end{alltt} + +These work like the full mp\_int capable variants except the second parameter $b$ is a mp\_digit. These +functions fairly handy if you have to work with relatively small numbers since you will not have to allocate +an entire mp\_int to store a number like $1$ or $2$. + +\input{bn.ind} + +\end{document} diff --git a/lib/hcrypto/libtommath/bn_error.c b/lib/hcrypto/libtommath/bn_error.c new file mode 100644 index 000000000..b1b7177e6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_error.c @@ -0,0 +1,47 @@ +#include +#ifdef BN_ERROR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +static const struct { + int code; + char *msg; +} msgs[] = { + { MP_OKAY, "Successful" }, + { MP_MEM, "Out of heap" }, + { MP_VAL, "Value out of range" } +}; + +/* return a char * string for a given code */ +char *mp_error_to_string(int code) +{ + int x; + + /* scan the lookup table for the given message */ + for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) { + if (msgs[x].code == code) { + return msgs[x].msg; + } + } + + /* generic reply for invalid code */ + return "Invalid error code"; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_error.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_fast_mp_invmod.c b/lib/hcrypto/libtommath/bn_fast_mp_invmod.c new file mode 100644 index 000000000..ff03dfffe --- /dev/null +++ b/lib/hcrypto/libtommath/bn_fast_mp_invmod.c @@ -0,0 +1,148 @@ +#include +#ifdef BN_FAST_MP_INVMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes the modular inverse via binary extended euclidean algorithm, + * that is c = 1/a mod b + * + * Based on slow invmod except this is optimized for the case where b is + * odd as per HAC Note 14.64 on pp. 610 + */ +int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x, y, u, v, B, D; + int res, neg; + + /* 2. [modified] b must be odd */ + if (mp_iseven (b) == 1) { + return MP_VAL; + } + + /* init all our temps */ + if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { + return res; + } + + /* x == modulus, y == value to invert */ + if ((res = mp_copy (b, &x)) != MP_OKAY) { + goto LBL_ERR; + } + + /* we need y = |a| */ + if ((res = mp_mod (a, b, &y)) != MP_OKAY) { + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = mp_copy (&x, &u)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_copy (&y, &v)) != MP_OKAY) { + goto LBL_ERR; + } + mp_set (&D, 1); + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto LBL_ERR; + } + /* 4.2 if B is odd then */ + if (mp_isodd (&B) == 1) { + if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* B = B/2 */ + if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 5. while v is even do */ + while (mp_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto LBL_ERR; + } + /* 5.2 if D is odd then */ + if (mp_isodd (&D) == 1) { + /* D = (D-x)/2 */ + if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* D = D/2 */ + if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 6. if u >= v then */ + if (mp_cmp (&u, &v) != MP_LT) { + /* u = u - v, B = B - D */ + if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + /* v - v - u, D = D - B */ + if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* if not zero goto step 4 */ + if (mp_iszero (&u) == 0) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d (&v, 1) != MP_EQ) { + res = MP_VAL; + goto LBL_ERR; + } + + /* b is now the inverse */ + neg = a->sign; + while (D.sign == MP_NEG) { + if ((res = mp_add (&D, b, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + mp_exch (&D, c); + c->sign = neg; + res = MP_OKAY; + +LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_fast_mp_invmod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c b/lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c new file mode 100644 index 000000000..b6c0694bd --- /dev/null +++ b/lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c @@ -0,0 +1,172 @@ +#include +#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes xR**-1 == x (mod N) via Montgomery Reduction + * + * This is an optimized implementation of montgomery_reduce + * which uses the comba method to quickly calculate the columns of the + * reduction. + * + * Based on Algorithm 14.32 on pp.601 of HAC. +*/ +int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +{ + int ix, res, olduse; + mp_word W[MP_WARRAY]; + + /* get old used count */ + olduse = x->used; + + /* grow a as required */ + if (x->alloc < n->used + 1) { + if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { + return res; + } + } + + /* first we have to get the digits of the input into + * an array of double precision words W[...] + */ + { + register mp_word *_W; + register mp_digit *tmpx; + + /* alias for the W[] array */ + _W = W; + + /* alias for the digits of x*/ + tmpx = x->dp; + + /* copy the digits of a into W[0..a->used-1] */ + for (ix = 0; ix < x->used; ix++) { + *_W++ = *tmpx++; + } + + /* zero the high words of W[a->used..m->used*2] */ + for (; ix < n->used * 2 + 1; ix++) { + *_W++ = 0; + } + } + + /* now we proceed to zero successive digits + * from the least significant upwards + */ + for (ix = 0; ix < n->used; ix++) { + /* mu = ai * m' mod b + * + * We avoid a double precision multiplication (which isn't required) + * by casting the value down to a mp_digit. Note this requires + * that W[ix-1] have the carry cleared (see after the inner loop) + */ + register mp_digit mu; + mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); + + /* a = a + mu * m * b**i + * + * This is computed in place and on the fly. The multiplication + * by b**i is handled by offseting which columns the results + * are added to. + * + * Note the comba method normally doesn't handle carries in the + * inner loop In this case we fix the carry from the previous + * column since the Montgomery reduction requires digits of the + * result (so far) [see above] to work. This is + * handled by fixing up one carry after the inner loop. The + * carry fixups are done in order so after these loops the + * first m->used words of W[] have the carries fixed + */ + { + register int iy; + register mp_digit *tmpn; + register mp_word *_W; + + /* alias for the digits of the modulus */ + tmpn = n->dp; + + /* Alias for the columns set by an offset of ix */ + _W = W + ix; + + /* inner loop */ + for (iy = 0; iy < n->used; iy++) { + *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++); + } + } + + /* now fix carry for next digit, W[ix+1] */ + W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); + } + + /* now we have to propagate the carries and + * shift the words downward [all those least + * significant digits we zeroed]. + */ + { + register mp_digit *tmpx; + register mp_word *_W, *_W1; + + /* nox fix rest of carries */ + + /* alias for current word */ + _W1 = W + ix; + + /* alias for next word, where the carry goes */ + _W = W + ++ix; + + for (; ix <= n->used * 2 + 1; ix++) { + *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); + } + + /* copy out, A = A/b**n + * + * The result is A/b**n but instead of converting from an + * array of mp_word to mp_digit than calling mp_rshd + * we just copy them in the right order + */ + + /* alias for destination word */ + tmpx = x->dp; + + /* alias for shifted double precision result */ + _W = W + n->used; + + for (ix = 0; ix < n->used + 1; ix++) { + *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); + } + + /* zero oldused digits, if the input a was larger than + * m->used+1 we'll have to clear the digits + */ + for (; ix < olduse; ix++) { + *tmpx++ = 0; + } + } + + /* set the max used and clamp */ + x->used = n->used + 1; + mp_clamp (x); + + /* if A >= m then A = A - m */ + if (mp_cmp_mag (x, n) != MP_LT) { + return s_mp_sub (x, n, x); + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_fast_mp_montgomery_reduce.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c b/lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c new file mode 100644 index 000000000..91e10d670 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c @@ -0,0 +1,107 @@ +#include +#ifdef BN_FAST_S_MP_MUL_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Fast (comba) multiplier + * + * This is the fast column-array [comba] multiplier. It is + * designed to compute the columns of the product first + * then handle the carries afterwards. This has the effect + * of making the nested loops that compute the columns very + * simple and schedulable on super-scalar processors. + * + * This has been modified to produce a variable number of + * digits of output so if say only a half-product is required + * you don't have to compute the upper half (a feature + * required for fast Barrett reduction). + * + * Based on Algorithm 14.12 on pp.595 of HAC. + * + */ +int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + int olduse, res, pa, ix, iz; + mp_digit W[MP_WARRAY]; + register mp_word _W; + + /* grow the destination as required */ + if (c->alloc < digs) { + if ((res = mp_grow (c, digs)) != MP_OKAY) { + return res; + } + } + + /* number of output digits to produce */ + pa = MIN(digs, a->used + b->used); + + /* clear the carry */ + _W = 0; + for (ix = 0; ix < pa; ix++) { + int tx, ty; + int iy; + mp_digit *tmpx, *tmpy; + + /* get offsets into the two bignums */ + ty = MIN(b->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = b->dp + ty; + + /* this is the number of times the loop will iterrate, essentially + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; ++iz) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + + } + + /* store term */ + W[ix] = ((mp_digit)_W) & MP_MASK; + + /* make next carry */ + _W = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + register mp_digit *tmpc; + tmpc = c->dp; + for (ix = 0; ix < pa+1; ix++) { + /* now extract the previous digit [below the carry] */ + *tmpc++ = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpc++ = 0; + } + } + mp_clamp (c); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_digs.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c b/lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c new file mode 100644 index 000000000..5b114d717 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c @@ -0,0 +1,98 @@ +#include +#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* this is a modified version of fast_s_mul_digs that only produces + * output digits *above* digs. See the comments for fast_s_mul_digs + * to see how it works. + * + * This is used in the Barrett reduction since for one of the multiplications + * only the higher digits were needed. This essentially halves the work. + * + * Based on Algorithm 14.12 on pp.595 of HAC. + */ +int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + int olduse, res, pa, ix, iz; + mp_digit W[MP_WARRAY]; + mp_word _W; + + /* grow the destination as required */ + pa = a->used + b->used; + if (c->alloc < pa) { + if ((res = mp_grow (c, pa)) != MP_OKAY) { + return res; + } + } + + /* number of output digits to produce */ + pa = a->used + b->used; + _W = 0; + for (ix = digs; ix < pa; ix++) { + int tx, ty, iy; + mp_digit *tmpx, *tmpy; + + /* get offsets into the two bignums */ + ty = MIN(b->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = b->dp + ty; + + /* this is the number of times the loop will iterrate, essentially its + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + } + + /* store term */ + W[ix] = ((mp_digit)_W) & MP_MASK; + + /* make next carry */ + _W = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + register mp_digit *tmpc; + + tmpc = c->dp + digs; + for (ix = digs; ix < pa; ix++) { + /* now extract the previous digit [below the carry] */ + *tmpc++ = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpc++ = 0; + } + } + mp_clamp (c); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_high_digs.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c b/lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c new file mode 100644 index 000000000..19e92ef18 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c @@ -0,0 +1,114 @@ +#include +#ifdef BN_FAST_S_MP_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* the jist of squaring... + * you do like mult except the offset of the tmpx [one that + * starts closer to zero] can't equal the offset of tmpy. + * So basically you set up iy like before then you min it with + * (ty-tx) so that it never happens. You double all those + * you add in the inner loop + +After that loop you do the squares and add them in. +*/ + +int fast_s_mp_sqr (mp_int * a, mp_int * b) +{ + int olduse, res, pa, ix, iz; + mp_digit W[MP_WARRAY], *tmpx; + mp_word W1; + + /* grow the destination as required */ + pa = a->used + a->used; + if (b->alloc < pa) { + if ((res = mp_grow (b, pa)) != MP_OKAY) { + return res; + } + } + + /* number of output digits to produce */ + W1 = 0; + for (ix = 0; ix < pa; ix++) { + int tx, ty, iy; + mp_word _W; + mp_digit *tmpy; + + /* clear counter */ + _W = 0; + + /* get offsets into the two bignums */ + ty = MIN(a->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = a->dp + ty; + + /* this is the number of times the loop will iterrate, essentially + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* now for squaring tx can never equal ty + * we halve the distance since they approach at a rate of 2x + * and we have to round because odd cases need to be executed + */ + iy = MIN(iy, (ty-tx+1)>>1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + } + + /* double the inner product and add carry */ + _W = _W + _W + W1; + + /* even columns have the square term in them */ + if ((ix&1) == 0) { + _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]); + } + + /* store it */ + W[ix] = (mp_digit)(_W & MP_MASK); + + /* make next carry */ + W1 = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = b->used; + b->used = a->used+a->used; + + { + mp_digit *tmpb; + tmpb = b->dp; + for (ix = 0; ix < pa; ix++) { + *tmpb++ = W[ix] & MP_MASK; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpb++ = 0; + } + } + mp_clamp (b); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_sqr.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_2expt.c b/lib/hcrypto/libtommath/bn_mp_2expt.c new file mode 100644 index 000000000..f422ffc99 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_2expt.c @@ -0,0 +1,48 @@ +#include +#ifdef BN_MP_2EXPT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes a = 2**b + * + * Simple algorithm which zeroes the int, grows it then just sets one bit + * as required. + */ +int +mp_2expt (mp_int * a, int b) +{ + int res; + + /* zero a as per default */ + mp_zero (a); + + /* grow a to accomodate the single bit */ + if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { + return res; + } + + /* set the used count of where the bit will go */ + a->used = b / DIGIT_BIT + 1; + + /* put the single bit in its place */ + a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT); + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_2expt.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_abs.c b/lib/hcrypto/libtommath/bn_mp_abs.c new file mode 100644 index 000000000..09dd7229e --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_abs.c @@ -0,0 +1,43 @@ +#include +#ifdef BN_MP_ABS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* b = |a| + * + * Simple function copies the input and fixes the sign to positive + */ +int +mp_abs (mp_int * a, mp_int * b) +{ + int res; + + /* copy a to b */ + if (a != b) { + if ((res = mp_copy (a, b)) != MP_OKAY) { + return res; + } + } + + /* force the sign of b to positive */ + b->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_abs.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_add.c b/lib/hcrypto/libtommath/bn_mp_add.c new file mode 100644 index 000000000..be2064477 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_add.c @@ -0,0 +1,53 @@ +#include +#ifdef BN_MP_ADD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* high level addition (handles signs) */ +int mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + int sa, sb, res; + + /* get sign of both inputs */ + sa = a->sign; + sb = b->sign; + + /* handle two cases, not four */ + if (sa == sb) { + /* both positive or both negative */ + /* add their magnitudes, copy the sign */ + c->sign = sa; + res = s_mp_add (a, b, c); + } else { + /* one positive, the other negative */ + /* subtract the one with the greater magnitude from */ + /* the one of the lesser magnitude. The result gets */ + /* the sign of the one with the greater magnitude. */ + if (mp_cmp_mag (a, b) == MP_LT) { + c->sign = sb; + res = s_mp_sub (b, a, c); + } else { + c->sign = sa; + res = s_mp_sub (a, b, c); + } + } + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_add.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_add_d.c b/lib/hcrypto/libtommath/bn_mp_add_d.c new file mode 100644 index 000000000..8ca36c112 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_add_d.c @@ -0,0 +1,112 @@ +#include +#ifdef BN_MP_ADD_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* single digit addition */ +int +mp_add_d (mp_int * a, mp_digit b, mp_int * c) +{ + int res, ix, oldused; + mp_digit *tmpa, *tmpc, mu; + + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* if a is negative and |a| >= b, call c = |a| - b */ + if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) { + /* temporarily fix sign of a */ + a->sign = MP_ZPOS; + + /* c = |a| - b */ + res = mp_sub_d(a, b, c); + + /* fix sign */ + a->sign = c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return res; + } + + /* old number of used digits in c */ + oldused = c->used; + + /* sign always positive */ + c->sign = MP_ZPOS; + + /* source alias */ + tmpa = a->dp; + + /* destination alias */ + tmpc = c->dp; + + /* if a is positive */ + if (a->sign == MP_ZPOS) { + /* add digit, after this we're propagating + * the carry. + */ + *tmpc = *tmpa++ + b; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + + /* now handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ + mu; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + } + /* set final carry */ + ix++; + *tmpc++ = mu; + + /* setup size */ + c->used = a->used + 1; + } else { + /* a was negative and |a| < b */ + c->used = 1; + + /* the result is a single digit */ + if (a->used == 1) { + *tmpc++ = b - a->dp[0]; + } else { + *tmpc++ = b; + } + + /* setup count so the clearing of oldused + * can fall through correctly + */ + ix = 1; + } + + /* now zero to oldused */ + while (ix++ < oldused) { + *tmpc++ = 0; + } + mp_clamp(c); + + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_add_d.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_addmod.c b/lib/hcrypto/libtommath/bn_mp_addmod.c new file mode 100644 index 000000000..6d8afe18c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_addmod.c @@ -0,0 +1,41 @@ +#include +#ifdef BN_MP_ADDMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* d = a + b (mod c) */ +int +mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_add (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, c, d); + mp_clear (&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_addmod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_and.c b/lib/hcrypto/libtommath/bn_mp_and.c new file mode 100644 index 000000000..8ea22878f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_and.c @@ -0,0 +1,57 @@ +#include +#ifdef BN_MP_AND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* AND two ints together */ +int +mp_and (mp_int * a, mp_int * b, mp_int * c) +{ + int res, ix, px; + mp_int t, *x; + + if (a->used > b->used) { + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + px = b->used; + x = b; + } else { + if ((res = mp_init_copy (&t, b)) != MP_OKAY) { + return res; + } + px = a->used; + x = a; + } + + for (ix = 0; ix < px; ix++) { + t.dp[ix] &= x->dp[ix]; + } + + /* zero digits above the last from the smallest mp_int */ + for (; ix < t.used; ix++) { + t.dp[ix] = 0; + } + + mp_clamp (&t); + mp_exch (c, &t); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_and.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_clamp.c b/lib/hcrypto/libtommath/bn_mp_clamp.c new file mode 100644 index 000000000..359c2ff24 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_clamp.c @@ -0,0 +1,44 @@ +#include +#ifdef BN_MP_CLAMP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* trim unused digits + * + * This is used to ensure that leading zero digits are + * trimed and the leading "used" digit will be non-zero + * Typically very fast. Also fixes the sign if there + * are no more leading digits + */ +void +mp_clamp (mp_int * a) +{ + /* decrease used while the most significant digit is + * zero. + */ + while (a->used > 0 && a->dp[a->used - 1] == 0) { + --(a->used); + } + + /* reset the sign flag if used == 0 */ + if (a->used == 0) { + a->sign = MP_ZPOS; + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_clamp.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_clear.c b/lib/hcrypto/libtommath/bn_mp_clear.c new file mode 100644 index 000000000..a65f0a36c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_clear.c @@ -0,0 +1,44 @@ +#include +#ifdef BN_MP_CLEAR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* clear one (frees) */ +void +mp_clear (mp_int * a) +{ + int i; + + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* first zero the digits */ + for (i = 0; i < a->used; i++) { + a->dp[i] = 0; + } + + /* free ram */ + XFREE(a->dp); + + /* reset members to make debugging easier */ + a->dp = NULL; + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_clear.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_clear_multi.c b/lib/hcrypto/libtommath/bn_mp_clear_multi.c new file mode 100644 index 000000000..daaea79a3 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_clear_multi.c @@ -0,0 +1,34 @@ +#include +#ifdef BN_MP_CLEAR_MULTI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include + +void mp_clear_multi(mp_int *mp, ...) +{ + mp_int* next_mp = mp; + va_list args; + va_start(args, mp); + while (next_mp != NULL) { + mp_clear(next_mp); + next_mp = va_arg(args, mp_int*); + } + va_end(args); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_clear_multi.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_cmp.c b/lib/hcrypto/libtommath/bn_mp_cmp.c new file mode 100644 index 000000000..533f36bf9 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_cmp.c @@ -0,0 +1,43 @@ +#include +#ifdef BN_MP_CMP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* compare two ints (signed)*/ +int +mp_cmp (mp_int * a, mp_int * b) +{ + /* compare based on sign */ + if (a->sign != b->sign) { + if (a->sign == MP_NEG) { + return MP_LT; + } else { + return MP_GT; + } + } + + /* compare digits */ + if (a->sign == MP_NEG) { + /* if negative compare opposite direction */ + return mp_cmp_mag(b, a); + } else { + return mp_cmp_mag(a, b); + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_cmp.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_cmp_d.c b/lib/hcrypto/libtommath/bn_mp_cmp_d.c new file mode 100644 index 000000000..724c1c363 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_cmp_d.c @@ -0,0 +1,44 @@ +#include +#ifdef BN_MP_CMP_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* compare a digit */ +int mp_cmp_d(mp_int * a, mp_digit b) +{ + /* compare based on sign */ + if (a->sign == MP_NEG) { + return MP_LT; + } + + /* compare based on magnitude */ + if (a->used > 1) { + return MP_GT; + } + + /* compare the only digit of a to b */ + if (a->dp[0] > b) { + return MP_GT; + } else if (a->dp[0] < b) { + return MP_LT; + } else { + return MP_EQ; + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_cmp_mag.c b/lib/hcrypto/libtommath/bn_mp_cmp_mag.c new file mode 100644 index 000000000..693eb7cc7 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_cmp_mag.c @@ -0,0 +1,55 @@ +#include +#ifdef BN_MP_CMP_MAG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* compare maginitude of two ints (unsigned) */ +int mp_cmp_mag (mp_int * a, mp_int * b) +{ + int n; + mp_digit *tmpa, *tmpb; + + /* compare based on # of non-zero digits */ + if (a->used > b->used) { + return MP_GT; + } + + if (a->used < b->used) { + return MP_LT; + } + + /* alias for a */ + tmpa = a->dp + (a->used - 1); + + /* alias for b */ + tmpb = b->dp + (a->used - 1); + + /* compare based on digits */ + for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { + if (*tmpa > *tmpb) { + return MP_GT; + } + + if (*tmpa < *tmpb) { + return MP_LT; + } + } + return MP_EQ; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_mag.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c b/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c new file mode 100644 index 000000000..66d1a7471 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c @@ -0,0 +1,53 @@ +#include +#ifdef BN_MP_CNT_LSB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +static const int lnz[16] = { + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(mp_int *a) +{ + int x; + mp_digit q, qq; + + /* easy out */ + if (mp_iszero(a) == 1) { + return 0; + } + + /* scan lower digits until non-zero */ + for (x = 0; x < a->used && a->dp[x] == 0; x++); + q = a->dp[x]; + x *= DIGIT_BIT; + + /* now scan this digit until a 1 is found */ + if ((q & 1) == 0) { + do { + qq = q & 15; + x += lnz[qq]; + q >>= 4; + } while (qq == 0); + } + return x; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_cnt_lsb.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_copy.c b/lib/hcrypto/libtommath/bn_mp_copy.c new file mode 100644 index 000000000..b0de16d8a --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_copy.c @@ -0,0 +1,68 @@ +#include +#ifdef BN_MP_COPY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* copy, b = a */ +int +mp_copy (mp_int * a, mp_int * b) +{ + int res, n; + + /* if dst == src do nothing */ + if (a == b) { + return MP_OKAY; + } + + /* grow dest */ + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + } + + /* zero b and copy the parameters over */ + { + register mp_digit *tmpa, *tmpb; + + /* pointer aliases */ + + /* source */ + tmpa = a->dp; + + /* destination */ + tmpb = b->dp; + + /* copy all the digits */ + for (n = 0; n < a->used; n++) { + *tmpb++ = *tmpa++; + } + + /* clear high digits */ + for (; n < b->used; n++) { + *tmpb++ = 0; + } + } + + /* copy used count and sign */ + b->used = a->used; + b->sign = a->sign; + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_copy.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_count_bits.c b/lib/hcrypto/libtommath/bn_mp_count_bits.c new file mode 100644 index 000000000..8bc5657a3 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_count_bits.c @@ -0,0 +1,45 @@ +#include +#ifdef BN_MP_COUNT_BITS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* returns the number of bits in an int */ +int +mp_count_bits (mp_int * a) +{ + int r; + mp_digit q; + + /* shortcut */ + if (a->used == 0) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > ((mp_digit) 0)) { + ++r; + q >>= ((mp_digit) 1); + } + return r; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_count_bits.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_div.c b/lib/hcrypto/libtommath/bn_mp_div.c new file mode 100644 index 000000000..aee9c9432 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_div.c @@ -0,0 +1,292 @@ +#include +#ifdef BN_MP_DIV_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +#ifdef BN_MP_DIV_SMALL + +/* slower bit-bang division... also smaller */ +int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + mp_int ta, tb, tq, q; + int res, n, n2; + + /* is divisor zero ? */ + if (mp_iszero (b) == 1) { + return MP_VAL; + } + + /* if a < b then q=0, r = a */ + if (mp_cmp_mag (a, b) == MP_LT) { + if (d != NULL) { + res = mp_copy (a, d); + } else { + res = MP_OKAY; + } + if (c != NULL) { + mp_zero (c); + } + return res; + } + + /* init our temps */ + if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) { + return res; + } + + + mp_set(&tq, 1); + n = mp_count_bits(a) - mp_count_bits(b); + if (((res = mp_abs(a, &ta)) != MP_OKAY) || + ((res = mp_abs(b, &tb)) != MP_OKAY) || + ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) || + ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) { + goto LBL_ERR; + } + + while (n-- >= 0) { + if (mp_cmp(&tb, &ta) != MP_GT) { + if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) || + ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) { + goto LBL_ERR; + } + } + if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) || + ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) { + goto LBL_ERR; + } + } + + /* now q == quotient and ta == remainder */ + n = a->sign; + n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG); + if (c != NULL) { + mp_exch(c, &q); + c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2; + } + if (d != NULL) { + mp_exch(d, &ta); + d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n; + } +LBL_ERR: + mp_clear_multi(&ta, &tb, &tq, &q, NULL); + return res; +} + +#else + +/* integer signed division. + * c*b + d == a [e.g. a/b, c=quotient, d=remainder] + * HAC pp.598 Algorithm 14.20 + * + * Note that the description in HAC is horribly + * incomplete. For example, it doesn't consider + * the case where digits are removed from 'x' in + * the inner loop. It also doesn't consider the + * case that y has fewer than three digits, etc.. + * + * The overall algorithm is as described as + * 14.20 from HAC but fixed to treat these cases. +*/ +int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + mp_int q, x, y, t1, t2; + int res, n, t, i, norm, neg; + + /* is divisor zero ? */ + if (mp_iszero (b) == 1) { + return MP_VAL; + } + + /* if a < b then q=0, r = a */ + if (mp_cmp_mag (a, b) == MP_LT) { + if (d != NULL) { + res = mp_copy (a, d); + } else { + res = MP_OKAY; + } + if (c != NULL) { + mp_zero (c); + } + return res; + } + + if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { + return res; + } + q.used = a->used + 2; + + if ((res = mp_init (&t1)) != MP_OKAY) { + goto LBL_Q; + } + + if ((res = mp_init (&t2)) != MP_OKAY) { + goto LBL_T1; + } + + if ((res = mp_init_copy (&x, a)) != MP_OKAY) { + goto LBL_T2; + } + + if ((res = mp_init_copy (&y, b)) != MP_OKAY) { + goto LBL_X; + } + + /* fix the sign */ + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + x.sign = y.sign = MP_ZPOS; + + /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ + norm = mp_count_bits(&y) % DIGIT_BIT; + if (norm < (int)(DIGIT_BIT-1)) { + norm = (DIGIT_BIT-1) - norm; + if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { + goto LBL_Y; + } + if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { + goto LBL_Y; + } + } else { + norm = 0; + } + + /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ + n = x.used - 1; + t = y.used - 1; + + /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ + if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */ + goto LBL_Y; + } + + while (mp_cmp (&x, &y) != MP_LT) { + ++(q.dp[n - t]); + if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { + goto LBL_Y; + } + } + + /* reset y by shifting it back down */ + mp_rshd (&y, n - t); + + /* step 3. for i from n down to (t + 1) */ + for (i = n; i >= (t + 1); i--) { + if (i > x.used) { + continue; + } + + /* step 3.1 if xi == yt then set q{i-t-1} to b-1, + * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ + if (x.dp[i] == y.dp[t]) { + q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); + } else { + mp_word tmp; + tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); + tmp |= ((mp_word) x.dp[i - 1]); + tmp /= ((mp_word) y.dp[t]); + if (tmp > (mp_word) MP_MASK) + tmp = MP_MASK; + q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); + } + + /* while (q{i-t-1} * (yt * b + y{t-1})) > + xi * b**2 + xi-1 * b + xi-2 + + do q{i-t-1} -= 1; + */ + q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; + do { + q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; + + /* find left hand */ + mp_zero (&t1); + t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; + t1.dp[1] = y.dp[t]; + t1.used = 2; + if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { + goto LBL_Y; + } + + /* find right hand */ + t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; + t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; + t2.dp[2] = x.dp[i]; + t2.used = 3; + } while (mp_cmp_mag(&t1, &t2) == MP_GT); + + /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ + if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { + goto LBL_Y; + } + + if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { + goto LBL_Y; + } + + if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { + goto LBL_Y; + } + + /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ + if (x.sign == MP_NEG) { + if ((res = mp_copy (&y, &t1)) != MP_OKAY) { + goto LBL_Y; + } + if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { + goto LBL_Y; + } + if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { + goto LBL_Y; + } + + q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; + } + } + + /* now q is the quotient and x is the remainder + * [which we have to normalize] + */ + + /* get sign before writing to c */ + x.sign = x.used == 0 ? MP_ZPOS : a->sign; + + if (c != NULL) { + mp_clamp (&q); + mp_exch (&q, c); + c->sign = neg; + } + + if (d != NULL) { + mp_div_2d (&x, norm, &x, NULL); + mp_exch (&x, d); + } + + res = MP_OKAY; + +LBL_Y:mp_clear (&y); +LBL_X:mp_clear (&x); +LBL_T2:mp_clear (&t2); +LBL_T1:mp_clear (&t1); +LBL_Q:mp_clear (&q); + return res; +} + +#endif + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_div.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_div_2.c b/lib/hcrypto/libtommath/bn_mp_div_2.c new file mode 100644 index 000000000..7ee3e5b70 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_div_2.c @@ -0,0 +1,68 @@ +#include +#ifdef BN_MP_DIV_2_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* b = a/2 */ +int mp_div_2(mp_int * a, mp_int * b) +{ + int x, res, oldused; + + /* copy */ + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + } + + oldused = b->used; + b->used = a->used; + { + register mp_digit r, rr, *tmpa, *tmpb; + + /* source alias */ + tmpa = a->dp + b->used - 1; + + /* dest alias */ + tmpb = b->dp + b->used - 1; + + /* carry */ + r = 0; + for (x = b->used - 1; x >= 0; x--) { + /* get the carry for the next iteration */ + rr = *tmpa & 1; + + /* shift the current digit, add in carry and store */ + *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero excess digits */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + mp_clamp (b); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_div_2.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_div_2d.c b/lib/hcrypto/libtommath/bn_mp_div_2d.c new file mode 100644 index 000000000..4f7fa59e3 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_div_2d.c @@ -0,0 +1,97 @@ +#include +#ifdef BN_MP_DIV_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ +int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) +{ + mp_digit D, r, rr; + int x, res; + mp_int t; + + + /* if the shift count is <= 0 then we do no work */ + if (b <= 0) { + res = mp_copy (a, c); + if (d != NULL) { + mp_zero (d); + } + return res; + } + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + /* get the remainder */ + if (d != NULL) { + if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + } + + /* copy */ + if ((res = mp_copy (a, c)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + mp_rshd (c, b / DIGIT_BIT); + } + + /* shift any bit count < DIGIT_BIT */ + D = (mp_digit) (b % DIGIT_BIT); + if (D != 0) { + register mp_digit *tmpc, mask, shift; + + /* mask */ + mask = (((mp_digit)1) << D) - 1; + + /* shift for lsb */ + shift = DIGIT_BIT - D; + + /* alias */ + tmpc = c->dp + (c->used - 1); + + /* carry */ + r = 0; + for (x = c->used - 1; x >= 0; x--) { + /* get the lower bits of this word in a temp */ + rr = *tmpc & mask; + + /* shift the current word and mix in the carry bits from the previous word */ + *tmpc = (*tmpc >> D) | (r << shift); + --tmpc; + + /* set the carry to the carry bits of the current word found above */ + r = rr; + } + } + mp_clamp (c); + if (d != NULL) { + mp_exch (&t, d); + } + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_div_2d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_div_3.c b/lib/hcrypto/libtommath/bn_mp_div_3.c new file mode 100644 index 000000000..3c60269ec --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_div_3.c @@ -0,0 +1,79 @@ +#include +#ifdef BN_MP_DIV_3_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* divide by three (based on routine from MPI and the GMP manual) */ +int +mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) +{ + mp_int q; + mp_word w, t; + mp_digit b; + int res, ix; + + /* b = 2**DIGIT_BIT / 3 */ + b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3); + + if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { + return res; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); + + if (w >= 3) { + /* multiply w by [1/3] */ + t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); + + /* now subtract 3 * [w/3] from w, to get the remainder */ + w -= t+t+t; + + /* fixup the remainder as required since + * the optimization is not exact. + */ + while (w >= 3) { + t += 1; + w -= 3; + } + } else { + t = 0; + } + q.dp[ix] = (mp_digit)t; + } + + /* [optional] store the remainder */ + if (d != NULL) { + *d = (mp_digit)w; + } + + /* [optional] store the quotient */ + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_div_3.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_div_d.c b/lib/hcrypto/libtommath/bn_mp_div_d.c new file mode 100644 index 000000000..6a26d4f0c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_div_d.c @@ -0,0 +1,115 @@ +#include +#ifdef BN_MP_DIV_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +static int s_is_power_of_two(mp_digit b, int *p) +{ + int x; + + /* fast return if no power of two */ + if ((b==0) || (b & (b-1))) { + return 0; + } + + for (x = 0; x < DIGIT_BIT; x++) { + if (b == (((mp_digit)1)<dp[0] & ((((mp_digit)1)<used)) != MP_OKAY) { + return res; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); + + if (w >= b) { + t = (mp_digit)(w / b); + w -= ((mp_word)t) * ((mp_word)b); + } else { + t = 0; + } + q.dp[ix] = (mp_digit)t; + } + + if (d != NULL) { + *d = (mp_digit)w; + } + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_div_d.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2007/01/09 04:44:32 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c b/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c new file mode 100644 index 000000000..52373440d --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c @@ -0,0 +1,43 @@ +#include +#ifdef BN_MP_DR_IS_MODULUS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines if a number is a valid DR modulus */ +int mp_dr_is_modulus(mp_int *a) +{ + int ix; + + /* must be at least two digits */ + if (a->used < 2) { + return 0; + } + + /* must be of the form b**k - a [a <= b] so all + * but the first digit must be equal to -1 (mod b). + */ + for (ix = 1; ix < a->used; ix++) { + if (a->dp[ix] != MP_MASK) { + return 0; + } + } + return 1; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_dr_is_modulus.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_dr_reduce.c b/lib/hcrypto/libtommath/bn_mp_dr_reduce.c new file mode 100644 index 000000000..e60b5784f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_dr_reduce.c @@ -0,0 +1,94 @@ +#include +#ifdef BN_MP_DR_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reduce "x" in place modulo "n" using the Diminished Radix algorithm. + * + * Based on algorithm from the paper + * + * "Generating Efficient Primes for Discrete Log Cryptosystems" + * Chae Hoon Lim, Pil Joong Lee, + * POSTECH Information Research Laboratories + * + * The modulus must be of a special format [see manual] + * + * Has been modified to use algorithm 7.10 from the LTM book instead + * + * Input x must be in the range 0 <= x <= (n-1)**2 + */ +int +mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k) +{ + int err, i, m; + mp_word r; + mp_digit mu, *tmpx1, *tmpx2; + + /* m = digits in modulus */ + m = n->used; + + /* ensure that "x" has at least 2m digits */ + if (x->alloc < m + m) { + if ((err = mp_grow (x, m + m)) != MP_OKAY) { + return err; + } + } + +/* top of loop, this is where the code resumes if + * another reduction pass is required. + */ +top: + /* aliases for digits */ + /* alias for lower half of x */ + tmpx1 = x->dp; + + /* alias for upper half of x, or x/B**m */ + tmpx2 = x->dp + m; + + /* set carry to zero */ + mu = 0; + + /* compute (x mod B**m) + k * [x/B**m] inline and inplace */ + for (i = 0; i < m; i++) { + r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu; + *tmpx1++ = (mp_digit)(r & MP_MASK); + mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT)); + } + + /* set final carry */ + *tmpx1++ = mu; + + /* zero words above m */ + for (i = m + 1; i < x->used; i++) { + *tmpx1++ = 0; + } + + /* clamp, sub and return */ + mp_clamp (x); + + /* if x >= n then subtract and reduce again + * Each successive "recursion" makes the input smaller and smaller. + */ + if (mp_cmp_mag (x, n) != MP_LT) { + s_mp_sub(x, n, x); + goto top; + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_dr_reduce.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_dr_setup.c b/lib/hcrypto/libtommath/bn_mp_dr_setup.c new file mode 100644 index 000000000..1d7d856ef --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_dr_setup.c @@ -0,0 +1,32 @@ +#include +#ifdef BN_MP_DR_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines the setup value */ +void mp_dr_setup(mp_int *a, mp_digit *d) +{ + /* the casts are required if DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. DIGIT_BIT==31] + */ + *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - + ((mp_word)a->dp[0])); +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_dr_setup.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_exch.c b/lib/hcrypto/libtommath/bn_mp_exch.c new file mode 100644 index 000000000..38574e0a5 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_exch.c @@ -0,0 +1,34 @@ +#include +#ifdef BN_MP_EXCH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* swap the elements of two integers, for cases where you can't simply swap the + * mp_int pointers around + */ +void +mp_exch (mp_int * a, mp_int * b) +{ + mp_int t; + + t = *a; + *a = *b; + *b = t; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_exch.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_expt_d.c b/lib/hcrypto/libtommath/bn_mp_expt_d.c new file mode 100644 index 000000000..4bdc2d13a --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_expt_d.c @@ -0,0 +1,57 @@ +#include +#ifdef BN_MP_EXPT_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* calculate c = a**b using a square-multiply algorithm */ +int mp_expt_d (mp_int * a, mp_digit b, mp_int * c) +{ + int res, x; + mp_int g; + + if ((res = mp_init_copy (&g, a)) != MP_OKAY) { + return res; + } + + /* set initial result */ + mp_set (c, 1); + + for (x = 0; x < (int) DIGIT_BIT; x++) { + /* square */ + if ((res = mp_sqr (c, c)) != MP_OKAY) { + mp_clear (&g); + return res; + } + + /* if the bit is set multiply */ + if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) { + if ((res = mp_mul (c, &g, c)) != MP_OKAY) { + mp_clear (&g); + return res; + } + } + + /* shift to next bit */ + b <<= 1; + } + + mp_clear (&g); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_expt_d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_exptmod.c b/lib/hcrypto/libtommath/bn_mp_exptmod.c new file mode 100644 index 000000000..023191657 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_exptmod.c @@ -0,0 +1,112 @@ +#include +#ifdef BN_MP_EXPTMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + + +/* this is a shell function that calls either the normal or Montgomery + * exptmod functions. Originally the call to the montgomery code was + * embedded in the normal function but that wasted alot of stack space + * for nothing (since 99% of the time the Montgomery code would be called) + */ +int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + int dr; + + /* modulus P must be positive */ + if (P->sign == MP_NEG) { + return MP_VAL; + } + + /* if exponent X is negative we have to recurse */ + if (X->sign == MP_NEG) { +#ifdef BN_MP_INVMOD_C + mp_int tmpG, tmpX; + int err; + + /* first compute 1/G mod P */ + if ((err = mp_init(&tmpG)) != MP_OKAY) { + return err; + } + if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { + mp_clear(&tmpG); + return err; + } + + /* now get |X| */ + if ((err = mp_init(&tmpX)) != MP_OKAY) { + mp_clear(&tmpG); + return err; + } + if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; + } + + /* and now compute (1/G)**|X| instead of G**X [X < 0] */ + err = mp_exptmod(&tmpG, &tmpX, P, Y); + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; +#else + /* no invmod */ + return MP_VAL; +#endif + } + +/* modified diminished radix reduction */ +#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C) + if (mp_reduce_is_2k_l(P) == MP_YES) { + return s_mp_exptmod(G, X, P, Y, 1); + } +#endif + +#ifdef BN_MP_DR_IS_MODULUS_C + /* is it a DR modulus? */ + dr = mp_dr_is_modulus(P); +#else + /* default to no */ + dr = 0; +#endif + +#ifdef BN_MP_REDUCE_IS_2K_C + /* if not, is it a unrestricted DR modulus? */ + if (dr == 0) { + dr = mp_reduce_is_2k(P) << 1; + } +#endif + + /* if the modulus is odd or dr != 0 use the montgomery method */ +#ifdef BN_MP_EXPTMOD_FAST_C + if (mp_isodd (P) == 1 || dr != 0) { + return mp_exptmod_fast (G, X, P, Y, dr); + } else { +#endif +#ifdef BN_S_MP_EXPTMOD_C + /* otherwise use the generic Barrett reduction technique */ + return s_mp_exptmod (G, X, P, Y, 0); +#else + /* no exptmod for evens */ + return MP_VAL; +#endif +#ifdef BN_MP_EXPTMOD_FAST_C + } +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_exptmod_fast.c b/lib/hcrypto/libtommath/bn_mp_exptmod_fast.c new file mode 100644 index 000000000..2a3b3c9e8 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_exptmod_fast.c @@ -0,0 +1,321 @@ +#include +#ifdef BN_MP_EXPTMOD_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 + * + * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. + * The value of k changes based on the size of the exponent. + * + * Uses Montgomery or Diminished Radix reduction [whichever appropriate] + */ + +#ifdef MP_LOW_MEM + #define TAB_SIZE 32 +#else + #define TAB_SIZE 256 +#endif + +int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) +{ + mp_int M[TAB_SIZE], res; + mp_digit buf, mp; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + + /* use a pointer to the reduction algorithm. This allows us to use + * one of many reduction algorithms without modding the guts of + * the code with if statements everywhere. + */ + int (*redux)(mp_int*,mp_int*,mp_digit); + + /* find window size */ + x = mp_count_bits (X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + +#ifdef MP_LOW_MEM + if (winsize > 5) { + winsize = 5; + } +#endif + + /* init M array */ + /* init first cell */ + if ((err = mp_init(&M[1])) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init(&M[x])) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear (&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* determine and setup reduction code */ + if (redmode == 0) { +#ifdef BN_MP_MONTGOMERY_SETUP_C + /* now setup montgomery */ + if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { + goto LBL_M; + } +#else + err = MP_VAL; + goto LBL_M; +#endif + + /* automatically pick the comba one if available (saves quite a few calls/ifs) */ +#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C + if (((P->used * 2 + 1) < MP_WARRAY) && + P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + redux = fast_mp_montgomery_reduce; + } else +#endif + { +#ifdef BN_MP_MONTGOMERY_REDUCE_C + /* use slower baseline Montgomery method */ + redux = mp_montgomery_reduce; +#else + err = MP_VAL; + goto LBL_M; +#endif + } + } else if (redmode == 1) { +#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C) + /* setup DR reduction for moduli of the form B**k - b */ + mp_dr_setup(P, &mp); + redux = mp_dr_reduce; +#else + err = MP_VAL; + goto LBL_M; +#endif + } else { +#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) + /* setup DR reduction for moduli of the form 2**k - b */ + if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { + goto LBL_M; + } + redux = mp_reduce_2k; +#else + err = MP_VAL; + goto LBL_M; +#endif + } + + /* setup result */ + if ((err = mp_init (&res)) != MP_OKAY) { + goto LBL_M; + } + + /* create M table + * + + * + * The first half of the table is not computed though accept for M[0] and M[1] + */ + + if (redmode == 0) { +#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { + goto LBL_RES; + } +#else + err = MP_VAL; + goto LBL_RES; +#endif + + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { + goto LBL_RES; + } + } else { + mp_set(&res, 1); + if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { + goto LBL_RES; + } + } + + /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ + if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto LBL_RES; + } + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&M[x], P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* then multiply */ + if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + + /* get next bit of the window */ + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + } + } + + if (redmode == 0) { + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ + if ((err = redux(&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* swap res with Y */ + mp_exch (&res, Y); + err = MP_OKAY; +LBL_RES:mp_clear (&res); +LBL_M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear (&M[x]); + } + return err; +} +#endif + + +/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod_fast.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_exteuclid.c b/lib/hcrypto/libtommath/bn_mp_exteuclid.c new file mode 100644 index 000000000..e6c4ce2b8 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_exteuclid.c @@ -0,0 +1,82 @@ +#include +#ifdef BN_MP_EXTEUCLID_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Extended euclidean algorithm of (a, b) produces + a*u1 + b*u2 = u3 + */ +int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) +{ + mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp; + int err; + + if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { + return err; + } + + /* initialize, (u1,u2,u3) = (1,0,a) */ + mp_set(&u1, 1); + if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; } + + /* initialize, (v1,v2,v3) = (0,1,b) */ + mp_set(&v2, 1); + if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; } + + /* loop while v3 != 0 */ + while (mp_iszero(&v3) == MP_NO) { + /* q = u3/v3 */ + if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; } + + /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ + if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; } + if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; } + if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; } + if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; } + if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; } + if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; } + + /* (u1,u2,u3) = (v1,v2,v3) */ + if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; } + + /* (v1,v2,v3) = (t1,t2,t3) */ + if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; } + } + + /* make sure U3 >= 0 */ + if (u3.sign == MP_NEG) { + mp_neg(&u1, &u1); + mp_neg(&u2, &u2); + mp_neg(&u3, &u3); + } + + /* copy result out */ + if (U1 != NULL) { mp_exch(U1, &u1); } + if (U2 != NULL) { mp_exch(U2, &u2); } + if (U3 != NULL) { mp_exch(U3, &u3); } + + err = MP_OKAY; +_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_exteuclid.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_fread.c b/lib/hcrypto/libtommath/bn_mp_fread.c new file mode 100644 index 000000000..b344b6f05 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_fread.c @@ -0,0 +1,67 @@ +#include +#ifdef BN_MP_FREAD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* read a bigint from a file stream in ASCII */ +int mp_fread(mp_int *a, int radix, FILE *stream) +{ + int err, ch, neg, y; + + /* clear a */ + mp_zero(a); + + /* if first digit is - then set negative */ + ch = fgetc(stream); + if (ch == '-') { + neg = MP_NEG; + ch = fgetc(stream); + } else { + neg = MP_ZPOS; + } + + for (;;) { + /* find y in the radix map */ + for (y = 0; y < radix; y++) { + if (mp_s_rmap[y] == ch) { + break; + } + } + if (y == radix) { + break; + } + + /* shift up and add */ + if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, y, a)) != MP_OKAY) { + return err; + } + + ch = fgetc(stream); + } + if (mp_cmp_d(a, 0) != MP_EQ) { + a->sign = neg; + } + + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_fread.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_fwrite.c b/lib/hcrypto/libtommath/bn_mp_fwrite.c new file mode 100644 index 000000000..a0b4c6b6d --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_fwrite.c @@ -0,0 +1,52 @@ +#include +#ifdef BN_MP_FWRITE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +int mp_fwrite(mp_int *a, int radix, FILE *stream) +{ + char *buf; + int err, len, x; + + if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) { + return err; + } + + buf = OPT_CAST(char) XMALLOC (len); + if (buf == NULL) { + return MP_MEM; + } + + if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) { + XFREE (buf); + return err; + } + + for (x = 0; x < len; x++) { + if (fputc(buf[x], stream) == EOF) { + XFREE (buf); + return MP_VAL; + } + } + + XFREE (buf); + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_fwrite.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_gcd.c b/lib/hcrypto/libtommath/bn_mp_gcd.c new file mode 100644 index 000000000..b39ba9041 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_gcd.c @@ -0,0 +1,105 @@ +#include +#ifdef BN_MP_GCD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Greatest Common Divisor using the binary method */ +int mp_gcd (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int u, v; + int k, u_lsb, v_lsb, res; + + /* either zero than gcd is the largest */ + if (mp_iszero (a) == MP_YES) { + return mp_abs (b, c); + } + if (mp_iszero (b) == MP_YES) { + return mp_abs (a, c); + } + + /* get copies of a and b we can modify */ + if ((res = mp_init_copy (&u, a)) != MP_OKAY) { + return res; + } + + if ((res = mp_init_copy (&v, b)) != MP_OKAY) { + goto LBL_U; + } + + /* must be positive for the remainder of the algorithm */ + u.sign = v.sign = MP_ZPOS; + + /* B1. Find the common power of two for u and v */ + u_lsb = mp_cnt_lsb(&u); + v_lsb = mp_cnt_lsb(&v); + k = MIN(u_lsb, v_lsb); + + if (k > 0) { + /* divide the power of two out */ + if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + + if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* divide any remaining factors of two out */ + if (u_lsb != k) { + if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + if (v_lsb != k) { + if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + while (mp_iszero(&v) == 0) { + /* make sure v is the largest */ + if (mp_cmp_mag(&u, &v) == MP_GT) { + /* swap u and v to make sure v is >= u */ + mp_exch(&u, &v); + } + + /* subtract smallest from largest */ + if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) { + goto LBL_V; + } + + /* Divide out all factors of two */ + if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* multiply by 2**k which we divided out at the beginning */ + if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) { + goto LBL_V; + } + c->sign = MP_ZPOS; + res = MP_OKAY; +LBL_V:mp_clear (&u); +LBL_U:mp_clear (&v); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_gcd.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_get_int.c b/lib/hcrypto/libtommath/bn_mp_get_int.c new file mode 100644 index 000000000..17162e2bf --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_get_int.c @@ -0,0 +1,45 @@ +#include +#ifdef BN_MP_GET_INT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* get the lower 32-bits of an mp_int */ +unsigned long mp_get_int(mp_int * a) +{ + int i; + unsigned long res; + + if (a->used == 0) { + return 0; + } + + /* get number of digits of the lsb we have to read */ + i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1; + + /* get most significant digit of result */ + res = DIGIT(a,i); + + while (--i >= 0) { + res = (res << DIGIT_BIT) | DIGIT(a,i); + } + + /* force result to 32-bits always so it is consistent on non 32-bit platforms */ + return res & 0xFFFFFFFFUL; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_get_int.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_grow.c b/lib/hcrypto/libtommath/bn_mp_grow.c new file mode 100644 index 000000000..cf2b949b2 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_grow.c @@ -0,0 +1,57 @@ +#include +#ifdef BN_MP_GROW_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* grow as required */ +int mp_grow (mp_int * a, int size) +{ + int i; + mp_digit *tmp; + + /* if the alloc size is smaller alloc more ram */ + if (a->alloc < size) { + /* ensure there are always at least MP_PREC digits extra on top */ + size += (MP_PREC * 2) - (size % MP_PREC); + + /* reallocate the array a->dp + * + * We store the return in a temporary variable + * in case the operation failed we don't want + * to overwrite the dp member of a. + */ + tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size); + if (tmp == NULL) { + /* reallocation failed but "a" is still valid [can be freed] */ + return MP_MEM; + } + + /* reallocation succeeded so set a->dp */ + a->dp = tmp; + + /* zero excess digits */ + i = a->alloc; + a->alloc = size; + for (; i < a->alloc; i++) { + a->dp[i] = 0; + } + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_grow.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init.c b/lib/hcrypto/libtommath/bn_mp_init.c new file mode 100644 index 000000000..8be27f569 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init.c @@ -0,0 +1,46 @@ +#include +#ifdef BN_MP_INIT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* init a new mp_int */ +int mp_init (mp_int * a) +{ + int i; + + /* allocate memory required and clear it */ + a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the digits to zero */ + for (i = 0; i < MP_PREC; i++) { + a->dp[i] = 0; + } + + /* set the used to zero, allocated digits to the default precision + * and sign to positive */ + a->used = 0; + a->alloc = MP_PREC; + a->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_copy.c b/lib/hcrypto/libtommath/bn_mp_init_copy.c new file mode 100644 index 000000000..0160811af --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_copy.c @@ -0,0 +1,32 @@ +#include +#ifdef BN_MP_INIT_COPY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* creates "a" then copies b into it */ +int mp_init_copy (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_init (a)) != MP_OKAY) { + return res; + } + return mp_copy (b, a); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init_copy.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_multi.c b/lib/hcrypto/libtommath/bn_mp_init_multi.c new file mode 100644 index 000000000..59dc3a9ea --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_multi.c @@ -0,0 +1,59 @@ +#include +#ifdef BN_MP_INIT_MULTI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include + +int mp_init_multi(mp_int *mp, ...) +{ + mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ + int n = 0; /* Number of ok inits */ + mp_int* cur_arg = mp; + va_list args; + + va_start(args, mp); /* init args to next argument from caller */ + while (cur_arg != NULL) { + if (mp_init(cur_arg) != MP_OKAY) { + /* Oops - error! Back-track and mp_clear what we already + succeeded in init-ing, then return error. + */ + va_list clean_args; + + /* end the current list */ + va_end(args); + + /* now start cleaning up */ + cur_arg = mp; + va_start(clean_args, mp); + while (n--) { + mp_clear(cur_arg); + cur_arg = va_arg(clean_args, mp_int*); + } + va_end(clean_args); + res = MP_MEM; + break; + } + n++; + cur_arg = va_arg(args, mp_int*); + } + va_end(args); + return res; /* Assumed ok, if error flagged above. */ +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init_multi.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_set.c b/lib/hcrypto/libtommath/bn_mp_init_set.c new file mode 100644 index 000000000..34edad92f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_set.c @@ -0,0 +1,32 @@ +#include +#ifdef BN_MP_INIT_SET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* initialize and set a digit */ +int mp_init_set (mp_int * a, mp_digit b) +{ + int err; + if ((err = mp_init(a)) != MP_OKAY) { + return err; + } + mp_set(a, b); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init_set.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_set_int.c b/lib/hcrypto/libtommath/bn_mp_init_set_int.c new file mode 100644 index 000000000..5c5599315 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_set_int.c @@ -0,0 +1,31 @@ +#include +#ifdef BN_MP_INIT_SET_INT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* initialize and set a digit */ +int mp_init_set_int (mp_int * a, unsigned long b) +{ + int err; + if ((err = mp_init(a)) != MP_OKAY) { + return err; + } + return mp_set_int(a, b); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init_set_int.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_size.c b/lib/hcrypto/libtommath/bn_mp_init_size.c new file mode 100644 index 000000000..8e014183a --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_size.c @@ -0,0 +1,48 @@ +#include +#ifdef BN_MP_INIT_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* init an mp_init for a given size */ +int mp_init_size (mp_int * a, int size) +{ + int x; + + /* pad size so there are always extra digits */ + size += (MP_PREC * 2) - (size % MP_PREC); + + /* alloc mem */ + a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the members */ + a->used = 0; + a->alloc = size; + a->sign = MP_ZPOS; + + /* zero the digits */ + for (x = 0; x < size; x++) { + a->dp[x] = 0; + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init_size.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_invmod.c b/lib/hcrypto/libtommath/bn_mp_invmod.c new file mode 100644 index 000000000..154651468 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_invmod.c @@ -0,0 +1,43 @@ +#include +#ifdef BN_MP_INVMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* hac 14.61, pp608 */ +int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + /* b cannot be negative */ + if (b->sign == MP_NEG || mp_iszero(b) == 1) { + return MP_VAL; + } + +#ifdef BN_FAST_MP_INVMOD_C + /* if the modulus is odd we can use a faster routine instead */ + if (mp_isodd (b) == 1) { + return fast_mp_invmod (a, b, c); + } +#endif + +#ifdef BN_MP_INVMOD_SLOW_C + return mp_invmod_slow(a, b, c); +#endif + + return MP_VAL; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_invmod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_invmod_slow.c b/lib/hcrypto/libtommath/bn_mp_invmod_slow.c new file mode 100644 index 000000000..eedd47dcf --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_invmod_slow.c @@ -0,0 +1,175 @@ +#include +#ifdef BN_MP_INVMOD_SLOW_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* hac 14.61, pp608 */ +int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x, y, u, v, A, B, C, D; + int res; + + /* b cannot be negative */ + if (b->sign == MP_NEG || mp_iszero(b) == 1) { + return MP_VAL; + } + + /* init temps */ + if ((res = mp_init_multi(&x, &y, &u, &v, + &A, &B, &C, &D, NULL)) != MP_OKAY) { + return res; + } + + /* x = a, y = b */ + if ((res = mp_mod(a, b, &x)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_copy (b, &y)) != MP_OKAY) { + goto LBL_ERR; + } + + /* 2. [modified] if x,y are both even then return an error! */ + if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { + res = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = mp_copy (&x, &u)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_copy (&y, &v)) != MP_OKAY) { + goto LBL_ERR; + } + mp_set (&A, 1); + mp_set (&D, 1); + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto LBL_ERR; + } + /* 4.2 if A or B is odd then */ + if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* A = A/2, B = B/2 */ + if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 5. while v is even do */ + while (mp_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto LBL_ERR; + } + /* 5.2 if C or D is odd then */ + if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* C = C/2, D = D/2 */ + if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 6. if u >= v then */ + if (mp_cmp (&u, &v) != MP_LT) { + /* u = u - v, A = A - C, B = B - D */ + if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* if not zero goto step 4 */ + if (mp_iszero (&u) == 0) + goto top; + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d (&v, 1) != MP_EQ) { + res = MP_VAL; + goto LBL_ERR; + } + + /* if its too low */ + while (mp_cmp_d(&C, 0) == MP_LT) { + if ((res = mp_add(&C, b, &C)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* too big */ + while (mp_cmp_mag(&C, b) != MP_LT) { + if ((res = mp_sub(&C, b, &C)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* C is now the inverse */ + mp_exch (&C, c); + res = MP_OKAY; +LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_invmod_slow.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_is_square.c b/lib/hcrypto/libtommath/bn_mp_is_square.c new file mode 100644 index 000000000..50c524444 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_is_square.c @@ -0,0 +1,109 @@ +#include +#ifdef BN_MP_IS_SQUARE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Check if remainders are possible squares - fast exclude non-squares */ +static const char rem_128[128] = { + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 +}; + +static const char rem_105[105] = { + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 +}; + +/* Store non-zero to ret if arg is square, and zero if not */ +int mp_is_square(mp_int *arg,int *ret) +{ + int res; + mp_digit c; + mp_int t; + unsigned long r; + + /* Default to Non-square :) */ + *ret = MP_NO; + + if (arg->sign == MP_NEG) { + return MP_VAL; + } + + /* digits used? (TSD) */ + if (arg->used == 0) { + return MP_OKAY; + } + + /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */ + if (rem_128[127 & DIGIT(arg,0)] == 1) { + return MP_OKAY; + } + + /* Next check mod 105 (3*5*7) */ + if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) { + return res; + } + if (rem_105[c] == 1) { + return MP_OKAY; + } + + + if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) { + return res; + } + if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) { + goto ERR; + } + r = mp_get_int(&t); + /* Check for other prime modules, note it's not an ERROR but we must + * free "t" so the easiest way is to goto ERR. We know that res + * is already equal to MP_OKAY from the mp_mod call + */ + if ( (1L<<(r%11)) & 0x5C4L ) goto ERR; + if ( (1L<<(r%13)) & 0x9E4L ) goto ERR; + if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR; + if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR; + if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR; + if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR; + if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR; + + /* Final check - is sqr(sqrt(arg)) == arg ? */ + if ((res = mp_sqrt(arg,&t)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sqr(&t,&t)) != MP_OKAY) { + goto ERR; + } + + *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO; +ERR:mp_clear(&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_is_square.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_jacobi.c b/lib/hcrypto/libtommath/bn_mp_jacobi.c new file mode 100644 index 000000000..91cfeeade --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_jacobi.c @@ -0,0 +1,105 @@ +#include +#ifdef BN_MP_JACOBI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes the jacobi c = (a | n) (or Legendre if n is prime) + * HAC pp. 73 Algorithm 2.149 + */ +int mp_jacobi (mp_int * a, mp_int * p, int *c) +{ + mp_int a1, p1; + int k, s, r, res; + mp_digit residue; + + /* if p <= 0 return MP_VAL */ + if (mp_cmp_d(p, 0) != MP_GT) { + return MP_VAL; + } + + /* step 1. if a == 0, return 0 */ + if (mp_iszero (a) == 1) { + *c = 0; + return MP_OKAY; + } + + /* step 2. if a == 1, return 1 */ + if (mp_cmp_d (a, 1) == MP_EQ) { + *c = 1; + return MP_OKAY; + } + + /* default */ + s = 0; + + /* step 3. write a = a1 * 2**k */ + if ((res = mp_init_copy (&a1, a)) != MP_OKAY) { + return res; + } + + if ((res = mp_init (&p1)) != MP_OKAY) { + goto LBL_A1; + } + + /* divide out larger power of two */ + k = mp_cnt_lsb(&a1); + if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) { + goto LBL_P1; + } + + /* step 4. if e is even set s=1 */ + if ((k & 1) == 0) { + s = 1; + } else { + /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */ + residue = p->dp[0] & 7; + + if (residue == 1 || residue == 7) { + s = 1; + } else if (residue == 3 || residue == 5) { + s = -1; + } + } + + /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */ + if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) { + s = -s; + } + + /* if a1 == 1 we're done */ + if (mp_cmp_d (&a1, 1) == MP_EQ) { + *c = s; + } else { + /* n1 = n mod a1 */ + if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) { + goto LBL_P1; + } + if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) { + goto LBL_P1; + } + *c = s * r; + } + + /* done */ + res = MP_OKAY; +LBL_P1:mp_clear (&p1); +LBL_A1:mp_clear (&a1); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_jacobi.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c b/lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c new file mode 100644 index 000000000..8ea2c2792 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c @@ -0,0 +1,167 @@ +#include +#ifdef BN_MP_KARATSUBA_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* c = |a| * |b| using Karatsuba Multiplication using + * three half size multiplications + * + * Let B represent the radix [e.g. 2**DIGIT_BIT] and + * let n represent half of the number of digits in + * the min(a,b) + * + * a = a1 * B**n + a0 + * b = b1 * B**n + b0 + * + * Then, a * b => + a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0 + * + * Note that a1b1 and a0b0 are used twice and only need to be + * computed once. So in total three half size (half # of + * digit) multiplications are performed, a0b0, a1b1 and + * (a1+b1)(a0+b0) + * + * Note that a multiplication of half the digits requires + * 1/4th the number of single precision multiplications so in + * total after one call 25% of the single precision multiplications + * are saved. Note also that the call to mp_mul can end up back + * in this function if the a0, a1, b0, or b1 are above the threshold. + * This is known as divide-and-conquer and leads to the famous + * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than + * the standard O(N**2) that the baseline/comba methods use. + * Generally though the overhead of this method doesn't pay off + * until a certain size (N ~ 80) is reached. + */ +int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x0, x1, y0, y1, t1, x0y0, x1y1; + int B, err; + + /* default the return code to an error */ + err = MP_MEM; + + /* min # of digits */ + B = MIN (a->used, b->used); + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if (mp_init_size (&x0, B) != MP_OKAY) + goto ERR; + if (mp_init_size (&x1, a->used - B) != MP_OKAY) + goto X0; + if (mp_init_size (&y0, B) != MP_OKAY) + goto X1; + if (mp_init_size (&y1, b->used - B) != MP_OKAY) + goto Y0; + + /* init temps */ + if (mp_init_size (&t1, B * 2) != MP_OKAY) + goto Y1; + if (mp_init_size (&x0y0, B * 2) != MP_OKAY) + goto T1; + if (mp_init_size (&x1y1, B * 2) != MP_OKAY) + goto X0Y0; + + /* now shift the digits */ + x0.used = y0.used = B; + x1.used = a->used - B; + y1.used = b->used - B; + + { + register int x; + register mp_digit *tmpa, *tmpb, *tmpx, *tmpy; + + /* we copy the digits directly instead of using higher level functions + * since we also need to shift the digits + */ + tmpa = a->dp; + tmpb = b->dp; + + tmpx = x0.dp; + tmpy = y0.dp; + for (x = 0; x < B; x++) { + *tmpx++ = *tmpa++; + *tmpy++ = *tmpb++; + } + + tmpx = x1.dp; + for (x = B; x < a->used; x++) { + *tmpx++ = *tmpa++; + } + + tmpy = y1.dp; + for (x = B; x < b->used; x++) { + *tmpy++ = *tmpb++; + } + } + + /* only need to clamp the lower words since by definition the + * upper words x1/y1 must have a known number of digits + */ + mp_clamp (&x0); + mp_clamp (&y0); + + /* now calc the products x0y0 and x1y1 */ + /* after this x0 is no longer required, free temp [x0==t2]! */ + if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY) + goto X1Y1; /* x0y0 = x0*y0 */ + if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY) + goto X1Y1; /* x1y1 = x1*y1 */ + + /* now calc x1+x0 and y1+y0 */ + if (s_mp_add (&x1, &x0, &t1) != MP_OKAY) + goto X1Y1; /* t1 = x1 - x0 */ + if (s_mp_add (&y1, &y0, &x0) != MP_OKAY) + goto X1Y1; /* t2 = y1 - y0 */ + if (mp_mul (&t1, &x0, &t1) != MP_OKAY) + goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */ + + /* add x0y0 */ + if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY) + goto X1Y1; /* t2 = x0y0 + x1y1 */ + if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY) + goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */ + + /* shift by B */ + if (mp_lshd (&t1, B) != MP_OKAY) + goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))< +#ifdef BN_MP_KARATSUBA_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Karatsuba squaring, computes b = a*a using three + * half size squarings + * + * See comments of karatsuba_mul for details. It + * is essentially the same algorithm but merely + * tuned to perform recursive squarings. + */ +int mp_karatsuba_sqr (mp_int * a, mp_int * b) +{ + mp_int x0, x1, t1, t2, x0x0, x1x1; + int B, err; + + err = MP_MEM; + + /* min # of digits */ + B = a->used; + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if (mp_init_size (&x0, B) != MP_OKAY) + goto ERR; + if (mp_init_size (&x1, a->used - B) != MP_OKAY) + goto X0; + + /* init temps */ + if (mp_init_size (&t1, a->used * 2) != MP_OKAY) + goto X1; + if (mp_init_size (&t2, a->used * 2) != MP_OKAY) + goto T1; + if (mp_init_size (&x0x0, B * 2) != MP_OKAY) + goto T2; + if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY) + goto X0X0; + + { + register int x; + register mp_digit *dst, *src; + + src = a->dp; + + /* now shift the digits */ + dst = x0.dp; + for (x = 0; x < B; x++) { + *dst++ = *src++; + } + + dst = x1.dp; + for (x = B; x < a->used; x++) { + *dst++ = *src++; + } + } + + x0.used = B; + x1.used = a->used - B; + + mp_clamp (&x0); + + /* now calc the products x0*x0 and x1*x1 */ + if (mp_sqr (&x0, &x0x0) != MP_OKAY) + goto X1X1; /* x0x0 = x0*x0 */ + if (mp_sqr (&x1, &x1x1) != MP_OKAY) + goto X1X1; /* x1x1 = x1*x1 */ + + /* now calc (x1+x0)**2 */ + if (s_mp_add (&x1, &x0, &t1) != MP_OKAY) + goto X1X1; /* t1 = x1 - x0 */ + if (mp_sqr (&t1, &t1) != MP_OKAY) + goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */ + + /* add x0y0 */ + if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY) + goto X1X1; /* t2 = x0x0 + x1x1 */ + if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY) + goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */ + + /* shift by B */ + if (mp_lshd (&t1, B) != MP_OKAY) + goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))< +#ifdef BN_MP_LCM_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes least common multiple as |a*b|/(a, b) */ +int mp_lcm (mp_int * a, mp_int * b, mp_int * c) +{ + int res; + mp_int t1, t2; + + + if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) { + return res; + } + + /* t1 = get the GCD of the two inputs */ + if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) { + goto LBL_T; + } + + /* divide the smallest by the GCD */ + if (mp_cmp_mag(a, b) == MP_LT) { + /* store quotient in t2 such that t2 * b is the LCM */ + if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + res = mp_mul(b, &t2, c); + } else { + /* store quotient in t2 such that t2 * a is the LCM */ + if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + res = mp_mul(a, &t2, c); + } + + /* fix the sign to positive */ + c->sign = MP_ZPOS; + +LBL_T: + mp_clear_multi (&t1, &t2, NULL); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_lcm.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_lshd.c b/lib/hcrypto/libtommath/bn_mp_lshd.c new file mode 100644 index 000000000..f118cf1ae --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_lshd.c @@ -0,0 +1,67 @@ +#include +#ifdef BN_MP_LSHD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* shift left a certain amount of digits */ +int mp_lshd (mp_int * a, int b) +{ + int x, res; + + /* if its less than zero return */ + if (b <= 0) { + return MP_OKAY; + } + + /* grow to fit the new digits */ + if (a->alloc < a->used + b) { + if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { + return res; + } + } + + { + register mp_digit *top, *bottom; + + /* increment the used by the shift amount then copy upwards */ + a->used += b; + + /* top */ + top = a->dp + a->used - 1; + + /* base */ + bottom = a->dp + a->used - 1 - b; + + /* much like mp_rshd this is implemented using a sliding window + * except the window goes the otherway around. Copying from + * the bottom to the top. see bn_mp_rshd.c for more info. + */ + for (x = a->used - 1; x >= b; x--) { + *top-- = *bottom--; + } + + /* zero the lower digits */ + top = a->dp; + for (x = 0; x < b; x++) { + *top++ = 0; + } + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_lshd.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mod.c b/lib/hcrypto/libtommath/bn_mp_mod.c new file mode 100644 index 000000000..f5cf8d09f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_mod.c @@ -0,0 +1,48 @@ +#include +#ifdef BN_MP_MOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* c = a mod b, 0 <= c < b */ +int +mp_mod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int t; + int res; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + if (t.sign != b->sign) { + res = mp_add (b, &t, c); + } else { + res = MP_OKAY; + mp_exch (&t, c); + } + + mp_clear (&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mod_2d.c b/lib/hcrypto/libtommath/bn_mp_mod_2d.c new file mode 100644 index 000000000..e194a0687 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_mod_2d.c @@ -0,0 +1,55 @@ +#include +#ifdef BN_MP_MOD_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* calc a value mod 2**b */ +int +mp_mod_2d (mp_int * a, int b, mp_int * c) +{ + int x, res; + + /* if b is <= 0 then zero the int */ + if (b <= 0) { + mp_zero (c); + return MP_OKAY; + } + + /* if the modulus is larger than the value than return */ + if (b >= (int) (a->used * DIGIT_BIT)) { + res = mp_copy (a, c); + return res; + } + + /* copy */ + if ((res = mp_copy (a, c)) != MP_OKAY) { + return res; + } + + /* zero digits above the last digit of the modulus */ + for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { + c->dp[x] = 0; + } + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / DIGIT_BIT] &= + (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); + mp_clamp (c); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mod_2d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mod_d.c b/lib/hcrypto/libtommath/bn_mp_mod_d.c new file mode 100644 index 000000000..9ca37e673 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_mod_d.c @@ -0,0 +1,27 @@ +#include +#ifdef BN_MP_MOD_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +int +mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) +{ + return mp_div_d(a, b, NULL, c); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mod_d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c b/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c new file mode 100644 index 000000000..c669fe0ec --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c @@ -0,0 +1,59 @@ +#include +#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* + * shifts with subtractions when the result is greater than b. + * + * The method is slightly modified to shift B unconditionally upto just under + * the leading bit of b. This saves alot of multiple precision shifting. + */ +int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) +{ + int x, bits, res; + + /* how many bits of last digit does b use */ + bits = mp_count_bits (b) % DIGIT_BIT; + + if (b->used > 1) { + if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { + return res; + } + } else { + mp_set(a, 1); + bits = 1; + } + + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int)DIGIT_BIT; x++) { + if ((res = mp_mul_2 (a, a)) != MP_OKAY) { + return res; + } + if (mp_cmp_mag (a, b) != MP_LT) { + if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { + return res; + } + } + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_calc_normalization.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c b/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c new file mode 100644 index 000000000..b76509051 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c @@ -0,0 +1,118 @@ +#include +#ifdef BN_MP_MONTGOMERY_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes xR**-1 == x (mod N) via Montgomery Reduction */ +int +mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +{ + int ix, res, digs; + mp_digit mu; + + /* can the fast reduction [comba] method be used? + * + * Note that unlike in mul you're safely allowed *less* + * than the available columns [255 per default] since carries + * are fixed up in the inner loop. + */ + digs = n->used * 2 + 1; + if ((digs < MP_WARRAY) && + n->used < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_mp_montgomery_reduce (x, n, rho); + } + + /* grow the input as required */ + if (x->alloc < digs) { + if ((res = mp_grow (x, digs)) != MP_OKAY) { + return res; + } + } + x->used = digs; + + for (ix = 0; ix < n->used; ix++) { + /* mu = ai * rho mod b + * + * The value of rho must be precalculated via + * montgomery_setup() such that + * it equals -1/n0 mod b this allows the + * following inner loop to reduce the + * input one digit at a time + */ + mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK); + + /* a = a + mu * m * b**i */ + { + register int iy; + register mp_digit *tmpn, *tmpx, u; + register mp_word r; + + /* alias for digits of the modulus */ + tmpn = n->dp; + + /* alias for the digits of x [the input] */ + tmpx = x->dp + ix; + + /* set the carry to zero */ + u = 0; + + /* Multiply and add in place */ + for (iy = 0; iy < n->used; iy++) { + /* compute product and sum */ + r = ((mp_word)mu) * ((mp_word)*tmpn++) + + ((mp_word) u) + ((mp_word) * tmpx); + + /* get carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + + /* fix digit */ + *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK)); + } + /* At this point the ix'th digit of x should be zero */ + + + /* propagate carries upwards as required*/ + while (u) { + *tmpx += u; + u = *tmpx >> DIGIT_BIT; + *tmpx++ &= MP_MASK; + } + } + } + + /* at this point the n.used'th least + * significant digits of x are all zero + * which means we can shift x to the + * right by n.used digits and the + * residue is unchanged. + */ + + /* x = x/b**n.used */ + mp_clamp(x); + mp_rshd (x, n->used); + + /* if x >= n then x = x - n */ + if (mp_cmp_mag (x, n) != MP_LT) { + return s_mp_sub (x, n, x); + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_reduce.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c b/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c new file mode 100644 index 000000000..f08274936 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c @@ -0,0 +1,59 @@ +#include +#ifdef BN_MP_MONTGOMERY_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* setups the montgomery reduction stuff */ +int +mp_montgomery_setup (mp_int * n, mp_digit * rho) +{ + mp_digit x, b; + +/* fast inversion mod 2**k + * + * Based on the fact that + * + * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) + * => 2*X*A - X*X*A*A = 1 + * => 2*(1) - (1) = 1 + */ + b = n->dp[0]; + + if ((b & 1) == 0) { + return MP_VAL; + } + + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ +#if !defined(MP_8BIT) + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ +#endif +#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT)) + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ +#endif +#ifdef MP_64BIT + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ +#endif + + /* rho = -1/m mod b */ + *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK; + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_setup.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mul.c b/lib/hcrypto/libtommath/bn_mp_mul.c new file mode 100644 index 000000000..8b1117a63 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_mul.c @@ -0,0 +1,66 @@ +#include +#ifdef BN_MP_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* high level multiplication (handles sign) */ +int mp_mul (mp_int * a, mp_int * b, mp_int * c) +{ + int res, neg; + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + + /* use Toom-Cook? */ +#ifdef BN_MP_TOOM_MUL_C + if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { + res = mp_toom_mul(a, b, c); + } else +#endif +#ifdef BN_MP_KARATSUBA_MUL_C + /* use Karatsuba? */ + if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { + res = mp_karatsuba_mul (a, b, c); + } else +#endif + { + /* can we use the fast multiplier? + * + * The fast multiplier can be used if the output will + * have less than MP_WARRAY digits and the number of + * digits won't affect carry propagation + */ + int digs = a->used + b->used + 1; + +#ifdef BN_FAST_S_MP_MUL_DIGS_C + if ((digs < MP_WARRAY) && + MIN(a->used, b->used) <= + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + res = fast_s_mp_mul_digs (a, b, c, digs); + } else +#endif +#ifdef BN_S_MP_MUL_DIGS_C + res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */ +#else + res = MP_VAL; +#endif + + } + c->sign = (c->used > 0) ? neg : MP_ZPOS; + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mul.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mul_2.c b/lib/hcrypto/libtommath/bn_mp_mul_2.c new file mode 100644 index 000000000..02455fc35 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_mul_2.c @@ -0,0 +1,82 @@ +#include +#ifdef BN_MP_MUL_2_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* b = a*2 */ +int mp_mul_2(mp_int * a, mp_int * b) +{ + int x, res, oldused; + + /* grow to accomodate result */ + if (b->alloc < a->used + 1) { + if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { + return res; + } + } + + oldused = b->used; + b->used = a->used; + + { + register mp_digit r, rr, *tmpa, *tmpb; + + /* alias for source */ + tmpa = a->dp; + + /* alias for dest */ + tmpb = b->dp; + + /* carry */ + r = 0; + for (x = 0; x < a->used; x++) { + + /* get what will be the *next* carry bit from the + * MSB of the current digit + */ + rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); + + /* now shift up this digit, add in the carry [from the previous] */ + *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; + + /* copy the carry that would be from the source + * digit into the next iteration + */ + r = rr; + } + + /* new leading digit? */ + if (r != 0) { + /* add a MSB which is always 1 at this point */ + *tmpb = 1; + ++(b->used); + } + + /* now zero any excess digits on the destination + * that we didn't write to + */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mul_2d.c b/lib/hcrypto/libtommath/bn_mp_mul_2d.c new file mode 100644 index 000000000..efeff2e75 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_mul_2d.c @@ -0,0 +1,85 @@ +#include +#ifdef BN_MP_MUL_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* shift left by a certain bit count */ +int mp_mul_2d (mp_int * a, int b, mp_int * c) +{ + mp_digit d; + int res; + + /* copy */ + if (a != c) { + if ((res = mp_copy (a, c)) != MP_OKAY) { + return res; + } + } + + if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) { + if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { + return res; + } + } + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { + return res; + } + } + + /* shift any bit count < DIGIT_BIT */ + d = (mp_digit) (b % DIGIT_BIT); + if (d != 0) { + register mp_digit *tmpc, shift, mask, r, rr; + register int x; + + /* bitmask for carries */ + mask = (((mp_digit)1) << d) - 1; + + /* shift for msbs */ + shift = DIGIT_BIT - d; + + /* alias */ + tmpc = c->dp; + + /* carry */ + r = 0; + for (x = 0; x < c->used; x++) { + /* get the higher bits of the current word */ + rr = (*tmpc >> shift) & mask; + + /* shift the current word and OR in the carry */ + *tmpc = ((*tmpc << d) | r) & MP_MASK; + ++tmpc; + + /* set the carry to the carry bits of the current word */ + r = rr; + } + + /* set final carry */ + if (r != 0) { + c->dp[(c->used)++] = r; + } + } + mp_clamp (c); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mul_d.c b/lib/hcrypto/libtommath/bn_mp_mul_d.c new file mode 100644 index 000000000..00f9a899e --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_mul_d.c @@ -0,0 +1,79 @@ +#include +#ifdef BN_MP_MUL_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* multiply by a digit */ +int +mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +{ + mp_digit u, *tmpa, *tmpc; + mp_word r; + int ix, res, olduse; + + /* make sure c is big enough to hold a*b */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* get the original destinations used count */ + olduse = c->used; + + /* set the sign */ + c->sign = a->sign; + + /* alias for a->dp [source] */ + tmpa = a->dp; + + /* alias for c->dp [dest] */ + tmpc = c->dp; + + /* zero carry */ + u = 0; + + /* compute columns */ + for (ix = 0; ix < a->used; ix++) { + /* compute product and carry sum for this term */ + r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b); + + /* mask off higher bits to get a single digit */ + *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* send carry into next iteration */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + + /* store final carry [if any] and increment ix offset */ + *tmpc++ = u; + ++ix; + + /* now zero digits above the top */ + while (ix++ < olduse) { + *tmpc++ = 0; + } + + /* set used count */ + c->used = a->used + 1; + mp_clamp(c); + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mul_d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mulmod.c b/lib/hcrypto/libtommath/bn_mp_mulmod.c new file mode 100644 index 000000000..003ceb9b9 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_mulmod.c @@ -0,0 +1,40 @@ +#include +#ifdef BN_MP_MULMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* d = a * b (mod c) */ +int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_mul (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, c, d); + mp_clear (&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mulmod.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_n_root.c b/lib/hcrypto/libtommath/bn_mp_n_root.c new file mode 100644 index 000000000..0e7bedca7 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_n_root.c @@ -0,0 +1,132 @@ +#include +#ifdef BN_MP_N_ROOT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* find the n'th root of an integer + * + * Result found such that (c)**b <= a and (c+1)**b > a + * + * This algorithm uses Newton's approximation + * x[i+1] = x[i] - f(x[i])/f'(x[i]) + * which will find the root in log(N) time where + * each step involves a fair bit. This is not meant to + * find huge roots [square and cube, etc]. + */ +int mp_n_root (mp_int * a, mp_digit b, mp_int * c) +{ + mp_int t1, t2, t3; + int res, neg; + + /* input must be positive if b is even */ + if ((b & 1) == 0 && a->sign == MP_NEG) { + return MP_VAL; + } + + if ((res = mp_init (&t1)) != MP_OKAY) { + return res; + } + + if ((res = mp_init (&t2)) != MP_OKAY) { + goto LBL_T1; + } + + if ((res = mp_init (&t3)) != MP_OKAY) { + goto LBL_T2; + } + + /* if a is negative fudge the sign but keep track */ + neg = a->sign; + a->sign = MP_ZPOS; + + /* t2 = 2 */ + mp_set (&t2, 2); + + do { + /* t1 = t2 */ + if ((res = mp_copy (&t2, &t1)) != MP_OKAY) { + goto LBL_T3; + } + + /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ + + /* t3 = t1**(b-1) */ + if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) { + goto LBL_T3; + } + + /* numerator */ + /* t2 = t1**b */ + if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) { + goto LBL_T3; + } + + /* t2 = t1**b - a */ + if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) { + goto LBL_T3; + } + + /* denominator */ + /* t3 = t1**(b-1) * b */ + if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) { + goto LBL_T3; + } + + /* t3 = (t1**b - a)/(b * t1**(b-1)) */ + if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) { + goto LBL_T3; + } + + if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) { + goto LBL_T3; + } + } while (mp_cmp (&t1, &t2) != MP_EQ); + + /* result can be off by a few so check */ + for (;;) { + if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) { + goto LBL_T3; + } + + if (mp_cmp (&t2, a) == MP_GT) { + if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) { + goto LBL_T3; + } + } else { + break; + } + } + + /* reset the sign of a first */ + a->sign = neg; + + /* set the result */ + mp_exch (&t1, c); + + /* set the sign of the result */ + c->sign = neg; + + res = MP_OKAY; + +LBL_T3:mp_clear (&t3); +LBL_T2:mp_clear (&t2); +LBL_T1:mp_clear (&t1); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_n_root.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_neg.c b/lib/hcrypto/libtommath/bn_mp_neg.c new file mode 100644 index 000000000..a7d035ab6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_neg.c @@ -0,0 +1,40 @@ +#include +#ifdef BN_MP_NEG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* b = -a */ +int mp_neg (mp_int * a, mp_int * b) +{ + int res; + if (a != b) { + if ((res = mp_copy (a, b)) != MP_OKAY) { + return res; + } + } + + if (mp_iszero(b) != MP_YES) { + b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; + } else { + b->sign = MP_ZPOS; + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_neg.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_or.c b/lib/hcrypto/libtommath/bn_mp_or.c new file mode 100644 index 000000000..bff499548 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_or.c @@ -0,0 +1,50 @@ +#include +#ifdef BN_MP_OR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* OR two ints together */ +int mp_or (mp_int * a, mp_int * b, mp_int * c) +{ + int res, ix, px; + mp_int t, *x; + + if (a->used > b->used) { + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + px = b->used; + x = b; + } else { + if ((res = mp_init_copy (&t, b)) != MP_OKAY) { + return res; + } + px = a->used; + x = a; + } + + for (ix = 0; ix < px; ix++) { + t.dp[ix] |= x->dp[ix]; + } + mp_clamp (&t); + mp_exch (c, &t); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_or.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_fermat.c b/lib/hcrypto/libtommath/bn_mp_prime_fermat.c new file mode 100644 index 000000000..c23d77f6d --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_prime_fermat.c @@ -0,0 +1,62 @@ +#include +#ifdef BN_MP_PRIME_FERMAT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* performs one Fermat test. + * + * If "a" were prime then b**a == b (mod a) since the order of + * the multiplicative sub-group would be phi(a) = a-1. That means + * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a). + * + * Sets result to 1 if the congruence holds, or zero otherwise. + */ +int mp_prime_fermat (mp_int * a, mp_int * b, int *result) +{ + mp_int t; + int err; + + /* default to composite */ + *result = MP_NO; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1) != MP_GT) { + return MP_VAL; + } + + /* init t */ + if ((err = mp_init (&t)) != MP_OKAY) { + return err; + } + + /* compute t = b**a mod a */ + if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) { + goto LBL_T; + } + + /* is it equal to b? */ + if (mp_cmp (&t, b) == MP_EQ) { + *result = MP_YES; + } + + err = MP_OKAY; +LBL_T:mp_clear (&t); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_fermat.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c b/lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c new file mode 100644 index 000000000..8e7871c2c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c @@ -0,0 +1,50 @@ +#include +#ifdef BN_MP_PRIME_IS_DIVISIBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines if an integers is divisible by one + * of the first PRIME_SIZE primes or not + * + * sets result to 0 if not, 1 if yes + */ +int mp_prime_is_divisible (mp_int * a, int *result) +{ + int err, ix; + mp_digit res; + + /* default to not */ + *result = MP_NO; + + for (ix = 0; ix < PRIME_SIZE; ix++) { + /* what is a mod LBL_prime_tab[ix] */ + if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) { + return err; + } + + /* is the residue zero? */ + if (res == 0) { + *result = MP_YES; + return MP_OKAY; + } + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_divisible.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c b/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c new file mode 100644 index 000000000..c316d6210 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c @@ -0,0 +1,83 @@ +#include +#ifdef BN_MP_PRIME_IS_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* performs a variable number of rounds of Miller-Rabin + * + * Probability of error after t rounds is no more than + + * + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime (mp_int * a, int t, int *result) +{ + mp_int b; + int ix, err, res; + + /* default to no */ + *result = MP_NO; + + /* valid value of t? */ + if (t <= 0 || t > PRIME_SIZE) { + return MP_VAL; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < PRIME_SIZE; ix++) { + if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) { + *result = 1; + return MP_OKAY; + } + } + + /* first perform trial division */ + if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res == MP_YES) { + return MP_OKAY; + } + + /* now perform the miller-rabin rounds */ + if ((err = mp_init (&b)) != MP_OKAY) { + return err; + } + + for (ix = 0; ix < t; ix++) { + /* set the prime */ + mp_set (&b, ltm_prime_tab[ix]); + + if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + + if (res == MP_NO) { + goto LBL_B; + } + } + + /* passed the test */ + *result = MP_YES; +LBL_B:mp_clear (&b); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_prime.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c b/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c new file mode 100644 index 000000000..ddf03582a --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c @@ -0,0 +1,103 @@ +#include +#ifdef BN_MP_PRIME_MILLER_RABIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Miller-Rabin test of "a" to the base of "b" as described in + * HAC pp. 139 Algorithm 4.24 + * + * Sets result to 0 if definitely composite or 1 if probably prime. + * Randomly the chance of error is no more than 1/4 and often + * very much lower. + */ +int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result) +{ + mp_int n1, y, r; + int s, j, err; + + /* default */ + *result = MP_NO; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1) != MP_GT) { + return MP_VAL; + } + + /* get n1 = a - 1 */ + if ((err = mp_init_copy (&n1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) { + goto LBL_N1; + } + + /* set 2**s * r = n1 */ + if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) { + goto LBL_N1; + } + + /* count the number of least significant bits + * which are zero + */ + s = mp_cnt_lsb(&r); + + /* now divide n - 1 by 2**s */ + if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) { + goto LBL_R; + } + + /* compute y = b**r mod a */ + if ((err = mp_init (&y)) != MP_OKAY) { + goto LBL_R; + } + if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) { + goto LBL_Y; + } + + /* if y != 1 and y != n1 do */ + if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) { + j = 1; + /* while j <= s-1 and y != n1 */ + while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) { + if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) { + goto LBL_Y; + } + + /* if y == 1 then composite */ + if (mp_cmp_d (&y, 1) == MP_EQ) { + goto LBL_Y; + } + + ++j; + } + + /* if y != n1 then composite */ + if (mp_cmp (&y, &n1) != MP_EQ) { + goto LBL_Y; + } + } + + /* probably prime now */ + *result = MP_YES; +LBL_Y:mp_clear (&y); +LBL_R:mp_clear (&r); +LBL_N1:mp_clear (&n1); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_miller_rabin.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c b/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c new file mode 100644 index 000000000..daf2ec7c6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c @@ -0,0 +1,170 @@ +#include +#ifdef BN_MP_PRIME_NEXT_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + * + * bbs_style = 1 means the prime must be congruent to 3 mod 4 + */ +int mp_prime_next_prime(mp_int *a, int t, int bbs_style) +{ + int err, res, x, y; + mp_digit res_tab[PRIME_SIZE], step, kstep; + mp_int b; + + /* ensure t is valid */ + if (t <= 0 || t > PRIME_SIZE) { + return MP_VAL; + } + + /* force positive */ + a->sign = MP_ZPOS; + + /* simple algo if a is less than the largest prime in the table */ + if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) { + /* find which prime it is bigger than */ + for (x = PRIME_SIZE - 2; x >= 0; x--) { + if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) { + if (bbs_style == 1) { + /* ok we found a prime smaller or + * equal [so the next is larger] + * + * however, the prime must be + * congruent to 3 mod 4 + */ + if ((ltm_prime_tab[x + 1] & 3) != 3) { + /* scan upwards for a prime congruent to 3 mod 4 */ + for (y = x + 1; y < PRIME_SIZE; y++) { + if ((ltm_prime_tab[y] & 3) == 3) { + mp_set(a, ltm_prime_tab[y]); + return MP_OKAY; + } + } + } + } else { + mp_set(a, ltm_prime_tab[x + 1]); + return MP_OKAY; + } + } + } + /* at this point a maybe 1 */ + if (mp_cmp_d(a, 1) == MP_EQ) { + mp_set(a, 2); + return MP_OKAY; + } + /* fall through to the sieve */ + } + + /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */ + if (bbs_style == 1) { + kstep = 4; + } else { + kstep = 2; + } + + /* at this point we will use a combination of a sieve and Miller-Rabin */ + + if (bbs_style == 1) { + /* if a mod 4 != 3 subtract the correct value to make it so */ + if ((a->dp[0] & 3) != 3) { + if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; }; + } + } else { + if (mp_iseven(a) == 1) { + /* force odd */ + if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { + return err; + } + } + } + + /* generate the restable */ + for (x = 1; x < PRIME_SIZE; x++) { + if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) { + return err; + } + } + + /* init temp used for Miller-Rabin Testing */ + if ((err = mp_init(&b)) != MP_OKAY) { + return err; + } + + for (;;) { + /* skip to the next non-trivially divisible candidate */ + step = 0; + do { + /* y == 1 if any residue was zero [e.g. cannot be prime] */ + y = 0; + + /* increase step to next candidate */ + step += kstep; + + /* compute the new residue without using division */ + for (x = 1; x < PRIME_SIZE; x++) { + /* add the step to each residue */ + res_tab[x] += kstep; + + /* subtract the modulus [instead of using division] */ + if (res_tab[x] >= ltm_prime_tab[x]) { + res_tab[x] -= ltm_prime_tab[x]; + } + + /* set flag if zero */ + if (res_tab[x] == 0) { + y = 1; + } + } + } while (y == 1 && step < ((((mp_digit)1)<= ((((mp_digit)1)< +#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + + +static const struct { + int k, t; +} sizes[] = { +{ 128, 28 }, +{ 256, 16 }, +{ 384, 10 }, +{ 512, 7 }, +{ 640, 6 }, +{ 768, 5 }, +{ 896, 4 }, +{ 1024, 4 } +}; + +/* returns # of RM trials required for a given bit size */ +int mp_prime_rabin_miller_trials(int size) +{ + int x; + + for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) { + if (sizes[x].k == size) { + return sizes[x].t; + } else if (sizes[x].k > size) { + return (x == 0) ? sizes[0].t : sizes[x - 1].t; + } + } + return sizes[x-1].t + 1; +} + + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_rabin_miller_trials.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_random_ex.c b/lib/hcrypto/libtommath/bn_mp_prime_random_ex.c new file mode 100644 index 000000000..07aae4b07 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_prime_random_ex.c @@ -0,0 +1,125 @@ +#include +#ifdef BN_MP_PRIME_RANDOM_EX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * LTM_PRIME_BBS - make prime congruent to 3 mod 4 + * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) + * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero + * LTM_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ + +/* This is possibly the mother of all prime generation functions, muahahahahaha! */ +int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat) +{ + unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb; + int res, err, bsize, maskOR_msb_offset; + + /* sanity check the input */ + if (size <= 1 || t <= 0) { + return MP_VAL; + } + + /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */ + if (flags & LTM_PRIME_SAFE) { + flags |= LTM_PRIME_BBS; + } + + /* calc the byte size */ + bsize = (size>>3) + ((size&7)?1:0); + + /* we need a buffer of bsize bytes */ + tmp = OPT_CAST(unsigned char) XMALLOC(bsize); + if (tmp == NULL) { + return MP_MEM; + } + + /* calc the maskAND value for the MSbyte*/ + maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7))); + + /* calc the maskOR_msb */ + maskOR_msb = 0; + maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0; + if (flags & LTM_PRIME_2MSB_ON) { + maskOR_msb |= 0x80 >> ((9 - size) & 7); + } + + /* get the maskOR_lsb */ + maskOR_lsb = 1; + if (flags & LTM_PRIME_BBS) { + maskOR_lsb |= 3; + } + + do { + /* read the bytes */ + if (cb(tmp, bsize, dat) != bsize) { + err = MP_VAL; + goto error; + } + + /* work over the MSbyte */ + tmp[0] &= maskAND; + tmp[0] |= 1 << ((size - 1) & 7); + + /* mix in the maskORs */ + tmp[maskOR_msb_offset] |= maskOR_msb; + tmp[bsize-1] |= maskOR_lsb; + + /* read it in */ + if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; } + if (res == MP_NO) { + continue; + } + + if (flags & LTM_PRIME_SAFE) { + /* see if (a-1)/2 is prime */ + if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; } + if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; } + } + } while (res == MP_NO); + + if (flags & LTM_PRIME_SAFE) { + /* restore a to the original value */ + if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; } + if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; } + } + + err = MP_OKAY; +error: + XFREE(tmp); + return err; +} + + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_random_ex.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_radix_size.c b/lib/hcrypto/libtommath/bn_mp_radix_size.c new file mode 100644 index 000000000..1b61e3a1b --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_radix_size.c @@ -0,0 +1,78 @@ +#include +#ifdef BN_MP_RADIX_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* returns size of ASCII reprensentation */ +int mp_radix_size (mp_int * a, int radix, int *size) +{ + int res, digs; + mp_int t; + mp_digit d; + + *size = 0; + + /* special case for binary */ + if (radix == 2) { + *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; + return MP_OKAY; + } + + /* make sure the radix is in range */ + if (radix < 2 || radix > 64) { + return MP_VAL; + } + + if (mp_iszero(a) == MP_YES) { + *size = 2; + return MP_OKAY; + } + + /* digs is the digit count */ + digs = 0; + + /* if it's negative add one for the sign */ + if (a->sign == MP_NEG) { + ++digs; + } + + /* init a copy of the input */ + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* force temp to positive */ + t.sign = MP_ZPOS; + + /* fetch out all of the digits */ + while (mp_iszero (&t) == MP_NO) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + ++digs; + } + mp_clear (&t); + + /* return digs + 1, the 1 is for the NULL byte that would be required. */ + *size = digs + 1; + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_radix_size.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_radix_smap.c b/lib/hcrypto/libtommath/bn_mp_radix_smap.c new file mode 100644 index 000000000..7d72feb84 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_radix_smap.c @@ -0,0 +1,24 @@ +#include +#ifdef BN_MP_RADIX_SMAP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* chars used in radix conversions */ +const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_radix_smap.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_rand.c b/lib/hcrypto/libtommath/bn_mp_rand.c new file mode 100644 index 000000000..af66a67ee --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_rand.c @@ -0,0 +1,55 @@ +#include +#ifdef BN_MP_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* makes a pseudo-random int of a given size */ +int +mp_rand (mp_int * a, int digits) +{ + int res; + mp_digit d; + + mp_zero (a); + if (digits <= 0) { + return MP_OKAY; + } + + /* first place a random non-zero digit */ + do { + d = ((mp_digit) abs (rand ())) & MP_MASK; + } while (d == 0); + + if ((res = mp_add_d (a, d, a)) != MP_OKAY) { + return res; + } + + while (--digits > 0) { + if ((res = mp_lshd (a, 1)) != MP_OKAY) { + return res; + } + + if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) { + return res; + } + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_rand.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_read_radix.c b/lib/hcrypto/libtommath/bn_mp_read_radix.c new file mode 100644 index 000000000..91c46c22f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_read_radix.c @@ -0,0 +1,85 @@ +#include +#ifdef BN_MP_READ_RADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* read a string [ASCII] in a given radix */ +int mp_read_radix (mp_int * a, const char *str, int radix) +{ + int y, res, neg; + char ch; + + /* zero the digit bignum */ + mp_zero(a); + + /* make sure the radix is ok */ + if (radix < 2 || radix > 64) { + return MP_VAL; + } + + /* if the leading digit is a + * minus set the sign to negative. + */ + if (*str == '-') { + ++str; + neg = MP_NEG; + } else { + neg = MP_ZPOS; + } + + /* set the integer to the default of zero */ + mp_zero (a); + + /* process each digit of the string */ + while (*str) { + /* if the radix < 36 the conversion is case insensitive + * this allows numbers like 1AB and 1ab to represent the same value + * [e.g. in hex] + */ + ch = (char) ((radix < 36) ? toupper (*str) : *str); + for (y = 0; y < 64; y++) { + if (ch == mp_s_rmap[y]) { + break; + } + } + + /* if the char was found in the map + * and is less than the given radix add it + * to the number, otherwise exit the loop. + */ + if (y < radix) { + if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { + return res; + } + if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { + return res; + } + } else { + break; + } + ++str; + } + + /* set the sign only if a != 0 */ + if (mp_iszero(a) != 1) { + a->sign = neg; + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_read_radix.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_read_signed_bin.c b/lib/hcrypto/libtommath/bn_mp_read_signed_bin.c new file mode 100644 index 000000000..8da651ce3 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_read_signed_bin.c @@ -0,0 +1,41 @@ +#include +#ifdef BN_MP_READ_SIGNED_BIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* read signed bin, big endian, first byte is 0==positive or 1==negative */ +int mp_read_signed_bin (mp_int * a, const unsigned char *b, int c) +{ + int res; + + /* read magnitude */ + if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) { + return res; + } + + /* first byte is 0 for positive, non-zero for negative */ + if (b[0] == 0) { + a->sign = MP_ZPOS; + } else { + a->sign = MP_NEG; + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_read_signed_bin.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c b/lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c new file mode 100644 index 000000000..1ebba13a0 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c @@ -0,0 +1,55 @@ +#include +#ifdef BN_MP_READ_UNSIGNED_BIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reads a unsigned char array, assumes the msb is stored first [big endian] */ +int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) +{ + int res; + + /* make sure there are at least two digits */ + if (a->alloc < 2) { + if ((res = mp_grow(a, 2)) != MP_OKAY) { + return res; + } + } + + /* zero the int */ + mp_zero (a); + + /* read the bytes in */ + while (c-- > 0) { + if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { + return res; + } + +#ifndef MP_8BIT + a->dp[0] |= *b++; + a->used += 1; +#else + a->dp[0] = (*b & MP_MASK); + a->dp[1] |= ((*b++ >> 7U) & 1); + a->used += 2; +#endif + } + mp_clamp (a); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_read_unsigned_bin.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce.c b/lib/hcrypto/libtommath/bn_mp_reduce.c new file mode 100644 index 000000000..21d073090 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_reduce.c @@ -0,0 +1,100 @@ +#include +#ifdef BN_MP_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reduces x mod m, assumes 0 < x < m**2, mu is + * precomputed via mp_reduce_setup. + * From HAC pp.604 Algorithm 14.42 + */ +int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) +{ + mp_int q; + int res, um = m->used; + + /* q = x */ + if ((res = mp_init_copy (&q, x)) != MP_OKAY) { + return res; + } + + /* q1 = x / b**(k-1) */ + mp_rshd (&q, um - 1); + + /* according to HAC this optimization is ok */ + if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) { + if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { + goto CLEANUP; + } + } else { +#ifdef BN_S_MP_MUL_HIGH_DIGS_C + if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { + goto CLEANUP; + } +#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) + if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { + goto CLEANUP; + } +#else + { + res = MP_VAL; + goto CLEANUP; + } +#endif + } + + /* q3 = q2 / b**(k+1) */ + mp_rshd (&q, um + 1); + + /* x = x mod b**(k+1), quick (no division) */ + if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { + goto CLEANUP; + } + + /* q = q * m mod b**(k+1), quick (no division) */ + if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { + goto CLEANUP; + } + + /* x = x - q */ + if ((res = mp_sub (x, &q, x)) != MP_OKAY) { + goto CLEANUP; + } + + /* If x < 0, add b**(k+1) to it */ + if (mp_cmp_d (x, 0) == MP_LT) { + mp_set (&q, 1); + if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) + goto CLEANUP; + if ((res = mp_add (x, &q, x)) != MP_OKAY) + goto CLEANUP; + } + + /* Back off if it's too big */ + while (mp_cmp (x, m) != MP_LT) { + if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { + goto CLEANUP; + } + } + +CLEANUP: + mp_clear (&q); + + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_2k.c b/lib/hcrypto/libtommath/bn_mp_reduce_2k.c new file mode 100644 index 000000000..d9620c221 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_reduce_2k.c @@ -0,0 +1,61 @@ +#include +#ifdef BN_MP_REDUCE_2K_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reduces a modulo n where n is of the form 2**p - d */ +int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d) +{ + mp_int q; + int p, res; + + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (d != 1) { + /* q = q * d */ + if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { + goto ERR; + } + } + + /* a = a + q */ + if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + s_mp_sub(a, n, a); + goto top; + } + +ERR: + mp_clear(&q); + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c b/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c new file mode 100644 index 000000000..f06103d6a --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c @@ -0,0 +1,62 @@ +#include +#ifdef BN_MP_REDUCE_2K_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reduces a modulo n where n is of the form 2**p - d + This differs from reduce_2k since "d" can be larger + than a single digit. +*/ +int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) +{ + mp_int q; + int p, res; + + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto ERR; + } + + /* q = q * d */ + if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { + goto ERR; + } + + /* a = a + q */ + if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + s_mp_sub(a, n, a); + goto top; + } + +ERR: + mp_clear(&q); + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_l.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c b/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c new file mode 100644 index 000000000..a80e7a22f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c @@ -0,0 +1,47 @@ +#include +#ifdef BN_MP_REDUCE_2K_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines the setup value */ +int mp_reduce_2k_setup(mp_int *a, mp_digit *d) +{ + int res, p; + mp_int tmp; + + if ((res = mp_init(&tmp)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(a); + if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + *d = tmp.dp[0]; + mp_clear(&tmp); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c b/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c new file mode 100644 index 000000000..7cf002e88 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c @@ -0,0 +1,44 @@ +#include +#ifdef BN_MP_REDUCE_2K_SETUP_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines the setup value */ +int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) +{ + int res; + mp_int tmp; + + if ((res = mp_init(&tmp)) != MP_OKAY) { + return res; + } + + if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { + goto ERR; + } + + if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear(&tmp); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup_l.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c b/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c new file mode 100644 index 000000000..7308be73e --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c @@ -0,0 +1,52 @@ +#include +#ifdef BN_MP_REDUCE_IS_2K_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines if mp_reduce_2k can be used */ +int mp_reduce_is_2k(mp_int *a) +{ + int ix, iy, iw; + mp_digit iz; + + if (a->used == 0) { + return MP_NO; + } else if (a->used == 1) { + return MP_YES; + } else if (a->used > 1) { + iy = mp_count_bits(a); + iz = 1; + iw = 1; + + /* Test every bit from the second digit up, must be 1 */ + for (ix = DIGIT_BIT; ix < iy; ix++) { + if ((a->dp[iw] & iz) == 0) { + return MP_NO; + } + iz <<= 1; + if (iz > (mp_digit)MP_MASK) { + ++iw; + iz = 1; + } + } + } + return MP_YES; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c b/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c new file mode 100644 index 000000000..14a4d2184 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c @@ -0,0 +1,44 @@ +#include +#ifdef BN_MP_REDUCE_IS_2K_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines if reduce_2k_l can be used */ +int mp_reduce_is_2k_l(mp_int *a) +{ + int ix, iy; + + if (a->used == 0) { + return MP_NO; + } else if (a->used == 1) { + return MP_YES; + } else if (a->used > 1) { + /* if more than half of the digits are -1 we're sold */ + for (iy = ix = 0; ix < a->used; ix++) { + if (a->dp[ix] == MP_MASK) { + ++iy; + } + } + return (iy >= (a->used/2)) ? MP_YES : MP_NO; + + } + return MP_NO; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k_l.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_setup.c b/lib/hcrypto/libtommath/bn_mp_reduce_setup.c new file mode 100644 index 000000000..370f20bb1 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_reduce_setup.c @@ -0,0 +1,34 @@ +#include +#ifdef BN_MP_REDUCE_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* pre-calculate the value required for Barrett reduction + * For a given modulus "b" it calulates the value required in "a" + */ +int mp_reduce_setup (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { + return res; + } + return mp_div (a, b, a, NULL); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_setup.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_rshd.c b/lib/hcrypto/libtommath/bn_mp_rshd.c new file mode 100644 index 000000000..2a693c5a5 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_rshd.c @@ -0,0 +1,72 @@ +#include +#ifdef BN_MP_RSHD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* shift right a certain amount of digits */ +void mp_rshd (mp_int * a, int b) +{ + int x; + + /* if b <= 0 then ignore it */ + if (b <= 0) { + return; + } + + /* if b > used then simply zero it and return */ + if (a->used <= b) { + mp_zero (a); + return; + } + + { + register mp_digit *bottom, *top; + + /* shift the digits down */ + + /* bottom */ + bottom = a->dp; + + /* top [offset into digits] */ + top = a->dp + b; + + /* this is implemented as a sliding window where + * the window is b-digits long and digits from + * the top of the window are copied to the bottom + * + * e.g. + + b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> + /\ | ----> + \-------------------/ ----> + */ + for (x = 0; x < (a->used - b); x++) { + *bottom++ = *top++; + } + + /* zero the top digits */ + for (; x < a->used; x++) { + *bottom++ = 0; + } + } + + /* remove excess digits */ + a->used -= b; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_rshd.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_set.c b/lib/hcrypto/libtommath/bn_mp_set.c new file mode 100644 index 000000000..174adcbc6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set.c @@ -0,0 +1,29 @@ +#include +#ifdef BN_MP_SET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* set to a digit */ +void mp_set (mp_int * a, mp_digit b) +{ + mp_zero (a); + a->dp[0] = b & MP_MASK; + a->used = (a->dp[0] != 0) ? 1 : 0; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_set.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_set_int.c b/lib/hcrypto/libtommath/bn_mp_set_int.c new file mode 100644 index 000000000..cf10ea1a4 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set_int.c @@ -0,0 +1,48 @@ +#include +#ifdef BN_MP_SET_INT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* set a 32-bit const */ +int mp_set_int (mp_int * a, unsigned long b) +{ + int x, res; + + mp_zero (a); + + /* set four bits at a time */ + for (x = 0; x < 8; x++) { + /* shift the number up four bits */ + if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { + return res; + } + + /* OR in the top four bits of the source */ + a->dp[0] |= (b >> 28) & 15; + + /* shift the source up to the next four bits */ + b <<= 4; + + /* ensure that digits are not clamped off */ + a->used += 1; + } + mp_clamp (a); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_set_int.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_shrink.c b/lib/hcrypto/libtommath/bn_mp_shrink.c new file mode 100644 index 000000000..4b8c5ef11 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_shrink.c @@ -0,0 +1,35 @@ +#include +#ifdef BN_MP_SHRINK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* shrink a bignum */ +int mp_shrink (mp_int * a) +{ + mp_digit *tmp; + if (a->alloc != a->used && a->used > 0) { + if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) { + return MP_MEM; + } + a->dp = tmp; + a->alloc = a->used; + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_shrink.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_signed_bin_size.c b/lib/hcrypto/libtommath/bn_mp_signed_bin_size.c new file mode 100644 index 000000000..6739d19e2 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_signed_bin_size.c @@ -0,0 +1,27 @@ +#include +#ifdef BN_MP_SIGNED_BIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* get the size for an signed equivalent */ +int mp_signed_bin_size (mp_int * a) +{ + return 1 + mp_unsigned_bin_size (a); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_signed_bin_size.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_sqr.c b/lib/hcrypto/libtommath/bn_mp_sqr.c new file mode 100644 index 000000000..868ccbbae --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_sqr.c @@ -0,0 +1,58 @@ +#include +#ifdef BN_MP_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes b = a*a */ +int +mp_sqr (mp_int * a, mp_int * b) +{ + int res; + +#ifdef BN_MP_TOOM_SQR_C + /* use Toom-Cook? */ + if (a->used >= TOOM_SQR_CUTOFF) { + res = mp_toom_sqr(a, b); + /* Karatsuba? */ + } else +#endif +#ifdef BN_MP_KARATSUBA_SQR_C +if (a->used >= KARATSUBA_SQR_CUTOFF) { + res = mp_karatsuba_sqr (a, b); + } else +#endif + { +#ifdef BN_FAST_S_MP_SQR_C + /* can we use the fast comba multiplier? */ + if ((a->used * 2 + 1) < MP_WARRAY && + a->used < + (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { + res = fast_s_mp_sqr (a, b); + } else +#endif +#ifdef BN_S_MP_SQR_C + res = s_mp_sqr (a, b); +#else + res = MP_VAL; +#endif + } + b->sign = MP_ZPOS; + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_sqr.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_sqrmod.c b/lib/hcrypto/libtommath/bn_mp_sqrmod.c new file mode 100644 index 000000000..161cbbb30 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_sqrmod.c @@ -0,0 +1,41 @@ +#include +#ifdef BN_MP_SQRMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* c = a * a (mod b) */ +int +mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_sqr (a, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, b, c); + mp_clear (&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_sqrmod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_sqrt.c b/lib/hcrypto/libtommath/bn_mp_sqrt.c new file mode 100644 index 000000000..8fd057cee --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_sqrt.c @@ -0,0 +1,81 @@ +#include +#ifdef BN_MP_SQRT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* this function is less generic than mp_n_root, simpler and faster */ +int mp_sqrt(mp_int *arg, mp_int *ret) +{ + int res; + mp_int t1,t2; + + /* must be positive */ + if (arg->sign == MP_NEG) { + return MP_VAL; + } + + /* easy out */ + if (mp_iszero(arg) == MP_YES) { + mp_zero(ret); + return MP_OKAY; + } + + if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) { + return res; + } + + if ((res = mp_init(&t2)) != MP_OKAY) { + goto E2; + } + + /* First approx. (not very bad for large arg) */ + mp_rshd (&t1,t1.used/2); + + /* t1 > 0 */ + if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { + goto E1; + } + if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { + goto E1; + } + if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { + goto E1; + } + /* And now t1 > sqrt(arg) */ + do { + if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { + goto E1; + } + if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { + goto E1; + } + if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { + goto E1; + } + /* t1 >= sqrt(arg) >= t2 at this point */ + } while (mp_cmp_mag(&t1,&t2) == MP_GT); + + mp_exch(&t1,ret); + +E1: mp_clear(&t2); +E2: mp_clear(&t1); + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_sqrt.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_sub.c b/lib/hcrypto/libtommath/bn_mp_sub.c new file mode 100644 index 000000000..f5015cce4 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_sub.c @@ -0,0 +1,59 @@ +#include +#ifdef BN_MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* high level subtraction (handles signs) */ +int +mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int sa, sb, res; + + sa = a->sign; + sb = b->sign; + + if (sa != sb) { + /* subtract a negative from a positive, OR */ + /* subtract a positive from a negative. */ + /* In either case, ADD their magnitudes, */ + /* and use the sign of the first number. */ + c->sign = sa; + res = s_mp_add (a, b, c); + } else { + /* subtract a positive from a positive, OR */ + /* subtract a negative from a negative. */ + /* First, take the difference between their */ + /* magnitudes, then... */ + if (mp_cmp_mag (a, b) != MP_LT) { + /* Copy the sign from the first */ + c->sign = sa; + /* The first has a larger or equal magnitude */ + res = s_mp_sub (a, b, c); + } else { + /* The result has the *opposite* sign from */ + /* the first number. */ + c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; + /* The second has a larger magnitude */ + res = s_mp_sub (b, a, c); + } + } + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_sub.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_sub_d.c b/lib/hcrypto/libtommath/bn_mp_sub_d.c new file mode 100644 index 000000000..06cdca636 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_sub_d.c @@ -0,0 +1,93 @@ +#include +#ifdef BN_MP_SUB_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* single digit subtraction */ +int +mp_sub_d (mp_int * a, mp_digit b, mp_int * c) +{ + mp_digit *tmpa, *tmpc, mu; + int res, ix, oldused; + + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* if a is negative just do an unsigned + * addition [with fudged signs] + */ + if (a->sign == MP_NEG) { + a->sign = MP_ZPOS; + res = mp_add_d(a, b, c); + a->sign = c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return res; + } + + /* setup regs */ + oldused = c->used; + tmpa = a->dp; + tmpc = c->dp; + + /* if a <= b simply fix the single digit */ + if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) { + if (a->used == 1) { + *tmpc++ = b - *tmpa; + } else { + *tmpc++ = b; + } + ix = 1; + + /* negative/1digit */ + c->sign = MP_NEG; + c->used = 1; + } else { + /* positive/size */ + c->sign = MP_ZPOS; + c->used = a->used; + + /* subtract first digit */ + *tmpc = *tmpa++ - b; + mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); + *tmpc++ &= MP_MASK; + + /* handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ - mu; + mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); + *tmpc++ &= MP_MASK; + } + } + + /* zero excess digits */ + while (ix++ < oldused) { + *tmpc++ = 0; + } + mp_clamp(c); + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_sub_d.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_submod.c b/lib/hcrypto/libtommath/bn_mp_submod.c new file mode 100644 index 000000000..869e23cde --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_submod.c @@ -0,0 +1,42 @@ +#include +#ifdef BN_MP_SUBMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* d = a - b (mod c) */ +int +mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + int res; + mp_int t; + + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_sub (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, c, d); + mp_clear (&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_submod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_to_signed_bin.c b/lib/hcrypto/libtommath/bn_mp_to_signed_bin.c new file mode 100644 index 000000000..9df83ca52 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_to_signed_bin.c @@ -0,0 +1,33 @@ +#include +#ifdef BN_MP_TO_SIGNED_BIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* store in signed [big endian] format */ +int mp_to_signed_bin (mp_int * a, unsigned char *b) +{ + int res; + + if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) { + return res; + } + b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c b/lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c new file mode 100644 index 000000000..677f827d4 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c @@ -0,0 +1,31 @@ +#include +#ifdef BN_MP_TO_SIGNED_BIN_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* store in signed [big endian] format */ +int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen) +{ + if (*outlen < (unsigned long)mp_signed_bin_size(a)) { + return MP_VAL; + } + *outlen = mp_signed_bin_size(a); + return mp_to_signed_bin(a, b); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin_n.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c b/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c new file mode 100644 index 000000000..c137f104a --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c @@ -0,0 +1,48 @@ +#include +#ifdef BN_MP_TO_UNSIGNED_BIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* store in unsigned [big endian] format */ +int mp_to_unsigned_bin (mp_int * a, unsigned char *b) +{ + int x, res; + mp_int t; + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + x = 0; + while (mp_iszero (&t) == 0) { +#ifndef MP_8BIT + b[x++] = (unsigned char) (t.dp[0] & 255); +#else + b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); +#endif + if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { + mp_clear (&t); + return res; + } + } + bn_reverse (b, x); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c b/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c new file mode 100644 index 000000000..0dc00c623 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c @@ -0,0 +1,31 @@ +#include +#ifdef BN_MP_TO_UNSIGNED_BIN_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* store in unsigned [big endian] format */ +int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen) +{ + if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) { + return MP_VAL; + } + *outlen = mp_unsigned_bin_size(a); + return mp_to_unsigned_bin(a, b); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin_n.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_toom_mul.c b/lib/hcrypto/libtommath/bn_mp_toom_mul.c new file mode 100644 index 000000000..ad5d9e9b6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_toom_mul.c @@ -0,0 +1,284 @@ +#include +#ifdef BN_MP_TOOM_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* multiplication using the Toom-Cook 3-way algorithm + * + * Much more complicated than Karatsuba but has a lower + * asymptotic running time of O(N**1.464). This algorithm is + * only particularly useful on VERY large inputs + * (we're talking 1000s of digits here...). +*/ +int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) +{ + mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2; + int res, B; + + /* init temps */ + if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, + &a0, &a1, &a2, &b0, &b1, + &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) { + return res; + } + + /* B */ + B = MIN(a->used, b->used) / 3; + + /* a = a2 * B**2 + a1 * B + a0 */ + if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a1, B); + mp_mod_2d(&a1, DIGIT_BIT * B, &a1); + + if ((res = mp_copy(a, &a2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a2, B*2); + + /* b = b2 * B**2 + b1 * B + b0 */ + if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(b, &b1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&b1, B); + mp_mod_2d(&b1, DIGIT_BIT * B, &b1); + + if ((res = mp_copy(b, &b2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&b2, B*2); + + /* w0 = a0*b0 */ + if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) { + goto ERR; + } + + /* w4 = a2 * b2 */ + if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) { + goto ERR; + } + + /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */ + if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) { + goto ERR; + } + + /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */ + if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) { + goto ERR; + } + + + /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */ + if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) { + goto ERR; + } + + /* now solve the matrix + + 0 0 0 0 1 + 1 2 4 8 16 + 1 1 1 1 1 + 16 8 4 2 1 + 1 0 0 0 0 + + using 12 subtractions, 4 shifts, + 2 small divisions and 1 small multiplication + */ + + /* r1 - r4 */ + if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r0 */ + if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/2 */ + if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3/2 */ + if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { + goto ERR; + } + /* r2 - r0 - r4 */ + if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1 - 8r0 */ + if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - 8r4 */ + if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + /* 3r2 - r1 - r3 */ + if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/3 */ + if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { + goto ERR; + } + /* r3/3 */ + if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { + goto ERR; + } + + /* at this point shift W[n] by B*n */ + if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear_multi(&w0, &w1, &w2, &w3, &w4, + &a0, &a1, &a2, &b0, &b1, + &b2, &tmp1, &tmp2, NULL); + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_toom_mul.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_toom_sqr.c b/lib/hcrypto/libtommath/bn_mp_toom_sqr.c new file mode 100644 index 000000000..48880d035 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_toom_sqr.c @@ -0,0 +1,226 @@ +#include +#ifdef BN_MP_TOOM_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* squaring using Toom-Cook 3-way algorithm */ +int +mp_toom_sqr(mp_int *a, mp_int *b) +{ + mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2; + int res, B; + + /* init temps */ + if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) { + return res; + } + + /* B */ + B = a->used / 3; + + /* a = a2 * B**2 + a1 * B + a0 */ + if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a1, B); + mp_mod_2d(&a1, DIGIT_BIT * B, &a1); + + if ((res = mp_copy(a, &a2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a2, B*2); + + /* w0 = a0*a0 */ + if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) { + goto ERR; + } + + /* w4 = a2 * a2 */ + if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) { + goto ERR; + } + + /* w1 = (a2 + 2(a1 + 2a0))**2 */ + if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + + /* w3 = (a0 + 2(a1 + 2a2))**2 */ + if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + + + /* w2 = (a2 + a1 + a0)**2 */ + if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) { + goto ERR; + } + + /* now solve the matrix + + 0 0 0 0 1 + 1 2 4 8 16 + 1 1 1 1 1 + 16 8 4 2 1 + 1 0 0 0 0 + + using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication. + */ + + /* r1 - r4 */ + if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r0 */ + if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/2 */ + if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3/2 */ + if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { + goto ERR; + } + /* r2 - r0 - r4 */ + if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1 - 8r0 */ + if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - 8r4 */ + if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + /* 3r2 - r1 - r3 */ + if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/3 */ + if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { + goto ERR; + } + /* r3/3 */ + if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { + goto ERR; + } + + /* at this point shift W[n] by B*n */ + if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL); + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_toom_sqr.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_toradix.c b/lib/hcrypto/libtommath/bn_mp_toradix.c new file mode 100644 index 000000000..0adc28d2f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_toradix.c @@ -0,0 +1,75 @@ +#include +#ifdef BN_MP_TORADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* stores a bignum as a ASCII string in a given radix (2..64) */ +int mp_toradix (mp_int * a, char *str, int radix) +{ + int res, digs; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of the radix */ + if (radix < 2 || radix > 64) { + return MP_VAL; + } + + /* quick out if its zero */ + if (mp_iszero(a) == 1) { + *str++ = '0'; + *str = '\0'; + return MP_OKAY; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* if it is negative output a - */ + if (t.sign == MP_NEG) { + ++_s; + *str++ = '-'; + t.sign = MP_ZPOS; + } + + digs = 0; + while (mp_iszero (&t) == 0) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + *str++ = mp_s_rmap[d]; + ++digs; + } + + /* reverse the digits of the string. In this case _s points + * to the first digit [exluding the sign] of the number] + */ + bn_reverse ((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + + mp_clear (&t); + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_toradix.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_toradix_n.c b/lib/hcrypto/libtommath/bn_mp_toradix_n.c new file mode 100644 index 000000000..796ed55c6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_toradix_n.c @@ -0,0 +1,88 @@ +#include +#ifdef BN_MP_TORADIX_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* stores a bignum as a ASCII string in a given radix (2..64) + * + * Stores upto maxlen-1 chars and always a NULL byte + */ +int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen) +{ + int res, digs; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of the maxlen, radix */ + if (maxlen < 2 || radix < 2 || radix > 64) { + return MP_VAL; + } + + /* quick out if its zero */ + if (mp_iszero(a) == MP_YES) { + *str++ = '0'; + *str = '\0'; + return MP_OKAY; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* if it is negative output a - */ + if (t.sign == MP_NEG) { + /* we have to reverse our digits later... but not the - sign!! */ + ++_s; + + /* store the flag and mark the number as positive */ + *str++ = '-'; + t.sign = MP_ZPOS; + + /* subtract a char */ + --maxlen; + } + + digs = 0; + while (mp_iszero (&t) == 0) { + if (--maxlen < 1) { + /* no more room */ + break; + } + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + *str++ = mp_s_rmap[d]; + ++digs; + } + + /* reverse the digits of the string. In this case _s points + * to the first digit [exluding the sign] of the number + */ + bn_reverse ((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + + mp_clear (&t); + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_toradix_n.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c b/lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c new file mode 100644 index 000000000..6dc3bd5fc --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c @@ -0,0 +1,28 @@ +#include +#ifdef BN_MP_UNSIGNED_BIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* get the size for an unsigned equivalent */ +int mp_unsigned_bin_size (mp_int * a) +{ + int size = mp_count_bits (a); + return (size / 8 + ((size & 7) != 0 ? 1 : 0)); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_unsigned_bin_size.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_xor.c b/lib/hcrypto/libtommath/bn_mp_xor.c new file mode 100644 index 000000000..59ff2e183 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_xor.c @@ -0,0 +1,51 @@ +#include +#ifdef BN_MP_XOR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* XOR two ints together */ +int +mp_xor (mp_int * a, mp_int * b, mp_int * c) +{ + int res, ix, px; + mp_int t, *x; + + if (a->used > b->used) { + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + px = b->used; + x = b; + } else { + if ((res = mp_init_copy (&t, b)) != MP_OKAY) { + return res; + } + px = a->used; + x = a; + } + + for (ix = 0; ix < px; ix++) { + t.dp[ix] ^= x->dp[ix]; + } + mp_clamp (&t); + mp_exch (c, &t); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_xor.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_zero.c b/lib/hcrypto/libtommath/bn_mp_zero.c new file mode 100644 index 000000000..b0977d443 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_zero.c @@ -0,0 +1,36 @@ +#include +#ifdef BN_MP_ZERO_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* set to zero */ +void mp_zero (mp_int * a) +{ + int n; + mp_digit *tmp; + + a->sign = MP_ZPOS; + a->used = 0; + + tmp = a->dp; + for (n = 0; n < a->alloc; n++) { + *tmp++ = 0; + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_zero.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_prime_tab.c b/lib/hcrypto/libtommath/bn_prime_tab.c new file mode 100644 index 000000000..bd252477e --- /dev/null +++ b/lib/hcrypto/libtommath/bn_prime_tab.c @@ -0,0 +1,61 @@ +#include +#ifdef BN_PRIME_TAB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +const mp_digit ltm_prime_tab[] = { + 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, + 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, + 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, + 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, +#ifndef MP_8BIT + 0x0083, + 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, + 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, + 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, + 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, + + 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, + 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, + 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, + 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, + 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, + 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, + 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, + 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, + + 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, + 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, + 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, + 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, + 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, + 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, + 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, + 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, + + 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, + 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, + 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, + 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, + 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, + 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, + 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, + 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 +#endif +}; +#endif + +/* $Source: /cvs/libtom/libtommath/bn_prime_tab.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_reverse.c b/lib/hcrypto/libtommath/bn_reverse.c new file mode 100644 index 000000000..ddfa827a0 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_reverse.c @@ -0,0 +1,39 @@ +#include +#ifdef BN_REVERSE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reverse an array, used for radix code */ +void +bn_reverse (unsigned char *s, int len) +{ + int ix, iy; + unsigned char t; + + ix = 0; + iy = len - 1; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_reverse.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_add.c b/lib/hcrypto/libtommath/bn_s_mp_add.c new file mode 100644 index 000000000..f034ae62a --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_add.c @@ -0,0 +1,109 @@ +#include +#ifdef BN_S_MP_ADD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* low level addition, based on HAC pp.594, Algorithm 14.7 */ +int +s_mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int *x; + int olduse, res, min, max; + + /* find sizes, we let |a| <= |b| which means we have to sort + * them. "x" will point to the input with the most digits + */ + if (a->used > b->used) { + min = b->used; + max = a->used; + x = a; + } else { + min = a->used; + max = b->used; + x = b; + } + + /* init result */ + if (c->alloc < max + 1) { + if ((res = mp_grow (c, max + 1)) != MP_OKAY) { + return res; + } + } + + /* get old used digit count and set new one */ + olduse = c->used; + c->used = max + 1; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; + + /* alias for digit pointers */ + + /* first input */ + tmpa = a->dp; + + /* second input */ + tmpb = b->dp; + + /* destination */ + tmpc = c->dp; + + /* zero the carry */ + u = 0; + for (i = 0; i < min; i++) { + /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ + *tmpc = *tmpa++ + *tmpb++ + u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)DIGIT_BIT); + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, that is in A+B + * if A or B has more digits add those in + */ + if (min != max) { + for (; i < max; i++) { + /* T[i] = X[i] + U */ + *tmpc = x->dp[i] + u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)DIGIT_BIT); + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + } + + /* add carry */ + *tmpc++ = u; + + /* clear digits above oldused */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_add.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_exptmod.c b/lib/hcrypto/libtommath/bn_s_mp_exptmod.c new file mode 100644 index 000000000..097d89470 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_exptmod.c @@ -0,0 +1,252 @@ +#include +#ifdef BN_S_MP_EXPTMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#ifdef MP_LOW_MEM + #define TAB_SIZE 32 +#else + #define TAB_SIZE 256 +#endif + +int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) +{ + mp_int M[TAB_SIZE], res, mu; + mp_digit buf; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + int (*redux)(mp_int*,mp_int*,mp_int*); + + /* find window size */ + x = mp_count_bits (X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + +#ifdef MP_LOW_MEM + if (winsize > 5) { + winsize = 5; + } +#endif + + /* init M array */ + /* init first cell */ + if ((err = mp_init(&M[1])) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init(&M[x])) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear (&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* create mu, used for Barrett reduction */ + if ((err = mp_init (&mu)) != MP_OKAY) { + goto LBL_M; + } + + if (redmode == 0) { + if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { + goto LBL_MU; + } + redux = mp_reduce; + } else { + if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) { + goto LBL_MU; + } + redux = mp_reduce_2k_l; + } + + /* create M table + * + * The M table contains powers of the base, + * e.g. M[x] = G**x mod P + * + * The first half of the table is not + * computed though accept for M[0] and M[1] + */ + if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { + goto LBL_MU; + } + + /* compute the value at M[1<<(winsize-1)] by squaring + * M[1] (winsize-1) times + */ + if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto LBL_MU; + } + + for (x = 0; x < (winsize - 1); x++) { + /* square it */ + if ((err = mp_sqr (&M[1 << (winsize - 1)], + &M[1 << (winsize - 1)])) != MP_OKAY) { + goto LBL_MU; + } + + /* reduce modulo P */ + if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { + goto LBL_MU; + } + } + + /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) + * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) + */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { + goto LBL_MU; + } + if ((err = redux (&M[x], P, &mu)) != MP_OKAY) { + goto LBL_MU; + } + } + + /* setup result */ + if ((err = mp_init (&res)) != MP_OKAY) { + goto LBL_MU; + } + mp_set (&res, 1); + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits */ + if (digidx == -1) { + break; + } + /* read next digit and reset the bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int) DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* then multiply */ + if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + } + } + } + + mp_exch (&res, Y); + err = MP_OKAY; +LBL_RES:mp_clear (&res); +LBL_MU:mp_clear (&mu); +LBL_M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear (&M[x]); + } + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_exptmod.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c b/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c new file mode 100644 index 000000000..f5bbf39ce --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c @@ -0,0 +1,90 @@ +#include +#ifdef BN_S_MP_MUL_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* multiplies |a| * |b| and only computes upto digs digits of result + * HAC pp. 595, Algorithm 14.12 Modified so you can control how + * many digits of output are created. + */ +int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + /* can we use the fast multiplier? */ + if (((digs) < MP_WARRAY) && + MIN (a->used, b->used) < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_digs (a, b, c, digs); + } + + if ((res = mp_init_size (&t, digs)) != MP_OKAY) { + return res; + } + t.used = digs; + + /* compute the digits of the product directly */ + pa = a->used; + for (ix = 0; ix < pa; ix++) { + /* set the carry to zero */ + u = 0; + + /* limit ourselves to making digs digits of output */ + pb = MIN (b->used, digs - ix); + + /* setup some aliases */ + /* copy of the digit from a used within the nested loop */ + tmpx = a->dp[ix]; + + /* an alias for the destination shifted ix places */ + tmpt = t.dp + ix; + + /* an alias for the digits of b */ + tmpy = b->dp; + + /* compute the columns of the output and propagate the carry */ + for (iy = 0; iy < pb; iy++) { + /* compute the column as a mp_word */ + r = ((mp_word)*tmpt) + + ((mp_word)tmpx) * ((mp_word)*tmpy++) + + ((mp_word) u); + + /* the new column is the lower part of the result */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get the carry word from the result */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + /* set carry if it is placed below digs */ + if (ix + iy < digs) { + *tmpt = u; + } + } + + mp_clamp (&t); + mp_exch (&t, c); + + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_digs.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c b/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c new file mode 100644 index 000000000..2b718f23c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c @@ -0,0 +1,81 @@ +#include +#ifdef BN_S_MP_MUL_HIGH_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* multiplies |a| * |b| and does not compute the lower digs digits + * [meant to get the higher part of the product] + */ +int +s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + /* can we use the fast multiplier? */ +#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C + if (((a->used + b->used + 1) < MP_WARRAY) + && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_high_digs (a, b, c, digs); + } +#endif + + if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { + return res; + } + t.used = a->used + b->used + 1; + + pa = a->used; + pb = b->used; + for (ix = 0; ix < pa; ix++) { + /* clear the carry */ + u = 0; + + /* left hand side of A[ix] * B[iy] */ + tmpx = a->dp[ix]; + + /* alias to the address of where the digits will be stored */ + tmpt = &(t.dp[digs]); + + /* alias for where to read the right hand side from */ + tmpy = b->dp + (digs - ix); + + for (iy = digs - ix; iy < pb; iy++) { + /* calculate the double precision result */ + r = ((mp_word)*tmpt) + + ((mp_word)tmpx) * ((mp_word)*tmpy++) + + ((mp_word) u); + + /* get the lower part */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* carry the carry */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + *tmpt = u; + } + mp_clamp (&t); + mp_exch (&t, c); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_high_digs.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_sqr.c b/lib/hcrypto/libtommath/bn_s_mp_sqr.c new file mode 100644 index 000000000..d2531c292 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_sqr.c @@ -0,0 +1,84 @@ +#include +#ifdef BN_S_MP_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ +int s_mp_sqr (mp_int * a, mp_int * b) +{ + mp_int t; + int res, ix, iy, pa; + mp_word r; + mp_digit u, tmpx, *tmpt; + + pa = a->used; + if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { + return res; + } + + /* default used is maximum possible size */ + t.used = 2*pa + 1; + + for (ix = 0; ix < pa; ix++) { + /* first calculate the digit at 2*ix */ + /* calculate double precision result */ + r = ((mp_word) t.dp[2*ix]) + + ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); + + /* store lower part in result */ + t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get the carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + + /* left hand side of A[ix] * A[iy] */ + tmpx = a->dp[ix]; + + /* alias for where to store the results */ + tmpt = t.dp + (2*ix + 1); + + for (iy = ix + 1; iy < pa; iy++) { + /* first calculate the product */ + r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); + + /* now calculate the double precision result, note we use + * addition instead of *2 since it's easier to optimize + */ + r = ((mp_word) *tmpt) + r + r + ((mp_word) u); + + /* store lower part */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + } + /* propagate upwards */ + while (u != ((mp_digit) 0)) { + r = ((mp_word) *tmpt) + ((mp_word) u); + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + } + } + + mp_clamp (&t); + mp_exch (&t, b); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_sqr.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_sub.c b/lib/hcrypto/libtommath/bn_s_mp_sub.c new file mode 100644 index 000000000..6a60c3932 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_sub.c @@ -0,0 +1,89 @@ +#include +#ifdef BN_S_MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ +int +s_mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int olduse, res, min, max; + + /* find sizes */ + min = b->used; + max = a->used; + + /* init result */ + if (c->alloc < max) { + if ((res = mp_grow (c, max)) != MP_OKAY) { + return res; + } + } + olduse = c->used; + c->used = max; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; + + /* alias for digit pointers */ + tmpa = a->dp; + tmpb = b->dp; + tmpc = c->dp; + + /* set carry to zero */ + u = 0; + for (i = 0; i < min; i++) { + /* T[i] = A[i] - B[i] - U */ + *tmpc = *tmpa++ - *tmpb++ - u; + + /* U = carry bit of T[i] + * Note this saves performing an AND operation since + * if a carry does occur it will propagate all the way to the + * MSB. As a result a single shift is enough to get the carry + */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, e.g. if A has more digits than B */ + for (; i < max; i++) { + /* T[i] = A[i] - U */ + *tmpc = *tmpa++ - u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* clear digits above used (since we may not have grown result above) */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_sub.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bncore.c b/lib/hcrypto/libtommath/bncore.c new file mode 100644 index 000000000..8fb1824c6 --- /dev/null +++ b/lib/hcrypto/libtommath/bncore.c @@ -0,0 +1,36 @@ +#include +#ifdef BNCORE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Known optimal configurations + + CPU /Compiler /MUL CUTOFF/SQR CUTOFF +------------------------------------------------------------- + Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-) + AMD Athlon64 /GCC v3.4.4 / 80/ 120/LTM 0.35 + +*/ + +int KARATSUBA_MUL_CUTOFF = 80, /* Min. number of digits before Karatsuba multiplication is used. */ + KARATSUBA_SQR_CUTOFF = 120, /* Min. number of digits before Karatsuba squaring is used. */ + + TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */ + TOOM_SQR_CUTOFF = 400; +#endif + +/* $Source: /cvs/libtom/libtommath/bncore.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/booker.pl b/lib/hcrypto/libtommath/booker.pl new file mode 100644 index 000000000..49f1889d1 --- /dev/null +++ b/lib/hcrypto/libtommath/booker.pl @@ -0,0 +1,265 @@ +#!/bin/perl +# +#Used to prepare the book "tommath.src" for LaTeX by pre-processing it into a .tex file +# +#Essentially you write the "tommath.src" as normal LaTex except where you want code snippets you put +# +#EXAM,file +# +#This preprocessor will then open "file" and insert it as a verbatim copy. +# +#Tom St Denis + +#get graphics type +if (shift =~ /PDF/) { + $graph = ""; +} else { + $graph = ".ps"; +} + +open(IN,"tommath.tex") or die "Can't open destination file"; + +print "Scanning for sections\n"; +$chapter = $section = $subsection = 0; +$x = 0; +while () { + print "."; + if (!(++$x % 80)) { print "\n"; } + #update the headings + if (~($_ =~ /\*/)) { + if ($_ =~ /\\chapter{.+}/) { + ++$chapter; + $section = $subsection = 0; + } elsif ($_ =~ /\\section{.+}/) { + ++$section; + $subsection = 0; + } elsif ($_ =~ /\\subsection{.+}/) { + ++$subsection; + } + } + + if ($_ =~ m/MARK/) { + @m = split(",",$_); + chomp(@m[1]); + $index1{@m[1]} = $chapter; + $index2{@m[1]} = $section; + $index3{@m[1]} = $subsection; + } +} +close(IN); + +open(IN,") { + ++$readline; + ++$srcline; + + if ($_ =~ m/MARK/) { + } elsif ($_ =~ m/EXAM/ || $_ =~ m/LIST/) { + if ($_ =~ m/EXAM/) { + $skipheader = 1; + } else { + $skipheader = 0; + } + + # EXAM,file + chomp($_); + @m = split(",",$_); + open(SRC,"<$m[1]") or die "Error:$srcline:Can't open source file $m[1]"; + + print "$srcline:Inserting $m[1]:"; + + $line = 0; + $tmp = $m[1]; + $tmp =~ s/_/"\\_"/ge; + print OUT "\\vspace{+3mm}\\begin{small}\n\\hspace{-5.1mm}{\\bf File}: $tmp\n\\vspace{-3mm}\n\\begin{alltt}\n"; + $wroteline += 5; + + if ($skipheader == 1) { + # scan till next end of comment, e.g. skip license + while () { + $text[$line++] = $_; + last if ($_ =~ /math\.libtomcrypt\.com/); + } + ; + } + + $inline = 0; + while () { + next if ($_ =~ /\$Source/); + next if ($_ =~ /\$Revision/); + next if ($_ =~ /\$Date/); + $text[$line++] = $_; + ++$inline; + chomp($_); + $_ =~ s/\t/" "/ge; + $_ =~ s/{/"^{"/ge; + $_ =~ s/}/"^}"/ge; + $_ =~ s/\\/'\symbol{92}'/ge; + $_ =~ s/\^/"\\"/ge; + + printf OUT ("%03d ", $line); + for ($x = 0; $x < length($_); $x++) { + print OUT chr(vec($_, $x, 8)); + if ($x == 75) { + print OUT "\n "; + ++$wroteline; + } + } + print OUT "\n"; + ++$wroteline; + } + $totlines = $line; + print OUT "\\end{alltt}\n\\end{small}\n"; + close(SRC); + print "$inline lines\n"; + $wroteline += 2; + } elsif ($_ =~ m/@\d+,.+@/) { + # line contains [number,text] + # e.g. @14,for (ix = 0)@ + $txt = $_; + while ($txt =~ m/@\d+,.+@/) { + @m = split("@",$txt); # splits into text, one, two + @parms = split(",",$m[1]); # splits one,two into two elements + + # now search from $parms[0] down for $parms[1] + $found1 = 0; + $found2 = 0; + for ($i = $parms[0]; $i < $totlines && $found1 == 0; $i++) { + if ($text[$i] =~ m/\Q$parms[1]\E/) { + $foundline1 = $i + 1; + $found1 = 1; + } + } + + # now search backwards + for ($i = $parms[0] - 1; $i >= 0 && $found2 == 0; $i--) { + if ($text[$i] =~ m/\Q$parms[1]\E/) { + $foundline2 = $i + 1; + $found2 = 1; + } + } + + # now use the closest match or the first if tied + if ($found1 == 1 && $found2 == 0) { + $found = 1; + $foundline = $foundline1; + } elsif ($found1 == 0 && $found2 == 1) { + $found = 1; + $foundline = $foundline2; + } elsif ($found1 == 1 && $found2 == 1) { + $found = 1; + if (($foundline1 - $parms[0]) <= ($parms[0] - $foundline2)) { + $foundline = $foundline1; + } else { + $foundline = $foundline2; + } + } else { + $found = 0; + } + + # if found replace + if ($found == 1) { + $delta = $parms[0] - $foundline; + print "Found replacement tag for \"$parms[1]\" on line $srcline which refers to line $foundline (delta $delta)\n"; + $_ =~ s/@\Q$m[1]\E@/$foundline/; + } else { + print "ERROR: The tag \"$parms[1]\" on line $srcline was not found in the most recently parsed source!\n"; + } + + # remake the rest of the line + $cnt = @m; + $txt = ""; + for ($i = 2; $i < $cnt; $i++) { + $txt = $txt . $m[$i] . "@"; + } + } + print OUT $_; + ++$wroteline; + } elsif ($_ =~ /~.+~/) { + # line contains a ~text~ pair used to refer to indexing :-) + $txt = $_; + while ($txt =~ /~.+~/) { + @m = split("~", $txt); + + # word is the second position + $word = @m[1]; + $a = $index1{$word}; + $b = $index2{$word}; + $c = $index3{$word}; + + # if chapter (a) is zero it wasn't found + if ($a == 0) { + print "ERROR: the tag \"$word\" on line $srcline was not found previously marked.\n"; + } else { + # format the tag as x, x.y or x.y.z depending on the values + $str = $a; + $str = $str . ".$b" if ($b != 0); + $str = $str . ".$c" if ($c != 0); + + if ($b == 0 && $c == 0) { + # its a chapter + if ($a <= 10) { + if ($a == 1) { + $str = "chapter one"; + } elsif ($a == 2) { + $str = "chapter two"; + } elsif ($a == 3) { + $str = "chapter three"; + } elsif ($a == 4) { + $str = "chapter four"; + } elsif ($a == 5) { + $str = "chapter five"; + } elsif ($a == 6) { + $str = "chapter six"; + } elsif ($a == 7) { + $str = "chapter seven"; + } elsif ($a == 8) { + $str = "chapter eight"; + } elsif ($a == 9) { + $str = "chapter nine"; + } elsif ($a == 10) { + $str = "chapter ten"; + } + } else { + $str = "chapter " . $str; + } + } else { + $str = "section " . $str if ($b != 0 && $c == 0); + $str = "sub-section " . $str if ($b != 0 && $c != 0); + } + + #substitute + $_ =~ s/~\Q$word\E~/$str/; + + print "Found replacement tag for marker \"$word\" on line $srcline which refers to $str\n"; + } + + # remake rest of the line + $cnt = @m; + $txt = ""; + for ($i = 2; $i < $cnt; $i++) { + $txt = $txt . $m[$i] . "~"; + } + } + print OUT $_; + ++$wroteline; + } elsif ($_ =~ m/FIGU/) { + # FIGU,file,caption + chomp($_); + @m = split(",", $_); + print OUT "\\begin{center}\n\\begin{figure}[here]\n\\includegraphics{pics/$m[1]$graph}\n"; + print OUT "\\caption{$m[2]}\n\\label{pic:$m[1]}\n\\end{figure}\n\\end{center}\n"; + $wroteline += 4; + } else { + print OUT $_; + ++$wroteline; + } +} +print "Read $readline lines, wrote $wroteline lines\n"; + +close (OUT); +close (IN); diff --git a/lib/hcrypto/libtommath/callgraph.txt b/lib/hcrypto/libtommath/callgraph.txt new file mode 100644 index 000000000..2efcf245b --- /dev/null +++ b/lib/hcrypto/libtommath/callgraph.txt @@ -0,0 +1,11913 @@ +BN_PRIME_TAB_C + + +BN_MP_SQRT_C ++--->BN_MP_N_ROOT_C +| +--->BN_MP_INIT_C +| +--->BN_MP_SET_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_EXPT_D_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_SQR_C +| | | +--->BN_MP_TOOM_SQR_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_KARATSUBA_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_FAST_S_MP_SQR_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MUL_C +| | | +--->BN_MP_TOOM_MUL_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_KARATSUBA_MUL_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| +--->BN_MP_MUL_C +| | +--->BN_MP_TOOM_MUL_C +| | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_KARATSUBA_MUL_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_MUL_DIGS_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_MUL_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_CMP_C +| | +--->BN_MP_CMP_MAG_C +| +--->BN_MP_SUB_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_ZERO_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_RSHD_C ++--->BN_MP_DIV_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_SET_C +| +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_ABS_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_SIZE_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_MUL_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_ADD_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_DIV_2_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_MAG_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_CMP_D_C + + +BN_MP_EXCH_C + + +BN_MP_IS_SQUARE_C ++--->BN_MP_MOD_D_C +| +--->BN_MP_DIV_D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_INIT_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_INIT_SET_INT_C +| +--->BN_MP_INIT_C +| +--->BN_MP_SET_INT_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_MOD_C +| +--->BN_MP_INIT_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_GET_INT_C ++--->BN_MP_SQRT_C +| +--->BN_MP_N_ROOT_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_SET_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_EXPT_D_C +| | | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_SQR_C +| | | | +--->BN_MP_TOOM_SQR_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_KARATSUBA_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_FAST_S_MP_SQR_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_MUL_C +| | | +--->BN_MP_TOOM_MUL_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_KARATSUBA_MUL_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_ABS_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_CMP_C +| | | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_SUB_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_2_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_SQR_C +| +--->BN_MP_TOOM_SQR_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_KARATSUBA_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | +--->BN_MP_ADD_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_SQR_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_CMP_MAG_C ++--->BN_MP_CLEAR_C + + +BN_MP_NEG_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C + + +BN_MP_EXPTMOD_C ++--->BN_MP_INIT_C ++--->BN_MP_INVMOD_C +| +--->BN_FAST_MP_INVMOD_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_MOD_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_SET_C +| | | | +--->BN_MP_COUNT_BITS_C +| | | | +--->BN_MP_ABS_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2D_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_COPY_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_SET_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_CMP_D_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_INVMOD_SLOW_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_SET_C +| | | | +--->BN_MP_COUNT_BITS_C +| | | | +--->BN_MP_ABS_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2D_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_COPY_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_SET_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_CMP_D_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_C ++--->BN_MP_ABS_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_CLEAR_MULTI_C ++--->BN_MP_REDUCE_IS_2K_L_C ++--->BN_S_MP_EXPTMOD_C +| +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_REDUCE_SETUP_C +| | +--->BN_MP_2EXPT_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_DIV_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_SET_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_REDUCE_C +| | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_C +| | | +--->BN_MP_TOOM_MUL_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_MUL_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_S_MP_MUL_HIGH_DIGS_C +| | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_MUL_DIGS_C +| | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_D_C +| | +--->BN_MP_SET_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_REDUCE_2K_SETUP_L_C +| | +--->BN_MP_2EXPT_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_GROW_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_REDUCE_2K_L_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_MUL_C +| | | +--->BN_MP_TOOM_MUL_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_MUL_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_MOD_C +| | +--->BN_MP_DIV_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_SET_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_SQR_C +| | +--->BN_MP_TOOM_SQR_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_KARATSUBA_SQR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | +--->BN_FAST_S_MP_SQR_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SQR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| +--->BN_MP_MUL_C +| | +--->BN_MP_TOOM_MUL_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_KARATSUBA_MUL_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_MUL_DIGS_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| +--->BN_MP_SET_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_EXCH_C ++--->BN_MP_DR_IS_MODULUS_C ++--->BN_MP_REDUCE_IS_2K_C +| +--->BN_MP_REDUCE_2K_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_COUNT_BITS_C ++--->BN_MP_EXPTMOD_FAST_C +| +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_MONTGOMERY_SETUP_C +| +--->BN_FAST_MP_MONTGOMERY_REDUCE_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| +--->BN_MP_MONTGOMERY_REDUCE_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| +--->BN_MP_DR_SETUP_C +| +--->BN_MP_DR_REDUCE_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| +--->BN_MP_REDUCE_2K_SETUP_C +| | +--->BN_MP_2EXPT_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_GROW_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_REDUCE_2K_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +| | +--->BN_MP_2EXPT_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_SET_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_MULMOD_C +| | +--->BN_MP_MUL_C +| | | +--->BN_MP_TOOM_MUL_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_MUL_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_MOD_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_SET_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2D_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_COPY_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| +--->BN_MP_SET_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_MOD_C +| | +--->BN_MP_DIV_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_SQR_C +| | +--->BN_MP_TOOM_SQR_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_KARATSUBA_SQR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | +--->BN_FAST_S_MP_SQR_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SQR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| +--->BN_MP_MUL_C +| | +--->BN_MP_TOOM_MUL_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_KARATSUBA_MUL_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_MUL_DIGS_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| +--->BN_MP_EXCH_C + + +BN_MP_OR_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_ZERO_C + + +BN_MP_GROW_C + + +BN_MP_COUNT_BITS_C + + +BN_MP_PRIME_FERMAT_C ++--->BN_MP_CMP_D_C ++--->BN_MP_INIT_C ++--->BN_MP_EXPTMOD_C +| +--->BN_MP_INVMOD_C +| | +--->BN_FAST_MP_INVMOD_C +| | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_SET_C +| | | | | +--->BN_MP_COUNT_BITS_C +| | | | | +--->BN_MP_ABS_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2D_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_INIT_COPY_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_SET_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INVMOD_SLOW_C +| | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_SET_C +| | | | | +--->BN_MP_COUNT_BITS_C +| | | | | +--->BN_MP_ABS_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2D_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_INIT_COPY_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_SET_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_ABS_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_REDUCE_IS_2K_L_C +| +--->BN_S_MP_EXPTMOD_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_REDUCE_SETUP_C +| | | +--->BN_MP_2EXPT_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_SET_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2D_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_COPY_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_REDUCE_C +| | | +--->BN_MP_INIT_COPY_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_S_MP_MUL_HIGH_DIGS_C +| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SET_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_REDUCE_2K_SETUP_L_C +| | | +--->BN_MP_2EXPT_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_REDUCE_2K_L_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MOD_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_SET_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2D_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_COPY_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_SQR_C +| | | +--->BN_MP_TOOM_SQR_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | +--->BN_FAST_S_MP_SQR_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_MUL_C +| | | +--->BN_MP_TOOM_MUL_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_MUL_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_SET_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_DR_IS_MODULUS_C +| +--->BN_MP_REDUCE_IS_2K_C +| | +--->BN_MP_REDUCE_2K_C +| | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_EXPTMOD_FAST_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_MONTGOMERY_SETUP_C +| | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | +--->BN_MP_MONTGOMERY_REDUCE_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | +--->BN_MP_DR_SETUP_C +| | +--->BN_MP_DR_REDUCE_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | +--->BN_MP_REDUCE_2K_SETUP_C +| | | +--->BN_MP_2EXPT_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_REDUCE_2K_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +| | | +--->BN_MP_2EXPT_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_SET_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MULMOD_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_SET_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2D_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_INIT_COPY_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_SET_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2D_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_COPY_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_SQR_C +| | | +--->BN_MP_TOOM_SQR_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | +--->BN_FAST_S_MP_SQR_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_MUL_C +| | | +--->BN_MP_TOOM_MUL_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_MUL_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C ++--->BN_MP_CMP_C +| +--->BN_MP_CMP_MAG_C ++--->BN_MP_CLEAR_C + + +BN_MP_SUBMOD_C ++--->BN_MP_INIT_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_CLEAR_C ++--->BN_MP_MOD_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C + + +BN_MP_MOD_2D_C ++--->BN_MP_ZERO_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C + + +BN_MP_TORADIX_N_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_DIV_D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_DIV_3_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_SIZE_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_C + + +BN_MP_CMP_C ++--->BN_MP_CMP_MAG_C + + +BNCORE_C + + +BN_MP_TORADIX_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_DIV_D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_DIV_3_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_SIZE_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_C + + +BN_MP_ADD_D_C ++--->BN_MP_GROW_C ++--->BN_MP_SUB_D_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLAMP_C + + +BN_MP_DIV_3_C ++--->BN_MP_INIT_SIZE_C +| +--->BN_MP_INIT_C ++--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_FAST_S_MP_MUL_DIGS_C ++--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C + + +BN_MP_SQRMOD_C ++--->BN_MP_INIT_C ++--->BN_MP_SQR_C +| +--->BN_MP_TOOM_SQR_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_KARATSUBA_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | +--->BN_MP_ADD_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_SQR_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_C ++--->BN_MP_MOD_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C + + +BN_MP_INVMOD_C ++--->BN_FAST_MP_INVMOD_C +| +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_MOD_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_DIV_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_SET_C +| | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_ABS_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_SET_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_DIV_2_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_C +| | +--->BN_MP_CMP_MAG_C +| +--->BN_MP_CMP_D_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_INVMOD_SLOW_C +| +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_MOD_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_DIV_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_SET_C +| | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_ABS_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_SET_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_DIV_2_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_C +| | +--->BN_MP_CMP_MAG_C +| +--->BN_MP_CMP_D_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_CLEAR_C + + +BN_MP_AND_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_MUL_D_C ++--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C + + +BN_FAST_MP_INVMOD_C ++--->BN_MP_INIT_MULTI_C +| +--->BN_MP_INIT_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_MOD_C +| +--->BN_MP_INIT_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_DIV_2_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_C +| +--->BN_MP_CMP_MAG_C ++--->BN_MP_CMP_D_C ++--->BN_MP_ADD_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_CLEAR_C + + +BN_MP_FWRITE_C ++--->BN_MP_RADIX_SIZE_C +| +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_DIV_D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_TORADIX_C +| +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_DIV_D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C + + +BN_S_MP_SQR_C ++--->BN_MP_INIT_SIZE_C +| +--->BN_MP_INIT_C ++--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_N_ROOT_C ++--->BN_MP_INIT_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_EXPT_D_C +| +--->BN_MP_INIT_COPY_C +| +--->BN_MP_SQR_C +| | +--->BN_MP_TOOM_SQR_C +| | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_KARATSUBA_SQR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_FAST_S_MP_SQR_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SQR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_MUL_C +| | +--->BN_MP_TOOM_MUL_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_KARATSUBA_MUL_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_MUL_DIGS_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C ++--->BN_MP_MUL_C +| +--->BN_MP_TOOM_MUL_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_KARATSUBA_MUL_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_MUL_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_DIV_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_ABS_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_SIZE_C +| +--->BN_MP_INIT_COPY_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_CMP_C +| +--->BN_MP_CMP_MAG_C ++--->BN_MP_SUB_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_ADD_D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_PRIME_RABIN_MILLER_TRIALS_C + + +BN_MP_RADIX_SIZE_C ++--->BN_MP_COUNT_BITS_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_DIV_D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_DIV_3_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_SIZE_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_C + + +BN_MP_READ_SIGNED_BIN_C ++--->BN_MP_READ_UNSIGNED_BIN_C +| +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C + + +BN_MP_PRIME_RANDOM_EX_C ++--->BN_MP_READ_UNSIGNED_BIN_C +| +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_PRIME_IS_PRIME_C +| +--->BN_MP_CMP_D_C +| +--->BN_MP_PRIME_IS_DIVISIBLE_C +| | +--->BN_MP_MOD_D_C +| | | +--->BN_MP_DIV_D_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_DIV_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_INIT_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_INIT_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_INIT_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_C +| +--->BN_MP_SET_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_PRIME_MILLER_RABIN_C +| | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_SUB_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CNT_LSB_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXPTMOD_C +| | | +--->BN_MP_INVMOD_C +| | | | +--->BN_FAST_MP_INVMOD_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_MOD_C +| | | | | | +--->BN_MP_DIV_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_COUNT_BITS_C +| | | | | | | +--->BN_MP_ABS_C +| | | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_C +| | | | | | | +--->BN_MP_SUB_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_ADD_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | | | +--->BN_MP_CLEAR_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_MUL_D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CLEAR_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_INVMOD_SLOW_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_MOD_C +| | | | | | +--->BN_MP_DIV_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_COUNT_BITS_C +| | | | | | | +--->BN_MP_ABS_C +| | | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_C +| | | | | | | +--->BN_MP_SUB_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_ADD_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | | | +--->BN_MP_CLEAR_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_MUL_D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CLEAR_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_ABS_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_REDUCE_IS_2K_L_C +| | | +--->BN_S_MP_EXPTMOD_C +| | | | +--->BN_MP_COUNT_BITS_C +| | | | +--->BN_MP_REDUCE_SETUP_C +| | | | | +--->BN_MP_2EXPT_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_DIV_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_REDUCE_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_C +| | | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | | | | +--->BN_MP_COPY_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_MUL_2_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_ADD_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_SUB_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_DIV_2_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_MUL_D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_DIV_3_C +| | | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_MP_EXCH_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_SUB_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_ADD_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_S_MP_MUL_HIGH_DIGS_C +| | | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_REDUCE_2K_SETUP_L_C +| | | | | +--->BN_MP_2EXPT_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_REDUCE_2K_L_C +| | | | | +--->BN_MP_MUL_C +| | | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | | | | +--->BN_MP_COPY_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_MUL_2_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_ADD_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_SUB_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_DIV_2_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_MUL_D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_DIV_3_C +| | | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_MP_EXCH_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_SUB_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_ADD_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MOD_C +| | | | | +--->BN_MP_DIV_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_SQR_C +| | | | | +--->BN_MP_TOOM_SQR_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_MUL_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_3_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_KARATSUBA_SQR_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_FAST_S_MP_SQR_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SQR_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_MUL_C +| | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_MUL_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_3_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_DR_IS_MODULUS_C +| | | +--->BN_MP_REDUCE_IS_2K_C +| | | | +--->BN_MP_REDUCE_2K_C +| | | | | +--->BN_MP_COUNT_BITS_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_EXPTMOD_FAST_C +| | | | +--->BN_MP_COUNT_BITS_C +| | | | +--->BN_MP_MONTGOMERY_SETUP_C +| | | | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_MONTGOMERY_REDUCE_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_DR_SETUP_C +| | | | +--->BN_MP_DR_REDUCE_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_REDUCE_2K_SETUP_C +| | | | | +--->BN_MP_2EXPT_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_REDUCE_2K_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +| | | | | +--->BN_MP_2EXPT_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MULMOD_C +| | | | | +--->BN_MP_MUL_C +| | | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | | | | +--->BN_MP_COPY_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_MUL_2_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_ADD_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_SUB_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_DIV_2_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_MUL_D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_DIV_3_C +| | | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_MP_EXCH_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_SUB_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_ADD_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_MOD_C +| | | | | | +--->BN_MP_DIV_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_C +| | | | | | | +--->BN_MP_SUB_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_ADD_C +| | | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_MUL_D_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_MOD_C +| | | | | +--->BN_MP_DIV_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_SQR_C +| | | | | +--->BN_MP_TOOM_SQR_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_MUL_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_3_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_KARATSUBA_SQR_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_FAST_S_MP_SQR_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SQR_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_MUL_C +| | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_MUL_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_3_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_CMP_C +| | | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_SQRMOD_C +| | | +--->BN_MP_SQR_C +| | | | +--->BN_MP_TOOM_SQR_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_KARATSUBA_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_FAST_S_MP_SQR_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_COUNT_BITS_C +| | | | | +--->BN_MP_ABS_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_SUB_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_ADD_D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_DIV_2_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_MUL_2_C +| +--->BN_MP_GROW_C ++--->BN_MP_ADD_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C + + +BN_MP_KARATSUBA_SQR_C ++--->BN_MP_INIT_SIZE_C +| +--->BN_MP_INIT_C ++--->BN_MP_CLAMP_C ++--->BN_MP_SQR_C +| +--->BN_MP_TOOM_SQR_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_SQR_C +| | +--->BN_MP_GROW_C +| +--->BN_S_MP_SQR_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C ++--->BN_S_MP_ADD_C +| +--->BN_MP_GROW_C ++--->BN_MP_LSHD_C +| +--->BN_MP_GROW_C +| +--->BN_MP_RSHD_C +| | +--->BN_MP_ZERO_C ++--->BN_MP_ADD_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C ++--->BN_MP_CLEAR_C + + +BN_MP_INIT_COPY_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C + + +BN_MP_CLAMP_C + + +BN_MP_TOOM_SQR_C ++--->BN_MP_INIT_MULTI_C +| +--->BN_MP_INIT_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_MOD_2D_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_RSHD_C +| +--->BN_MP_ZERO_C ++--->BN_MP_SQR_C +| +--->BN_MP_KARATSUBA_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_SQR_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_MUL_2_C +| +--->BN_MP_GROW_C ++--->BN_MP_ADD_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_DIV_2_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_MUL_2D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_LSHD_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_MUL_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_DIV_3_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_LSHD_C +| +--->BN_MP_GROW_C ++--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_CLEAR_C + + +BN_MP_MOD_C ++--->BN_MP_INIT_C ++--->BN_MP_DIV_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_SET_C +| +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_ABS_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_SIZE_C +| +--->BN_MP_INIT_COPY_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_MUL_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_C ++--->BN_MP_ADD_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C + + +BN_MP_INIT_C + + +BN_MP_TOOM_MUL_C ++--->BN_MP_INIT_MULTI_C +| +--->BN_MP_INIT_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_MOD_2D_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_RSHD_C +| +--->BN_MP_ZERO_C ++--->BN_MP_MUL_C +| +--->BN_MP_KARATSUBA_MUL_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_MUL_2_C +| +--->BN_MP_GROW_C ++--->BN_MP_ADD_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_DIV_2_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_MUL_2D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_LSHD_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_MUL_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_DIV_3_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_LSHD_C +| +--->BN_MP_GROW_C ++--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_CLEAR_C + + +BN_MP_PRIME_IS_PRIME_C ++--->BN_MP_CMP_D_C ++--->BN_MP_PRIME_IS_DIVISIBLE_C +| +--->BN_MP_MOD_D_C +| | +--->BN_MP_DIV_D_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_INIT_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_INIT_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C ++--->BN_MP_INIT_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_PRIME_MILLER_RABIN_C +| +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_SUB_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CNT_LSB_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_EXPTMOD_C +| | +--->BN_MP_INVMOD_C +| | | +--->BN_FAST_MP_INVMOD_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_MOD_C +| | | | | +--->BN_MP_DIV_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COUNT_BITS_C +| | | | | | +--->BN_MP_ABS_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | | +--->BN_MP_CLEAR_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_INVMOD_SLOW_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_MOD_C +| | | | | +--->BN_MP_DIV_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COUNT_BITS_C +| | | | | | +--->BN_MP_ABS_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | | +--->BN_MP_CLEAR_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_ABS_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_REDUCE_IS_2K_L_C +| | +--->BN_S_MP_EXPTMOD_C +| | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_REDUCE_SETUP_C +| | | | +--->BN_MP_2EXPT_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_REDUCE_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_C +| | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_MUL_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_3_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_S_MP_MUL_HIGH_DIGS_C +| | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_REDUCE_2K_SETUP_L_C +| | | | +--->BN_MP_2EXPT_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_REDUCE_2K_L_C +| | | | +--->BN_MP_MUL_C +| | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_MUL_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_3_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_SQR_C +| | | | +--->BN_MP_TOOM_SQR_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_FAST_S_MP_SQR_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_DR_IS_MODULUS_C +| | +--->BN_MP_REDUCE_IS_2K_C +| | | +--->BN_MP_REDUCE_2K_C +| | | | +--->BN_MP_COUNT_BITS_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_EXPTMOD_FAST_C +| | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_MONTGOMERY_SETUP_C +| | | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_MONTGOMERY_REDUCE_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_DR_SETUP_C +| | | +--->BN_MP_DR_REDUCE_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_REDUCE_2K_SETUP_C +| | | | +--->BN_MP_2EXPT_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_REDUCE_2K_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +| | | | +--->BN_MP_2EXPT_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MULMOD_C +| | | | +--->BN_MP_MUL_C +| | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_MUL_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_3_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_MOD_C +| | | | | +--->BN_MP_DIV_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_SQR_C +| | | | +--->BN_MP_TOOM_SQR_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_FAST_S_MP_SQR_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| +--->BN_MP_CMP_C +| | +--->BN_MP_CMP_MAG_C +| +--->BN_MP_SQRMOD_C +| | +--->BN_MP_SQR_C +| | | +--->BN_MP_TOOM_SQR_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_KARATSUBA_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_FAST_S_MP_SQR_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_COUNT_BITS_C +| | | | +--->BN_MP_ABS_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_C + + +BN_MP_COPY_C ++--->BN_MP_GROW_C + + +BN_S_MP_SUB_C ++--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C + + +BN_MP_READ_UNSIGNED_BIN_C ++--->BN_MP_GROW_C ++--->BN_MP_ZERO_C ++--->BN_MP_MUL_2D_C +| +--->BN_MP_COPY_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLAMP_C + + +BN_MP_EXPTMOD_FAST_C ++--->BN_MP_COUNT_BITS_C ++--->BN_MP_INIT_C ++--->BN_MP_CLEAR_C ++--->BN_MP_MONTGOMERY_SETUP_C ++--->BN_FAST_MP_MONTGOMERY_REDUCE_C +| +--->BN_MP_GROW_C +| +--->BN_MP_RSHD_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C ++--->BN_MP_MONTGOMERY_REDUCE_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_RSHD_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C ++--->BN_MP_DR_SETUP_C ++--->BN_MP_DR_REDUCE_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C ++--->BN_MP_REDUCE_2K_SETUP_C +| +--->BN_MP_2EXPT_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_GROW_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_REDUCE_2K_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_MUL_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +| +--->BN_MP_2EXPT_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_SET_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_MUL_2_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_MULMOD_C +| +--->BN_MP_MUL_C +| | +--->BN_MP_TOOM_MUL_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_KARATSUBA_MUL_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_MUL_DIGS_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| +--->BN_MP_MOD_C +| | +--->BN_MP_DIV_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_SET_C +| | | +--->BN_MP_ABS_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2D_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_MOD_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_SQR_C +| +--->BN_MP_TOOM_SQR_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_KARATSUBA_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | +--->BN_MP_ADD_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| +--->BN_FAST_S_MP_SQR_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C ++--->BN_MP_MUL_C +| +--->BN_MP_TOOM_MUL_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_KARATSUBA_MUL_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C ++--->BN_MP_EXCH_C + + +BN_MP_TO_UNSIGNED_BIN_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_DIV_2D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_SET_INT_C ++--->BN_MP_ZERO_C ++--->BN_MP_MUL_2D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_GROW_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLAMP_C + + +BN_MP_MOD_D_C ++--->BN_MP_DIV_D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_DIV_3_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C + + +BN_MP_SQR_C ++--->BN_MP_TOOM_SQR_C +| +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_RSHD_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_MUL_2_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_2_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_MUL_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_3_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_KARATSUBA_SQR_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| +--->BN_MP_ADD_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_CLEAR_C ++--->BN_FAST_S_MP_SQR_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_S_MP_SQR_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C + + +BN_MP_MULMOD_C ++--->BN_MP_INIT_C ++--->BN_MP_MUL_C +| +--->BN_MP_TOOM_MUL_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_KARATSUBA_MUL_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_C ++--->BN_MP_MOD_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C + + +BN_MP_DIV_2D_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_ZERO_C ++--->BN_MP_INIT_C ++--->BN_MP_MOD_2D_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLEAR_C ++--->BN_MP_RSHD_C ++--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C + + +BN_S_MP_ADD_C ++--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C + + +BN_FAST_S_MP_SQR_C ++--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C + + +BN_S_MP_MUL_DIGS_C ++--->BN_FAST_S_MP_MUL_DIGS_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_INIT_SIZE_C +| +--->BN_MP_INIT_C ++--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_XOR_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_RADIX_SMAP_C + + +BN_MP_DR_IS_MODULUS_C + + +BN_MP_MONTGOMERY_CALC_NORMALIZATION_C ++--->BN_MP_COUNT_BITS_C ++--->BN_MP_2EXPT_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_GROW_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_MUL_2_C +| +--->BN_MP_GROW_C ++--->BN_MP_CMP_MAG_C ++--->BN_S_MP_SUB_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C + + +BN_MP_SUB_C ++--->BN_S_MP_ADD_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_MAG_C ++--->BN_S_MP_SUB_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C + + +BN_MP_INIT_MULTI_C ++--->BN_MP_INIT_C ++--->BN_MP_CLEAR_C + + +BN_S_MP_MUL_HIGH_DIGS_C ++--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_INIT_SIZE_C +| +--->BN_MP_INIT_C ++--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_PRIME_NEXT_PRIME_C ++--->BN_MP_CMP_D_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_SUB_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_ADD_D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_MOD_D_C +| +--->BN_MP_DIV_D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_INIT_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_INIT_C ++--->BN_MP_ADD_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_PRIME_MILLER_RABIN_C +| +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_CNT_LSB_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_EXPTMOD_C +| | +--->BN_MP_INVMOD_C +| | | +--->BN_FAST_MP_INVMOD_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_MOD_C +| | | | | +--->BN_MP_DIV_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COUNT_BITS_C +| | | | | | +--->BN_MP_ABS_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | | +--->BN_MP_CLEAR_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_INVMOD_SLOW_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_MOD_C +| | | | | +--->BN_MP_DIV_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COUNT_BITS_C +| | | | | | +--->BN_MP_ABS_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | | +--->BN_MP_CLEAR_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_ABS_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_REDUCE_IS_2K_L_C +| | +--->BN_S_MP_EXPTMOD_C +| | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_REDUCE_SETUP_C +| | | | +--->BN_MP_2EXPT_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_REDUCE_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_C +| | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_MUL_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_3_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_S_MP_MUL_HIGH_DIGS_C +| | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_REDUCE_2K_SETUP_L_C +| | | | +--->BN_MP_2EXPT_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_REDUCE_2K_L_C +| | | | +--->BN_MP_MUL_C +| | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_MUL_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_3_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_SQR_C +| | | | +--->BN_MP_TOOM_SQR_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_FAST_S_MP_SQR_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_DR_IS_MODULUS_C +| | +--->BN_MP_REDUCE_IS_2K_C +| | | +--->BN_MP_REDUCE_2K_C +| | | | +--->BN_MP_COUNT_BITS_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_EXPTMOD_FAST_C +| | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_MONTGOMERY_SETUP_C +| | | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_MONTGOMERY_REDUCE_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_DR_SETUP_C +| | | +--->BN_MP_DR_REDUCE_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_REDUCE_2K_SETUP_C +| | | | +--->BN_MP_2EXPT_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_REDUCE_2K_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +| | | | +--->BN_MP_2EXPT_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MULMOD_C +| | | | +--->BN_MP_MUL_C +| | | | | +--->BN_MP_TOOM_MUL_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MOD_2D_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | | +--->BN_MP_COPY_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_MUL_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_2_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_DIV_3_C +| | | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_MOD_C +| | | | | +--->BN_MP_DIV_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_INIT_MULTI_C +| | | | | | +--->BN_MP_MUL_2D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_LSHD_C +| | | | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_C +| | | | | | +--->BN_MP_SUB_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_ADD_C +| | | | | | | +--->BN_S_MP_ADD_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | | +--->BN_S_MP_SUB_C +| | | | | | | | +--->BN_MP_GROW_C +| | | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_MUL_D_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_SQR_C +| | | | +--->BN_MP_TOOM_SQR_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_FAST_S_MP_SQR_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SQR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_EXCH_C +| +--->BN_MP_CMP_C +| | +--->BN_MP_CMP_MAG_C +| +--->BN_MP_SQRMOD_C +| | +--->BN_MP_SQR_C +| | | +--->BN_MP_TOOM_SQR_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_KARATSUBA_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_FAST_S_MP_SQR_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_COUNT_BITS_C +| | | | +--->BN_MP_ABS_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_C + + +BN_MP_SIGNED_BIN_SIZE_C ++--->BN_MP_UNSIGNED_BIN_SIZE_C +| +--->BN_MP_COUNT_BITS_C + + +BN_MP_INVMOD_SLOW_C ++--->BN_MP_INIT_MULTI_C +| +--->BN_MP_INIT_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_MOD_C +| +--->BN_MP_INIT_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_DIV_2_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_ADD_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_C +| +--->BN_MP_CMP_MAG_C ++--->BN_MP_CMP_D_C ++--->BN_MP_CMP_MAG_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_CLEAR_C + + +BN_MP_LCM_C ++--->BN_MP_INIT_MULTI_C +| +--->BN_MP_INIT_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_GCD_C +| +--->BN_MP_ABS_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_CNT_LSB_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_MP_EXCH_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_CMP_MAG_C ++--->BN_MP_DIV_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_SET_C +| +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_ABS_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_INIT_C +| +--->BN_MP_INIT_COPY_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_MUL_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_MUL_C +| +--->BN_MP_TOOM_MUL_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_KARATSUBA_MUL_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_CLEAR_C + + +BN_MP_REDUCE_2K_L_C ++--->BN_MP_INIT_C ++--->BN_MP_COUNT_BITS_C ++--->BN_MP_DIV_2D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_MUL_C +| +--->BN_MP_TOOM_MUL_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_KARATSUBA_MUL_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_S_MP_ADD_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_MAG_C ++--->BN_S_MP_SUB_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLEAR_C + + +BN_REVERSE_C + + +BN_MP_PRIME_IS_DIVISIBLE_C ++--->BN_MP_MOD_D_C +| +--->BN_MP_DIV_D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_INIT_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C + + +BN_MP_SET_C ++--->BN_MP_ZERO_C + + +BN_MP_GCD_C ++--->BN_MP_ABS_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_ZERO_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_CNT_LSB_C ++--->BN_MP_DIV_2D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_CMP_MAG_C ++--->BN_MP_EXCH_C ++--->BN_S_MP_SUB_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_MUL_2D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_GROW_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLEAR_C + + +BN_MP_REDUCE_2K_SETUP_L_C ++--->BN_MP_INIT_C ++--->BN_MP_2EXPT_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_GROW_C ++--->BN_MP_COUNT_BITS_C ++--->BN_S_MP_SUB_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLEAR_C + + +BN_MP_READ_RADIX_C ++--->BN_MP_ZERO_C ++--->BN_MP_MUL_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_ADD_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_SUB_D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C + + +BN_FAST_S_MP_MUL_HIGH_DIGS_C ++--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C + + +BN_FAST_MP_MONTGOMERY_REDUCE_C ++--->BN_MP_GROW_C ++--->BN_MP_RSHD_C +| +--->BN_MP_ZERO_C ++--->BN_MP_CLAMP_C ++--->BN_MP_CMP_MAG_C ++--->BN_S_MP_SUB_C + + +BN_MP_DIV_D_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_DIV_2D_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_INIT_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_DIV_3_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_INIT_SIZE_C +| +--->BN_MP_INIT_C ++--->BN_MP_CLAMP_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_REDUCE_2K_SETUP_C ++--->BN_MP_INIT_C ++--->BN_MP_COUNT_BITS_C ++--->BN_MP_2EXPT_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_GROW_C ++--->BN_MP_CLEAR_C ++--->BN_S_MP_SUB_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C + + +BN_MP_INIT_SET_C ++--->BN_MP_INIT_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C + + +BN_MP_REDUCE_2K_C ++--->BN_MP_INIT_C ++--->BN_MP_COUNT_BITS_C ++--->BN_MP_DIV_2D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_MUL_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_S_MP_ADD_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_MAG_C ++--->BN_S_MP_SUB_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLEAR_C + + +BN_ERROR_C + + +BN_MP_EXPT_D_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_SQR_C +| +--->BN_MP_TOOM_SQR_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_KARATSUBA_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | +--->BN_MP_ADD_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_SQR_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_CLEAR_C ++--->BN_MP_MUL_C +| +--->BN_MP_TOOM_MUL_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_KARATSUBA_MUL_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C + + +BN_S_MP_EXPTMOD_C ++--->BN_MP_COUNT_BITS_C ++--->BN_MP_INIT_C ++--->BN_MP_CLEAR_C ++--->BN_MP_REDUCE_SETUP_C +| +--->BN_MP_2EXPT_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_REDUCE_C +| +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_RSHD_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_MUL_C +| | +--->BN_MP_TOOM_MUL_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_KARATSUBA_MUL_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_MUL_DIGS_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| +--->BN_S_MP_MUL_HIGH_DIGS_C +| | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_D_C +| +--->BN_MP_SET_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_C +| | +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_REDUCE_2K_SETUP_L_C +| +--->BN_MP_2EXPT_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_GROW_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_REDUCE_2K_L_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_MUL_C +| | +--->BN_MP_TOOM_MUL_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_KARATSUBA_MUL_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_MUL_DIGS_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_MOD_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_SQR_C +| +--->BN_MP_TOOM_SQR_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_KARATSUBA_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | +--->BN_MP_ADD_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| +--->BN_FAST_S_MP_SQR_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_SQR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C ++--->BN_MP_MUL_C +| +--->BN_MP_TOOM_MUL_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_KARATSUBA_MUL_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_EXCH_C + + +BN_MP_ABS_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C + + +BN_MP_INIT_SET_INT_C ++--->BN_MP_INIT_C ++--->BN_MP_SET_INT_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C + + +BN_MP_SUB_D_C ++--->BN_MP_GROW_C ++--->BN_MP_ADD_D_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLAMP_C + + +BN_MP_TO_SIGNED_BIN_C ++--->BN_MP_TO_UNSIGNED_BIN_C +| +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C + + +BN_MP_DIV_2_C ++--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C + + +BN_MP_REDUCE_IS_2K_C ++--->BN_MP_REDUCE_2K_C +| +--->BN_MP_INIT_C +| +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_MUL_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_COUNT_BITS_C + + +BN_MP_INIT_SIZE_C ++--->BN_MP_INIT_C + + +BN_MP_DIV_C ++--->BN_MP_CMP_MAG_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_ZERO_C ++--->BN_MP_INIT_MULTI_C +| +--->BN_MP_INIT_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_SET_C ++--->BN_MP_COUNT_BITS_C ++--->BN_MP_ABS_C ++--->BN_MP_MUL_2D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_ADD_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_DIV_2D_C +| +--->BN_MP_INIT_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_INIT_SIZE_C +| +--->BN_MP_INIT_C ++--->BN_MP_INIT_C ++--->BN_MP_INIT_COPY_C ++--->BN_MP_LSHD_C +| +--->BN_MP_GROW_C +| +--->BN_MP_RSHD_C ++--->BN_MP_RSHD_C ++--->BN_MP_MUL_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLAMP_C ++--->BN_MP_CLEAR_C + + +BN_MP_CLEAR_C + + +BN_MP_MONTGOMERY_REDUCE_C ++--->BN_FAST_MP_MONTGOMERY_REDUCE_C +| +--->BN_MP_GROW_C +| +--->BN_MP_RSHD_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C ++--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C ++--->BN_MP_RSHD_C +| +--->BN_MP_ZERO_C ++--->BN_MP_CMP_MAG_C ++--->BN_S_MP_SUB_C + + +BN_MP_MUL_2_C ++--->BN_MP_GROW_C + + +BN_MP_UNSIGNED_BIN_SIZE_C ++--->BN_MP_COUNT_BITS_C + + +BN_MP_ADDMOD_C ++--->BN_MP_INIT_C ++--->BN_MP_ADD_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_CLEAR_C ++--->BN_MP_MOD_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C + + +BN_MP_ADD_C ++--->BN_S_MP_ADD_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_MAG_C ++--->BN_S_MP_SUB_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C + + +BN_MP_TO_SIGNED_BIN_N_C ++--->BN_MP_SIGNED_BIN_SIZE_C +| +--->BN_MP_UNSIGNED_BIN_SIZE_C +| | +--->BN_MP_COUNT_BITS_C ++--->BN_MP_TO_SIGNED_BIN_C +| +--->BN_MP_TO_UNSIGNED_BIN_C +| | +--->BN_MP_INIT_COPY_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C + + +BN_MP_REDUCE_IS_2K_L_C + + +BN_MP_RAND_C ++--->BN_MP_ZERO_C ++--->BN_MP_ADD_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_SUB_D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_LSHD_C +| +--->BN_MP_GROW_C +| +--->BN_MP_RSHD_C + + +BN_MP_CNT_LSB_C + + +BN_MP_2EXPT_C ++--->BN_MP_ZERO_C ++--->BN_MP_GROW_C + + +BN_MP_RSHD_C ++--->BN_MP_ZERO_C + + +BN_MP_SHRINK_C + + +BN_MP_TO_UNSIGNED_BIN_N_C ++--->BN_MP_UNSIGNED_BIN_SIZE_C +| +--->BN_MP_COUNT_BITS_C ++--->BN_MP_TO_UNSIGNED_BIN_C +| +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C + + +BN_MP_REDUCE_C ++--->BN_MP_REDUCE_SETUP_C +| +--->BN_MP_2EXPT_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2D_C +| | | +--->BN_MP_INIT_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_INIT_COPY_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_RSHD_C +| +--->BN_MP_ZERO_C ++--->BN_MP_MUL_C +| +--->BN_MP_TOOM_MUL_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_KARATSUBA_MUL_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_S_MP_MUL_HIGH_DIGS_C +| +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_INIT_SIZE_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_MOD_2D_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_S_MP_MUL_DIGS_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_INIT_SIZE_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_D_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_LSHD_C +| +--->BN_MP_GROW_C ++--->BN_MP_ADD_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_C +| +--->BN_MP_CMP_MAG_C ++--->BN_S_MP_SUB_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CLEAR_C + + +BN_MP_MUL_2D_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_GROW_C ++--->BN_MP_LSHD_C +| +--->BN_MP_RSHD_C +| | +--->BN_MP_ZERO_C ++--->BN_MP_CLAMP_C + + +BN_MP_GET_INT_C + + +BN_MP_JACOBI_C ++--->BN_MP_CMP_D_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_CNT_LSB_C ++--->BN_MP_DIV_2D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_MOD_C +| +--->BN_MP_DIV_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_SET_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_ABS_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_CLEAR_MULTI_C ++--->BN_MP_CLEAR_C + + +BN_MP_MUL_C ++--->BN_MP_TOOM_MUL_C +| +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_ZERO_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_RSHD_C +| | +--->BN_MP_ZERO_C +| +--->BN_MP_MUL_2_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_2_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_MUL_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_3_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_KARATSUBA_MUL_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CMP_MAG_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| +--->BN_MP_CLEAR_C ++--->BN_FAST_S_MP_MUL_DIGS_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_S_MP_MUL_DIGS_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_C + + +BN_MP_EXTEUCLID_C ++--->BN_MP_INIT_MULTI_C +| +--->BN_MP_INIT_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_SET_C +| +--->BN_MP_ZERO_C ++--->BN_MP_COPY_C +| +--->BN_MP_GROW_C ++--->BN_MP_DIV_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_ABS_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_INIT_C +| +--->BN_MP_INIT_COPY_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_MUL_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C ++--->BN_MP_MUL_C +| +--->BN_MP_TOOM_MUL_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_KARATSUBA_MUL_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C ++--->BN_MP_NEG_C ++--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_CLEAR_C + + +BN_MP_DR_REDUCE_C ++--->BN_MP_GROW_C ++--->BN_MP_CLAMP_C ++--->BN_MP_CMP_MAG_C ++--->BN_S_MP_SUB_C + + +BN_MP_FREAD_C ++--->BN_MP_ZERO_C ++--->BN_MP_MUL_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_ADD_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_SUB_D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CMP_D_C + + +BN_MP_REDUCE_SETUP_C ++--->BN_MP_2EXPT_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_GROW_C ++--->BN_MP_DIV_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_INIT_MULTI_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_SET_C +| +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_ABS_C +| +--->BN_MP_MUL_2D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CMP_C +| +--->BN_MP_SUB_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_ADD_C +| | +--->BN_S_MP_ADD_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SUB_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| +--->BN_MP_DIV_2D_C +| | +--->BN_MP_INIT_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_CLEAR_C +| | +--->BN_MP_RSHD_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_EXCH_C +| +--->BN_MP_CLEAR_MULTI_C +| | +--->BN_MP_CLEAR_C +| +--->BN_MP_INIT_SIZE_C +| | +--->BN_MP_INIT_C +| +--->BN_MP_INIT_C +| +--->BN_MP_INIT_COPY_C +| +--->BN_MP_LSHD_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_MUL_D_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C + + +BN_MP_MONTGOMERY_SETUP_C + + +BN_MP_KARATSUBA_MUL_C ++--->BN_MP_MUL_C +| +--->BN_MP_TOOM_MUL_C +| | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_MOD_2D_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_RSHD_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MUL_2_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_SUB_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_2_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_2D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MUL_D_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_DIV_3_C +| | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_INIT_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_LSHD_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_FAST_S_MP_MUL_DIGS_C +| | +--->BN_MP_GROW_C +| | +--->BN_MP_CLAMP_C +| +--->BN_S_MP_MUL_DIGS_C +| | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_INIT_C +| | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C +| | +--->BN_MP_CLEAR_C ++--->BN_MP_INIT_SIZE_C +| +--->BN_MP_INIT_C ++--->BN_MP_CLAMP_C ++--->BN_MP_SUB_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C ++--->BN_MP_ADD_C +| +--->BN_S_MP_ADD_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_CMP_MAG_C +| +--->BN_S_MP_SUB_C +| | +--->BN_MP_GROW_C ++--->BN_MP_LSHD_C +| +--->BN_MP_GROW_C +| +--->BN_MP_RSHD_C +| | +--->BN_MP_ZERO_C ++--->BN_MP_CLEAR_C + + +BN_MP_LSHD_C ++--->BN_MP_GROW_C ++--->BN_MP_RSHD_C +| +--->BN_MP_ZERO_C + + +BN_MP_PRIME_MILLER_RABIN_C ++--->BN_MP_CMP_D_C ++--->BN_MP_INIT_COPY_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C ++--->BN_MP_SUB_D_C +| +--->BN_MP_GROW_C +| +--->BN_MP_ADD_D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLAMP_C ++--->BN_MP_CNT_LSB_C ++--->BN_MP_DIV_2D_C +| +--->BN_MP_COPY_C +| | +--->BN_MP_GROW_C +| +--->BN_MP_ZERO_C +| +--->BN_MP_MOD_2D_C +| | +--->BN_MP_CLAMP_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_RSHD_C +| +--->BN_MP_CLAMP_C +| +--->BN_MP_EXCH_C ++--->BN_MP_EXPTMOD_C +| +--->BN_MP_INVMOD_C +| | +--->BN_FAST_MP_INVMOD_C +| | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_SET_C +| | | | | +--->BN_MP_COUNT_BITS_C +| | | | | +--->BN_MP_ABS_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_SET_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_INVMOD_SLOW_C +| | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_SET_C +| | | | | +--->BN_MP_COUNT_BITS_C +| | | | | +--->BN_MP_ABS_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_CLEAR_MULTI_C +| | | | | | +--->BN_MP_CLEAR_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_CLEAR_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_SET_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_ABS_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| +--->BN_MP_CLEAR_MULTI_C +| +--->BN_MP_REDUCE_IS_2K_L_C +| +--->BN_S_MP_EXPTMOD_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_REDUCE_SETUP_C +| | | +--->BN_MP_2EXPT_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_SET_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_REDUCE_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_S_MP_MUL_HIGH_DIGS_C +| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SET_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_REDUCE_2K_SETUP_L_C +| | | +--->BN_MP_2EXPT_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_REDUCE_2K_L_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MOD_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_SET_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_SQR_C +| | | +--->BN_MP_TOOM_SQR_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | +--->BN_FAST_S_MP_SQR_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_MUL_C +| | | +--->BN_MP_TOOM_MUL_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_MUL_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_SET_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_EXCH_C +| +--->BN_MP_DR_IS_MODULUS_C +| +--->BN_MP_REDUCE_IS_2K_C +| | +--->BN_MP_REDUCE_2K_C +| | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_COUNT_BITS_C +| +--->BN_MP_EXPTMOD_FAST_C +| | +--->BN_MP_COUNT_BITS_C +| | +--->BN_MP_MONTGOMERY_SETUP_C +| | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | +--->BN_MP_MONTGOMERY_REDUCE_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | +--->BN_MP_DR_SETUP_C +| | +--->BN_MP_DR_REDUCE_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | +--->BN_MP_REDUCE_2K_SETUP_C +| | | +--->BN_MP_2EXPT_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_REDUCE_2K_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +| | | +--->BN_MP_2EXPT_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_SET_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_MULMOD_C +| | | +--->BN_MP_MUL_C +| | | | +--->BN_MP_TOOM_MUL_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_MOD_2D_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | | +--->BN_MP_COPY_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_MUL_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_2_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_DIV_3_C +| | | | | | +--->BN_MP_INIT_SIZE_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_KARATSUBA_MUL_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CMP_MAG_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_MUL_DIGS_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_MOD_C +| | | | +--->BN_MP_DIV_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_MP_COPY_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_INIT_MULTI_C +| | | | | +--->BN_MP_SET_C +| | | | | +--->BN_MP_MUL_2D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_LSHD_C +| | | | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_C +| | | | | +--->BN_MP_SUB_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_ADD_C +| | | | | | +--->BN_S_MP_ADD_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | | +--->BN_S_MP_SUB_C +| | | | | | | +--->BN_MP_GROW_C +| | | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_MUL_D_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_SET_C +| | | +--->BN_MP_ZERO_C +| | +--->BN_MP_MOD_C +| | | +--->BN_MP_DIV_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | +--->BN_MP_COPY_C +| | | +--->BN_MP_GROW_C +| | +--->BN_MP_SQR_C +| | | +--->BN_MP_TOOM_SQR_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | +--->BN_FAST_S_MP_SQR_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_SQR_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_MUL_C +| | | +--->BN_MP_TOOM_MUL_C +| | | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_MOD_2D_C +| | | | | +--->BN_MP_ZERO_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_MUL_2_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_2_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_2D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_MUL_D_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_DIV_3_C +| | | | | +--->BN_MP_INIT_SIZE_C +| | | | | +--->BN_MP_CLAMP_C +| | | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_KARATSUBA_MUL_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_SUB_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_ADD_C +| | | | | +--->BN_S_MP_ADD_C +| | | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CMP_MAG_C +| | | | | +--->BN_S_MP_SUB_C +| | | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_RSHD_C +| | | | | | +--->BN_MP_ZERO_C +| | | +--->BN_FAST_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_S_MP_MUL_DIGS_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | +--->BN_MP_EXCH_C ++--->BN_MP_CMP_C +| +--->BN_MP_CMP_MAG_C ++--->BN_MP_SQRMOD_C +| +--->BN_MP_SQR_C +| | +--->BN_MP_TOOM_SQR_C +| | | +--->BN_MP_INIT_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_MOD_2D_C +| | | | +--->BN_MP_ZERO_C +| | | | +--->BN_MP_COPY_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_MUL_2_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_2_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_DIV_3_C +| | | | +--->BN_MP_INIT_SIZE_C +| | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_MP_EXCH_C +| | | | +--->BN_MP_CLEAR_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | | +--->BN_MP_CLEAR_C +| | +--->BN_MP_KARATSUBA_SQR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_MP_CMP_MAG_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLEAR_C +| | +--->BN_FAST_S_MP_SQR_C +| | | +--->BN_MP_GROW_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_S_MP_SQR_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_C +| +--->BN_MP_CLEAR_C +| +--->BN_MP_MOD_C +| | +--->BN_MP_DIV_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_MP_COPY_C +| | | | +--->BN_MP_GROW_C +| | | +--->BN_MP_ZERO_C +| | | +--->BN_MP_INIT_MULTI_C +| | | +--->BN_MP_SET_C +| | | +--->BN_MP_COUNT_BITS_C +| | | +--->BN_MP_ABS_C +| | | +--->BN_MP_MUL_2D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_LSHD_C +| | | | | +--->BN_MP_RSHD_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_SUB_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_ADD_C +| | | | +--->BN_S_MP_ADD_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | | +--->BN_S_MP_SUB_C +| | | | | +--->BN_MP_GROW_C +| | | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_EXCH_C +| | | +--->BN_MP_CLEAR_MULTI_C +| | | +--->BN_MP_INIT_SIZE_C +| | | +--->BN_MP_LSHD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_RSHD_C +| | | +--->BN_MP_MUL_D_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_ADD_C +| | | +--->BN_S_MP_ADD_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | | +--->BN_MP_CMP_MAG_C +| | | +--->BN_S_MP_SUB_C +| | | | +--->BN_MP_GROW_C +| | | | +--->BN_MP_CLAMP_C +| | +--->BN_MP_EXCH_C ++--->BN_MP_CLEAR_C + + +BN_MP_DR_SETUP_C + + +BN_MP_CMP_MAG_C + + diff --git a/lib/hcrypto/libtommath/changes.txt b/lib/hcrypto/libtommath/changes.txt new file mode 100644 index 000000000..b0da4da4f --- /dev/null +++ b/lib/hcrypto/libtommath/changes.txt @@ -0,0 +1,397 @@ +March 10th, 2007 +v0.41 -- Wolfgang Ehrhardt suggested a quick fix to mp_div_d() which makes the detection of powers of two quicker. + -- [CRI] Added libtommath.dsp for Visual C++ users. + +December 24th, 2006 +v0.40 -- Updated makefile to properly support LIBNAME + -- Fixed bug in fast_s_mp_mul_high_digs() which overflowed (line 83), thanks Valgrind! + +April 4th, 2006 +v0.39 -- Jim Wigginton pointed out my Montgomery examples in figures 6.4 and 6.6 were off by one, k should be 9 not 8 + -- Bruce Guenter suggested I use --tag=CC for libtool builds where the compiler may think it's C++. + -- "mm" from sci.crypt pointed out that my mp_gcd was sub-optimal (I also updated and corrected the book) + -- updated some of the @@ tags in tommath.src to reflect source changes. + -- updated email and url info in all source files + +Jan 26th, 2006 +v0.38 -- broken makefile.shared fixed + -- removed some carry stores that were not required [updated text] + +November 18th, 2005 +v0.37 -- [Don Porter] reported on a TCL list [HEY SEND ME BUGREPORTS ALREADY!!!] that mp_add_d() would compute -0 with some inputs. Fixed. + -- [rinick@gmail.com] reported the makefile.bcc was messed up. Fixed. + -- [Kevin Kenny] reported some issues with mp_toradix_n(). Now it doesn't require a min of 3 chars of output. + -- Made the make command renamable. Wee + +August 1st, 2005 +v0.36 -- LTM_PRIME_2MSB_ON was fixed and the "OFF" flag was removed. + -- [Peter LaDow] found a typo in the XREALLOC macro + -- [Peter LaDow] pointed out that mp_read_(un)signed_bin should have "const" on the input + -- Ported LTC patch to fix the prime_random_ex() function to get the bitsize correct [and the maskOR flags] + -- Kevin Kenny pointed out a stray // + -- David Hulton pointed out a typo in the textbook [mp_montgomery_setup() pseudo-code] + -- Neal Hamilton (Elliptic Semiconductor) pointed out that my Karatsuba notation was backwards and that I could use + unsigned operations in the routine. + -- Paul Schmidt pointed out a linking error in mp_exptmod() when BN_S_MP_EXPTMOD_C is undefined (and another for read_radix) + -- Updated makefiles to be way more flexible + +March 12th, 2005 +v0.35 -- Stupid XOR function missing line again... oops. + -- Fixed bug in invmod not handling negative inputs correctly [Wolfgang Ehrhardt] + -- Made exteuclid always give positive u3 output...[ Wolfgang Ehrhardt ] + -- [Wolfgang Ehrhardt] Suggested a fix for mp_reduce() which avoided underruns. ;-) + -- mp_rand() would emit one too many digits and it was possible to get a 0 out of it ... oops + -- Added montgomery to the testing to make sure it handles 1..10 digit moduli correctly + -- Fixed bug in comba that would lead to possible erroneous outputs when "pa < digs" + -- Fixed bug in mp_toradix_size for "0" [Kevin Kenny] + -- Updated chapters 1-5 of the textbook ;-) It now talks about the new comba code! + +February 12th, 2005 +v0.34 -- Fixed two more small errors in mp_prime_random_ex() + -- Fixed overflow in mp_mul_d() [Kevin Kenny] + -- Added mp_to_(un)signed_bin_n() functions which do bounds checking for ya [and report the size] + -- Added "large" diminished radix support. Speeds up things like DSA where the moduli is of the form 2^k - P for some P < 2^(k/2) or so + Actually is faster than Montgomery on my AMD64 (and probably much faster on a P4) + -- Updated the manual a bit + -- Ok so I haven't done the textbook work yet... My current freelance gig has landed me in France till the + end of Feb/05. Once I get back I'll have tons of free time and I plan to go to town on the book. + As of this release the API will freeze. At least until the book catches up with all the changes. I welcome + bug reports but new algorithms will have to wait. + +December 23rd, 2004 +v0.33 -- Fixed "small" variant for mp_div() which would munge with negative dividends... + -- Fixed bug in mp_prime_random_ex() which would set the most significant byte to zero when + no special flags were set + -- Fixed overflow [minor] bug in fast_s_mp_sqr() + -- Made the makefiles easier to configure the group/user that ltm will install as + -- Fixed "final carry" bug in comba multipliers. (Volkan Ceylan) + -- Matt Johnston pointed out a missing semi-colon in mp_exptmod + +October 29th, 2004 +v0.32 -- Added "makefile.shared" for shared object support + -- Added more to the build options/configs in the manual + -- Started the Depends framework, wrote dep.pl to scan deps and + produce "callgraph.txt" ;-) + -- Wrote SC_RSA_1 which will enable close to the minimum required to perform + RSA on 32-bit [or 64-bit] platforms with LibTomCrypt + -- Merged in the small/slower mp_div replacement. You can now toggle which + you want to use as your mp_div() at build time. Saves roughly 8KB or so. + -- Renamed a few files and changed some comments to make depends system work better. + (No changes to function names) + -- Merged in new Combas that perform 2 reads per inner loop instead of the older + 3reads/2writes per inner loop of the old code. Really though if you want speed + learn to use TomsFastMath ;-) + +August 9th, 2004 +v0.31 -- "profiled" builds now :-) new timings for Intel Northwoods + -- Added "pretty" build target + -- Update mp_init() to actually assign 0's instead of relying on calloc() + -- "Wolfgang Ehrhardt" found a bug in mp_mul() where if + you multiply a negative by zero you get negative zero as the result. Oops. + -- J Harper from PeerSec let me toy with his AMD64 and I got 60-bit digits working properly + [this also means that I fixed a bug where if sizeof(int) < sizeof(mp_digit) it would bug] + +April 11th, 2004 +v0.30 -- Added "mp_toradix_n" which stores upto "n-1" least significant digits of an mp_int + -- Johan Lindh sent a patch so MSVC wouldn't whine about redefining malloc [in weird dll modes] + -- Henrik Goldman spotted a missing OPT_CAST in mp_fwrite() + -- Tuned tommath.h so that when MP_LOW_MEM is defined MP_PREC shall be reduced. + [I also allow MP_PREC to be externally defined now] + -- Sped up mp_cnt_lsb() by using a 4x4 table [e.g. 4x speedup] + -- Added mp_prime_random_ex() which is a more versatile prime generator accurate to + exact bit lengths (unlike the deprecated but still available mp_prime_random() which + is only accurate to byte lengths). See the new LTM_PRIME_* flags ;-) + -- Alex Polushin contributed an optimized mp_sqrt() as well as mp_get_int() and mp_is_square(). + I've cleaned them all up to be a little more consistent [along with one bug fix] for this release. + -- Added mp_init_set and mp_init_set_int to initialize and set small constants with one function + call. + -- Removed /etclib directory [um LibTomPoly deprecates this]. + -- Fixed mp_mod() so the sign of the result agrees with the sign of the modulus. + ++ N.B. My semester is almost up so expect updates to the textbook to be posted to the libtomcrypt.org + website. + +Jan 25th, 2004 +v0.29 ++ Note: "Henrik" from the v0.28 changelog refers to Henrik Goldman ;-) + -- Added fix to mp_shrink to prevent a realloc when used == 0 [e.g. realloc zero bytes???] + -- Made the mp_prime_rabin_miller_trials() function internal table smaller and also + set the minimum number of tests to two (sounds a bit safer). + -- Added a mp_exteuclid() which computes the extended euclidean algorithm. + -- Fixed a memory leak in s_mp_exptmod() [called when Barrett reduction is to be used] which would arise + if a multiplication or subsequent reduction failed [would not free the temp result]. + -- Made an API change to mp_radix_size(). It now returns an error code and stores the required size + through an "int star" passed to it. + +Dec 24th, 2003 +v0.28 -- Henrik Goldman suggested I add casts to the montomgery code [stores into mu...] so compilers wouldn't + spew [erroneous] diagnostics... fixed. + -- Henrik Goldman also spotted two typos. One in mp_radix_size() and another in mp_toradix(). + -- Added fix to mp_shrink() to avoid a memory leak. + -- Added mp_prime_random() which requires a callback to make truly random primes of a given nature + (idea from chat with Niels Ferguson at Crypto'03) + -- Picked up a second wind. I'm filled with Gooo. Mission Gooo! + -- Removed divisions from mp_reduce_is_2k() + -- Sped up mp_div_d() [general case] to use only one division per digit instead of two. + -- Added the heap macros from LTC to LTM. Now you can easily [by editing four lines of tommath.h] + change the name of the heap functions used in LTM [also compatible with LTC via MPI mode] + -- Added bn_prime_rabin_miller_trials() which gives the number of Rabin-Miller trials to achieve + a failure rate of less than 2^-96 + -- fixed bug in fast_mp_invmod(). The initial testing logic was wrong. An invalid input is not when + "a" and "b" are even it's when "b" is even [the algo is for odd moduli only]. + -- Started a new manual [finally]. It is incomplete and will be finished as time goes on. I had to stop + adding full demos around half way in chapter three so I could at least get a good portion of the + manual done. If you really need help using the library you can always email me! + -- My Textbook is now included as part of the package [all Public Domain] + +Sept 19th, 2003 +v0.27 -- Removed changes.txt~ which was made by accident since "kate" decided it was + a good time to re-enable backups... [kde is fun!] + -- In mp_grow() "a->dp" is not overwritten by realloc call [re: memory leak] + Now if mp_grow() fails the mp_int is still valid and can be cleared via + mp_clear() to reclaim the memory. + -- Henrik Goldman found a buffer overflow bug in mp_add_d(). Fixed. + -- Cleaned up mp_mul_d() to be much easier to read and follow. + +Aug 29th, 2003 +v0.26 -- Fixed typo that caused warning with GCC 3.2 + -- Martin Marcel noticed a bug in mp_neg() that allowed negative zeroes. + Also, Martin is the fellow who noted the bugs in mp_gcd() of 0.24/0.25. + -- Martin Marcel noticed an optimization [and slight bug] in mp_lcm(). + -- Added fix to mp_read_unsigned_bin to prevent a buffer overflow. + -- Beefed up the comments in the baseline multipliers [and montgomery] + -- Added "mont" demo to the makefile.msvc in etc/ + -- Optimized sign compares in mp_cmp from 4 to 2 cases. + +Aug 4th, 2003 +v0.25 -- Fix to mp_gcd again... oops (0,-a) == (-a, 0) == a + -- Fix to mp_clear which didn't reset the sign [Greg Rose] + -- Added mp_error_to_string() to convert return codes to strings. [Greg Rose] + -- Optimized fast_mp_invmod() to do the test for invalid inputs [both even] + first so temps don't have to be initialized if it's going to fail. + -- Optimized mp_gcd() by removing mp_div_2d calls for when one of the inputs + is odd. + -- Tons of new comments, some indentation fixups, etc. + -- mp_jacobi() returns MP_VAL if the modulus is less than or equal to zero. + -- fixed two typos in the header of each file :-) + -- LibTomMath is officially Public Domain [see LICENSE] + +July 15th, 2003 +v0.24 -- Optimized mp_add_d and mp_sub_d to not allocate temporary variables + -- Fixed mp_gcd() so the gcd of 0,0 is 0. Allows the gcd operation to be chained + e.g. (0,0,a) == a [instead of 1] + -- Should be one of the last release for a while. Working on LibTomMath book now. + -- optimized the pprime demo [/etc/pprime.c] to first make a huge table of single + digit primes then it reads them randomly instead of randomly choosing/testing single + digit primes. + +July 12th, 2003 +v0.23 -- Optimized mp_prime_next_prime() to not use mp_mod [via is_divisible()] in each + iteration. Instead now a smaller table is kept of the residues which can be updated + without division. + -- Fixed a bug in next_prime() where an input of zero would be treated as odd and + have two added to it [to move to the next odd]. + -- fixed a bug in prime_fermat() and prime_miller_rabin() which allowed the base + to be negative, zero or one. Normally the test is only valid if the base is + greater than one. + -- changed the next_prime() prototype to accept a new parameter "bbs_style" which + will find the next prime congruent to 3 mod 4. The default [bbs_style==0] will + make primes which are either congruent to 1 or 3 mod 4. + -- fixed mp_read_unsigned_bin() so that it doesn't include both code for + the case DIGIT_BIT < 8 and >= 8 + -- optimized div_d() to easy out on division by 1 [or if a == 0] and use + logical shifts if the divisor is a power of two. + -- the default DIGIT_BIT type was not int for non-default builds. Fixed. + +July 2nd, 2003 +v0.22 -- Fixed up mp_invmod so the result is properly in range now [was always congruent to the inverse...] + -- Fixed up s_mp_exptmod and mp_exptmod_fast so the lower half of the pre-computed table isn't allocated + which makes the algorithm use half as much ram. + -- Fixed the install script not to make the book :-) [which isn't included anyways] + -- added mp_cnt_lsb() which counts how many of the lsbs are zero + -- optimized mp_gcd() to use the new mp_cnt_lsb() to replace multiple divisions by two by a single division. + -- applied similar optimization to mp_prime_miller_rabin(). + -- Fixed a bug in both mp_invmod() and fast_mp_invmod() which tested for odd + via "mp_iseven() == 0" which is not valid [since zero is not even either]. + +June 19th, 2003 +v0.21 -- Fixed bug in mp_mul_d which would not handle sign correctly [would not always forward it] + -- Removed the #line lines from gen.pl [was in violation of ISO C] + +June 8th, 2003 +v0.20 -- Removed the book from the package. Added the TDCAL license document. + -- This release is officially pure-bred TDCAL again [last officially TDCAL based release was v0.16] + +June 6th, 2003 +v0.19 -- Fixed a bug in mp_montgomery_reduce() which was introduced when I tweaked mp_rshd() in the previous release. + Essentially the digits were not trimmed before the compare which cause a subtraction to occur all the time. + -- Fixed up etc/tune.c a bit to stop testing new cutoffs after 16 failures [to find more optimal points]. + Brute force ho! + + +May 29th, 2003 +v0.18 -- Fixed a bug in s_mp_sqr which would handle carries properly just not very elegantly. + (e.g. correct result, just bad looking code) + -- Fixed bug in mp_sqr which still had a 512 constant instead of MP_WARRAY + -- Added Toom-Cook multipliers [needs tuning!] + -- Added efficient divide by 3 algorithm mp_div_3 + -- Re-wrote mp_div_d to be faster than calling mp_div + -- Added in a donated BCC makefile and a single page LTM poster (ahalhabsi@sbcglobal.net) + -- Added mp_reduce_2k which reduces an input modulo n = 2**p - k for any single digit k + -- Made the exptmod system be aware of the 2k reduction algorithms. + -- Rewrote mp_dr_reduce to be smaller, simpler and easier to understand. + +May 17th, 2003 +v0.17 -- Benjamin Goldberg submitted optimized mp_add and mp_sub routines. A new gen.pl as well + as several smaller suggestions. Thanks! + -- removed call to mp_cmp in inner loop of mp_div and put mp_cmp_mag in its place :-) + -- Fixed bug in mp_exptmod that would cause it to fail for odd moduli when DIGIT_BIT != 28 + -- mp_exptmod now also returns errors if the modulus is negative and will handle negative exponents + -- mp_prime_is_prime will now return true if the input is one of the primes in the prime table + -- Damian M Gryski (dgryski@uwaterloo.ca) found a index out of bounds error in the + mp_fast_s_mp_mul_high_digs function which didn't come up before. (fixed) + -- Refactored the DR reduction code so there is only one function per file. + -- Fixed bug in the mp_mul() which would erroneously avoid the faster multiplier [comba] when it was + allowed. The bug would not cause the incorrect value to be produced just less efficient (fixed) + -- Fixed similar bug in the Montgomery reduction code. + -- Added tons of (mp_digit) casts so the 7/15/28/31 bit digit code will work flawlessly out of the box. + Also added limited support for 64-bit machines with a 60-bit digit. Both thanks to Tom Wu (tom@arcot.com) + -- Added new comments here and there, cleaned up some code [style stuff] + -- Fixed a lingering typo in mp_exptmod* that would set bitcnt to zero then one. Very silly stuff :-) + -- Fixed up mp_exptmod_fast so it would set "redux" to the comba Montgomery reduction if allowed. This + saves quite a few calls and if statements. + -- Added etc/mont.c a test of the Montgomery reduction [assuming all else works :-| ] + -- Fixed up etc/tune.c to use a wider test range [more appropriate] also added a x86 based addition which + uses RDTSC for high precision timing. + -- Updated demo/demo.c to remove MPI stuff [won't work anyways], made the tests run for 2 seconds each so its + not so insanely slow. Also made the output space delimited [and fixed up various errors] + -- Added logs directory, logs/graph.dem which will use gnuplot to make a series of PNG files + that go with the pre-made index.html. You have to build [via make timing] and run ltmtest first in the + root of the package. + -- Fixed a bug in mp_sub and mp_add where "-a - -a" or "-a + a" would produce -0 as the result [obviously invalid]. + -- Fixed a bug in mp_rshd. If the count == a.used it should zero/return [instead of shifting] + -- Fixed a "off-by-one" bug in mp_mul2d. The initial size check on alloc would be off by one if the residue + shifting caused a carry. + -- Fixed a bug where s_mp_mul_digs() would not call the Comba based routine if allowed. This made Barrett reduction + slower than it had to be. + +Mar 29th, 2003 +v0.16 -- Sped up mp_div by making normalization one shift call + -- Sped up mp_mul_2d/mp_div_2d by aliasing pointers :-) + -- Cleaned up mp_gcd to use the macros for odd/even detection + -- Added comments here and there, mostly there but occasionally here too. + +Mar 22nd, 2003 +v0.15 -- Added series of prime testing routines to lib + -- Fixed up etc/tune.c + -- Added DR reduction algorithm + -- Beefed up the manual more. + -- Fixed up demo/demo.c so it doesn't have so many warnings and it does the full series of + tests + -- Added "pre-gen" directory which will hold a "gen.pl"'ed copy of the entire lib [done at + zipup time so its always the latest] + -- Added conditional casts for C++ users [boo!] + +Mar 15th, 2003 +v0.14 -- Tons of manual updates + -- cleaned up the directory + -- added MSVC makefiles + -- source changes [that I don't recall] + -- Fixed up the lshd/rshd code to use pointer aliasing + -- Fixed up the mul_2d and div_2d to not call rshd/lshd unless needed + -- Fixed up etc/tune.c a tad + -- fixed up demo/demo.c to output comma-delimited results of timing + also fixed up timing demo to use a finer granularity for various functions + -- fixed up demo/demo.c testing to pause during testing so my Duron won't catch on fire + [stays around 31-35C during testing :-)] + +Feb 13th, 2003 +v0.13 -- tons of minor speed-ups in low level add, sub, mul_2 and div_2 which propagate + to other functions like mp_invmod, mp_div, etc... + -- Sped up mp_exptmod_fast by using new code to find R mod m [e.g. B^n mod m] + -- minor fixes + +Jan 17th, 2003 +v0.12 -- re-wrote the majority of the makefile so its more portable and will + install via "make install" on most *nix platforms + -- Re-packaged all the source as seperate files. Means the library a single + file packagage any more. Instead of just adding "bn.c" you have to add + libtommath.a + -- Renamed "bn.h" to "tommath.h" + -- Changes to the manual to reflect all of this + -- Used GNU Indent to clean up the source + +Jan 15th, 2003 +v0.11 -- More subtle fixes + -- Moved to gentoo linux [hurrah!] so made *nix specific fixes to the make process + -- Sped up the montgomery reduction code quite a bit + -- fixed up demo so when building timing for the x86 it assumes ELF format now + +Jan 9th, 2003 +v0.10 -- Pekka Riikonen suggested fixes to the radix conversion code. + -- Added baseline montgomery and comba montgomery reductions, sped up exptmods + [to a point, see bn.h for MONTGOMERY_EXPT_CUTOFF] + +Jan 6th, 2003 +v0.09 -- Updated the manual to reflect recent changes. :-) + -- Added Jacobi function (mp_jacobi) to supplement the number theory side of the lib + -- Added a Mersenne prime finder demo in ./etc/mersenne.c + +Jan 2nd, 2003 +v0.08 -- Sped up the multipliers by moving the inner loop variables into a smaller scope + -- Corrected a bunch of small "warnings" + -- Added more comments + -- Made "mtest" be able to use /dev/random, /dev/urandom or stdin for RNG data + -- Corrected some bugs where error messages were potentially ignored + -- add etc/pprime.c program which makes numbers which are provably prime. + +Jan 1st, 2003 +v0.07 -- Removed alot of heap operations from core functions to speed them up + -- Added a root finding function [and mp_sqrt macro like from MPI] + -- Added more to manual + +Dec 31st, 2002 +v0.06 -- Sped up the s_mp_add, s_mp_sub which inturn sped up mp_invmod, mp_exptmod, etc... + -- Cleaned up the header a bit more + +Dec 30th, 2002 +v0.05 -- Builds with MSVC out of the box + -- Fixed a bug in mp_invmod w.r.t. even moduli + -- Made mp_toradix and mp_read_radix use char instead of unsigned char arrays + -- Fixed up exptmod to use fewer multiplications + -- Fixed up mp_init_size to use only one heap operation + -- Note there is a slight "off-by-one" bug in the library somewhere + without the padding (see the source for comment) the library + crashes in libtomcrypt. Anyways a reasonable workaround is to pad the + numbers which will always correct it since as the numbers grow the padding + will still be beyond the end of the number + -- Added more to the manual + +Dec 29th, 2002 +v0.04 -- Fixed a memory leak in mp_to_unsigned_bin + -- optimized invmod code + -- Fixed bug in mp_div + -- use exchange instead of copy for results + -- added a bit more to the manual + +Dec 27th, 2002 +v0.03 -- Sped up s_mp_mul_high_digs by not computing the carries of the lower digits + -- Fixed a bug where mp_set_int wouldn't zero the value first and set the used member. + -- fixed a bug in s_mp_mul_high_digs where the limit placed on the result digits was not calculated properly + -- fixed bugs in add/sub/mul/sqr_mod functions where if the modulus and dest were the same it wouldn't work + -- fixed a bug in mp_mod and mp_mod_d concerning negative inputs + -- mp_mul_d didn't preserve sign + -- Many many many many fixes + -- Works in LibTomCrypt now :-) + -- Added iterations to the timing demos... more accurate. + -- Tom needs a job. + +Dec 26th, 2002 +v0.02 -- Fixed a few "slips" in the manual. This is "LibTomMath" afterall :-) + -- Added mp_cmp_mag, mp_neg, mp_abs and mp_radix_size that were missing. + -- Sped up the fast [comba] multipliers more [yahoo!] + +Dec 25th,2002 +v0.01 -- Initial release. Gimme a break. + -- Todo list, + add details to manual [e.g. algorithms] + more comments in code + example programs diff --git a/lib/hcrypto/libtommath/demo/demo.c b/lib/hcrypto/libtommath/demo/demo.c new file mode 100644 index 000000000..bb5eb4401 --- /dev/null +++ b/lib/hcrypto/libtommath/demo/demo.c @@ -0,0 +1,740 @@ +#include + +#ifdef IOWNANATHLON +#include +#define SLEEP sleep(4) +#else +#define SLEEP +#endif + +#include "tommath.h" + +void ndraw(mp_int * a, char *name) +{ + char buf[16000]; + + printf("%s: ", name); + mp_toradix(a, buf, 10); + printf("%s\n", buf); +} + +static void draw(mp_int * a) +{ + ndraw(a, ""); +} + + +unsigned long lfsr = 0xAAAAAAAAUL; + +int lbit(void) +{ + if (lfsr & 0x80000000UL) { + lfsr = ((lfsr << 1) ^ 0x8000001BUL) & 0xFFFFFFFFUL; + return 1; + } else { + lfsr <<= 1; + return 0; + } +} + +int myrng(unsigned char *dst, int len, void *dat) +{ + int x; + + for (x = 0; x < len; x++) + dst[x] = rand() & 0xFF; + return len; +} + + + +char cmd[4096], buf[4096]; +int main(void) +{ + mp_int a, b, c, d, e, f; + unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, + gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n, t; + unsigned rr; + int i, n, err, cnt, ix, old_kara_m, old_kara_s; + mp_digit mp; + + + mp_init(&a); + mp_init(&b); + mp_init(&c); + mp_init(&d); + mp_init(&e); + mp_init(&f); + + srand(time(NULL)); + +#if 0 + // test montgomery + printf("Testing montgomery...\n"); + for (i = 1; i < 10; i++) { + printf("Testing digit size: %d\n", i); + for (n = 0; n < 1000; n++) { + mp_rand(&a, i); + a.dp[0] |= 1; + + // let's see if R is right + mp_montgomery_calc_normalization(&b, &a); + mp_montgomery_setup(&a, &mp); + + // now test a random reduction + for (ix = 0; ix < 100; ix++) { + mp_rand(&c, 1 + abs(rand()) % (2*i)); + mp_copy(&c, &d); + mp_copy(&c, &e); + + mp_mod(&d, &a, &d); + mp_montgomery_reduce(&c, &a, mp); + mp_mulmod(&c, &b, &a, &c); + + if (mp_cmp(&c, &d) != MP_EQ) { +printf("d = e mod a, c = e MOD a\n"); +mp_todecimal(&a, buf); printf("a = %s\n", buf); +mp_todecimal(&e, buf); printf("e = %s\n", buf); +mp_todecimal(&d, buf); printf("d = %s\n", buf); +mp_todecimal(&c, buf); printf("c = %s\n", buf); +printf("compare no compare!\n"); exit(EXIT_FAILURE); } + } + } + } + printf("done\n"); + + // test mp_get_int + printf("Testing: mp_get_int\n"); + for (i = 0; i < 1000; ++i) { + t = ((unsigned long) rand() * rand() + 1) & 0xFFFFFFFF; + mp_set_int(&a, t); + if (t != mp_get_int(&a)) { + printf("mp_get_int() bad result!\n"); + return 1; + } + } + mp_set_int(&a, 0); + if (mp_get_int(&a) != 0) { + printf("mp_get_int() bad result!\n"); + return 1; + } + mp_set_int(&a, 0xffffffff); + if (mp_get_int(&a) != 0xffffffff) { + printf("mp_get_int() bad result!\n"); + return 1; + } + // test mp_sqrt + printf("Testing: mp_sqrt\n"); + for (i = 0; i < 1000; ++i) { + printf("%6d\r", i); + fflush(stdout); + n = (rand() & 15) + 1; + mp_rand(&a, n); + if (mp_sqrt(&a, &b) != MP_OKAY) { + printf("mp_sqrt() error!\n"); + return 1; + } + mp_n_root(&a, 2, &a); + if (mp_cmp_mag(&b, &a) != MP_EQ) { + printf("mp_sqrt() bad result!\n"); + return 1; + } + } + + printf("\nTesting: mp_is_square\n"); + for (i = 0; i < 1000; ++i) { + printf("%6d\r", i); + fflush(stdout); + + /* test mp_is_square false negatives */ + n = (rand() & 7) + 1; + mp_rand(&a, n); + mp_sqr(&a, &a); + if (mp_is_square(&a, &n) != MP_OKAY) { + printf("fn:mp_is_square() error!\n"); + return 1; + } + if (n == 0) { + printf("fn:mp_is_square() bad result!\n"); + return 1; + } + + /* test for false positives */ + mp_add_d(&a, 1, &a); + if (mp_is_square(&a, &n) != MP_OKAY) { + printf("fp:mp_is_square() error!\n"); + return 1; + } + if (n == 1) { + printf("fp:mp_is_square() bad result!\n"); + return 1; + } + + } + printf("\n\n"); + + /* test for size */ + for (ix = 10; ix < 128; ix++) { + printf("Testing (not safe-prime): %9d bits \r", ix); + fflush(stdout); + err = + mp_prime_random_ex(&a, 8, ix, + (rand() & 1) ? LTM_PRIME_2MSB_OFF : + LTM_PRIME_2MSB_ON, myrng, NULL); + if (err != MP_OKAY) { + printf("failed with err code %d\n", err); + return EXIT_FAILURE; + } + if (mp_count_bits(&a) != ix) { + printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix); + return EXIT_FAILURE; + } + } + + for (ix = 16; ix < 128; ix++) { + printf("Testing ( safe-prime): %9d bits \r", ix); + fflush(stdout); + err = + mp_prime_random_ex(&a, 8, ix, + ((rand() & 1) ? LTM_PRIME_2MSB_OFF : + LTM_PRIME_2MSB_ON) | LTM_PRIME_SAFE, myrng, + NULL); + if (err != MP_OKAY) { + printf("failed with err code %d\n", err); + return EXIT_FAILURE; + } + if (mp_count_bits(&a) != ix) { + printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix); + return EXIT_FAILURE; + } + /* let's see if it's really a safe prime */ + mp_sub_d(&a, 1, &a); + mp_div_2(&a, &a); + mp_prime_is_prime(&a, 8, &cnt); + if (cnt != MP_YES) { + printf("sub is not prime!\n"); + return EXIT_FAILURE; + } + } + + printf("\n\n"); + + mp_read_radix(&a, "123456", 10); + mp_toradix_n(&a, buf, 10, 3); + printf("a == %s\n", buf); + mp_toradix_n(&a, buf, 10, 4); + printf("a == %s\n", buf); + mp_toradix_n(&a, buf, 10, 30); + printf("a == %s\n", buf); + + +#if 0 + for (;;) { + fgets(buf, sizeof(buf), stdin); + mp_read_radix(&a, buf, 10); + mp_prime_next_prime(&a, 5, 1); + mp_toradix(&a, buf, 10); + printf("%s, %lu\n", buf, a.dp[0] & 3); + } +#endif + + /* test mp_cnt_lsb */ + printf("testing mp_cnt_lsb...\n"); + mp_set(&a, 1); + for (ix = 0; ix < 1024; ix++) { + if (mp_cnt_lsb(&a) != ix) { + printf("Failed at %d, %d\n", ix, mp_cnt_lsb(&a)); + return 0; + } + mp_mul_2(&a, &a); + } + +/* test mp_reduce_2k */ + printf("Testing mp_reduce_2k...\n"); + for (cnt = 3; cnt <= 128; ++cnt) { + mp_digit tmp; + + mp_2expt(&a, cnt); + mp_sub_d(&a, 2, &a); /* a = 2**cnt - 2 */ + + + printf("\nTesting %4d bits", cnt); + printf("(%d)", mp_reduce_is_2k(&a)); + mp_reduce_2k_setup(&a, &tmp); + printf("(%d)", tmp); + for (ix = 0; ix < 1000; ix++) { + if (!(ix & 127)) { + printf("."); + fflush(stdout); + } + mp_rand(&b, (cnt / DIGIT_BIT + 1) * 2); + mp_copy(&c, &b); + mp_mod(&c, &a, &c); + mp_reduce_2k(&b, &a, 2); + if (mp_cmp(&c, &b)) { + printf("FAILED\n"); + exit(0); + } + } + } + +/* test mp_div_3 */ + printf("Testing mp_div_3...\n"); + mp_set(&d, 3); + for (cnt = 0; cnt < 10000;) { + mp_digit r1, r2; + + if (!(++cnt & 127)) + printf("%9d\r", cnt); + mp_rand(&a, abs(rand()) % 128 + 1); + mp_div(&a, &d, &b, &e); + mp_div_3(&a, &c, &r2); + + if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) { + printf("\n\nmp_div_3 => Failure\n"); + } + } + printf("\n\nPassed div_3 testing\n"); + +/* test the DR reduction */ + printf("testing mp_dr_reduce...\n"); + for (cnt = 2; cnt < 32; cnt++) { + printf("%d digit modulus\n", cnt); + mp_grow(&a, cnt); + mp_zero(&a); + for (ix = 1; ix < cnt; ix++) { + a.dp[ix] = MP_MASK; + } + a.used = cnt; + a.dp[0] = 3; + + mp_rand(&b, cnt - 1); + mp_copy(&b, &c); + + rr = 0; + do { + if (!(rr & 127)) { + printf("%9lu\r", rr); + fflush(stdout); + } + mp_sqr(&b, &b); + mp_add_d(&b, 1, &b); + mp_copy(&b, &c); + + mp_mod(&b, &a, &b); + mp_dr_reduce(&c, &a, (((mp_digit) 1) << DIGIT_BIT) - a.dp[0]); + + if (mp_cmp(&b, &c) != MP_EQ) { + printf("Failed on trial %lu\n", rr); + exit(-1); + + } + } while (++rr < 500); + printf("Passed DR test for %d digits\n", cnt); + } + +#endif + +/* test the mp_reduce_2k_l code */ +#if 0 +#if 0 +/* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */ + mp_2expt(&a, 1024); + mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16); + mp_sub(&a, &b, &a); +#elif 1 +/* p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F */ + mp_2expt(&a, 2048); + mp_read_radix(&b, + "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F", + 16); + mp_sub(&a, &b, &a); +#endif + + mp_todecimal(&a, buf); + printf("p==%s\n", buf); +/* now mp_reduce_is_2k_l() should return */ + if (mp_reduce_is_2k_l(&a) != 1) { + printf("mp_reduce_is_2k_l() return 0, should be 1\n"); + return EXIT_FAILURE; + } + mp_reduce_2k_setup_l(&a, &d); + /* now do a million square+1 to see if it varies */ + mp_rand(&b, 64); + mp_mod(&b, &a, &b); + mp_copy(&b, &c); + printf("testing mp_reduce_2k_l..."); + fflush(stdout); + for (cnt = 0; cnt < (1UL << 20); cnt++) { + mp_sqr(&b, &b); + mp_add_d(&b, 1, &b); + mp_reduce_2k_l(&b, &a, &d); + mp_sqr(&c, &c); + mp_add_d(&c, 1, &c); + mp_mod(&c, &a, &c); + if (mp_cmp(&b, &c) != MP_EQ) { + printf("mp_reduce_2k_l() failed at step %lu\n", cnt); + mp_tohex(&b, buf); + printf("b == %s\n", buf); + mp_tohex(&c, buf); + printf("c == %s\n", buf); + return EXIT_FAILURE; + } + } + printf("...Passed\n"); +#endif + + div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n = + sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n = + sub_d_n = 0; + + /* force KARA and TOOM to enable despite cutoffs */ + KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 8; + TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 16; + + for (;;) { + /* randomly clear and re-init one variable, this has the affect of triming the alloc space */ + switch (abs(rand()) % 7) { + case 0: + mp_clear(&a); + mp_init(&a); + break; + case 1: + mp_clear(&b); + mp_init(&b); + break; + case 2: + mp_clear(&c); + mp_init(&c); + break; + case 3: + mp_clear(&d); + mp_init(&d); + break; + case 4: + mp_clear(&e); + mp_init(&e); + break; + case 5: + mp_clear(&f); + mp_init(&f); + break; + case 6: + break; /* don't clear any */ + } + + + printf + ("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ", + add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n, + expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n); + fgets(cmd, 4095, stdin); + cmd[strlen(cmd) - 1] = 0; + printf("%s ]\r", cmd); + fflush(stdout); + if (!strcmp(cmd, "mul2d")) { + ++mul2d_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + sscanf(buf, "%d", &rr); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + + mp_mul_2d(&a, rr, &a); + a.sign = b.sign; + if (mp_cmp(&a, &b) != MP_EQ) { + printf("mul2d failed, rr == %d\n", rr); + draw(&a); + draw(&b); + return 0; + } + } else if (!strcmp(cmd, "div2d")) { + ++div2d_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + sscanf(buf, "%d", &rr); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + + mp_div_2d(&a, rr, &a, &e); + a.sign = b.sign; + if (a.used == b.used && a.used == 0) { + a.sign = b.sign = MP_ZPOS; + } + if (mp_cmp(&a, &b) != MP_EQ) { + printf("div2d failed, rr == %d\n", rr); + draw(&a); + draw(&b); + return 0; + } + } else if (!strcmp(cmd, "add")) { + ++add_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&c, buf, 64); + mp_copy(&a, &d); + mp_add(&d, &b, &d); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("add %lu failure!\n", add_n); + draw(&a); + draw(&b); + draw(&c); + draw(&d); + return 0; + } + + /* test the sign/unsigned storage functions */ + + rr = mp_signed_bin_size(&c); + mp_to_signed_bin(&c, (unsigned char *) cmd); + memset(cmd + rr, rand() & 255, sizeof(cmd) - rr); + mp_read_signed_bin(&d, (unsigned char *) cmd, rr); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("mp_signed_bin failure!\n"); + draw(&c); + draw(&d); + return 0; + } + + + rr = mp_unsigned_bin_size(&c); + mp_to_unsigned_bin(&c, (unsigned char *) cmd); + memset(cmd + rr, rand() & 255, sizeof(cmd) - rr); + mp_read_unsigned_bin(&d, (unsigned char *) cmd, rr); + if (mp_cmp_mag(&c, &d) != MP_EQ) { + printf("mp_unsigned_bin failure!\n"); + draw(&c); + draw(&d); + return 0; + } + + } else if (!strcmp(cmd, "sub")) { + ++sub_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&c, buf, 64); + mp_copy(&a, &d); + mp_sub(&d, &b, &d); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("sub %lu failure!\n", sub_n); + draw(&a); + draw(&b); + draw(&c); + draw(&d); + return 0; + } + } else if (!strcmp(cmd, "mul")) { + ++mul_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&c, buf, 64); + mp_copy(&a, &d); + mp_mul(&d, &b, &d); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("mul %lu failure!\n", mul_n); + draw(&a); + draw(&b); + draw(&c); + draw(&d); + return 0; + } + } else if (!strcmp(cmd, "div")) { + ++div_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&c, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&d, buf, 64); + + mp_div(&a, &b, &e, &f); + if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) { + printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e), + mp_cmp(&d, &f)); + draw(&a); + draw(&b); + draw(&c); + draw(&d); + draw(&e); + draw(&f); + return 0; + } + + } else if (!strcmp(cmd, "sqr")) { + ++sqr_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + mp_copy(&a, &c); + mp_sqr(&c, &c); + if (mp_cmp(&b, &c) != MP_EQ) { + printf("sqr %lu failure!\n", sqr_n); + draw(&a); + draw(&b); + draw(&c); + return 0; + } + } else if (!strcmp(cmd, "gcd")) { + ++gcd_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&c, buf, 64); + mp_copy(&a, &d); + mp_gcd(&d, &b, &d); + d.sign = c.sign; + if (mp_cmp(&c, &d) != MP_EQ) { + printf("gcd %lu failure!\n", gcd_n); + draw(&a); + draw(&b); + draw(&c); + draw(&d); + return 0; + } + } else if (!strcmp(cmd, "lcm")) { + ++lcm_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&c, buf, 64); + mp_copy(&a, &d); + mp_lcm(&d, &b, &d); + d.sign = c.sign; + if (mp_cmp(&c, &d) != MP_EQ) { + printf("lcm %lu failure!\n", lcm_n); + draw(&a); + draw(&b); + draw(&c); + draw(&d); + return 0; + } + } else if (!strcmp(cmd, "expt")) { + ++expt_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&c, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&d, buf, 64); + mp_copy(&a, &e); + mp_exptmod(&e, &b, &c, &e); + if (mp_cmp(&d, &e) != MP_EQ) { + printf("expt %lu failure!\n", expt_n); + draw(&a); + draw(&b); + draw(&c); + draw(&d); + draw(&e); + return 0; + } + } else if (!strcmp(cmd, "invmod")) { + ++inv_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&c, buf, 64); + mp_invmod(&a, &b, &d); + mp_mulmod(&d, &a, &b, &e); + if (mp_cmp_d(&e, 1) != MP_EQ) { + printf("inv [wrong value from MPI?!] failure\n"); + draw(&a); + draw(&b); + draw(&c); + draw(&d); + mp_gcd(&a, &b, &e); + draw(&e); + return 0; + } + + } else if (!strcmp(cmd, "div2")) { + ++div2_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + mp_div_2(&a, &c); + if (mp_cmp(&c, &b) != MP_EQ) { + printf("div_2 %lu failure\n", div2_n); + draw(&a); + draw(&b); + draw(&c); + return 0; + } + } else if (!strcmp(cmd, "mul2")) { + ++mul2_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + mp_mul_2(&a, &c); + if (mp_cmp(&c, &b) != MP_EQ) { + printf("mul_2 %lu failure\n", mul2_n); + draw(&a); + draw(&b); + draw(&c); + return 0; + } + } else if (!strcmp(cmd, "add_d")) { + ++add_d_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + sscanf(buf, "%d", &ix); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + mp_add_d(&a, ix, &c); + if (mp_cmp(&b, &c) != MP_EQ) { + printf("add_d %lu failure\n", add_d_n); + draw(&a); + draw(&b); + draw(&c); + printf("d == %d\n", ix); + return 0; + } + } else if (!strcmp(cmd, "sub_d")) { + ++sub_d_n; + fgets(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + fgets(buf, 4095, stdin); + sscanf(buf, "%d", &ix); + fgets(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + mp_sub_d(&a, ix, &c); + if (mp_cmp(&b, &c) != MP_EQ) { + printf("sub_d %lu failure\n", sub_d_n); + draw(&a); + draw(&b); + draw(&c); + printf("d == %d\n", ix); + return 0; + } + } + } + return 0; +} + +/* $Source: /cvs/libtom/libtommath/demo/demo.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2005/06/24 11:32:07 $ */ diff --git a/lib/hcrypto/libtommath/demo/timing.c b/lib/hcrypto/libtommath/demo/timing.c new file mode 100644 index 000000000..d4660a9b5 --- /dev/null +++ b/lib/hcrypto/libtommath/demo/timing.c @@ -0,0 +1,319 @@ +#include +#include + +ulong64 _tt; + +#ifdef IOWNANATHLON +#include +#define SLEEP sleep(4) +#else +#define SLEEP +#endif + + +void ndraw(mp_int * a, char *name) +{ + char buf[4096]; + + printf("%s: ", name); + mp_toradix(a, buf, 64); + printf("%s\n", buf); +} + +static void draw(mp_int * a) +{ + ndraw(a, ""); +} + + +unsigned long lfsr = 0xAAAAAAAAUL; + +int lbit(void) +{ + if (lfsr & 0x80000000UL) { + lfsr = ((lfsr << 1) ^ 0x8000001BUL) & 0xFFFFFFFFUL; + return 1; + } else { + lfsr <<= 1; + return 0; + } +} + +/* RDTSC from Scott Duplichan */ +static ulong64 TIMFUNC(void) +{ +#if defined __GNUC__ +#if defined(__i386__) || defined(__x86_64__) + unsigned long long a; + __asm__ __volatile__("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n":: + "m"(a):"%eax", "%edx"); + return a; +#else /* gcc-IA64 version */ + unsigned long result; + __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory"); + + while (__builtin_expect((int) result == -1, 0)) + __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory"); + + return result; +#endif + + // Microsoft and Intel Windows compilers +#elif defined _M_IX86 + __asm rdtsc +#elif defined _M_AMD64 + return __rdtsc(); +#elif defined _M_IA64 +#if defined __INTEL_COMPILER +#include +#endif + return __getReg(3116); +#else +#error need rdtsc function for this build +#endif +} + +#define DO(x) x; x; +//#define DO4(x) DO2(x); DO2(x); +//#define DO8(x) DO4(x); DO4(x); +//#define DO(x) DO8(x); DO8(x); + +int main(void) +{ + ulong64 tt, gg, CLK_PER_SEC; + FILE *log, *logb, *logc, *logd; + mp_int a, b, c, d, e, f; + int n, cnt, ix, old_kara_m, old_kara_s; + unsigned rr; + + mp_init(&a); + mp_init(&b); + mp_init(&c); + mp_init(&d); + mp_init(&e); + mp_init(&f); + + srand(time(NULL)); + + + /* temp. turn off TOOM */ + TOOM_MUL_CUTOFF = TOOM_SQR_CUTOFF = 100000; + + CLK_PER_SEC = TIMFUNC(); + sleep(1); + CLK_PER_SEC = TIMFUNC() - CLK_PER_SEC; + + printf("CLK_PER_SEC == %llu\n", CLK_PER_SEC); + goto exptmod; + log = fopen("logs/add.log", "w"); + for (cnt = 8; cnt <= 128; cnt += 8) { + SLEEP; + mp_rand(&a, cnt); + mp_rand(&b, cnt); + rr = 0; + tt = -1; + do { + gg = TIMFUNC(); + DO(mp_add(&a, &b, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100000); + printf("Adding\t\t%4d-bit => %9llu/sec, %9llu cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + fprintf(log, "%d %9llu\n", cnt * DIGIT_BIT, tt); + fflush(log); + } + fclose(log); + + log = fopen("logs/sub.log", "w"); + for (cnt = 8; cnt <= 128; cnt += 8) { + SLEEP; + mp_rand(&a, cnt); + mp_rand(&b, cnt); + rr = 0; + tt = -1; + do { + gg = TIMFUNC(); + DO(mp_sub(&a, &b, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100000); + + printf("Subtracting\t\t%4d-bit => %9llu/sec, %9llu cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + fprintf(log, "%d %9llu\n", cnt * DIGIT_BIT, tt); + fflush(log); + } + fclose(log); + + /* do mult/square twice, first without karatsuba and second with */ + multtest: + old_kara_m = KARATSUBA_MUL_CUTOFF; + old_kara_s = KARATSUBA_SQR_CUTOFF; + for (ix = 0; ix < 2; ix++) { + printf("With%s Karatsuba\n", (ix == 0) ? "out" : ""); + + KARATSUBA_MUL_CUTOFF = (ix == 0) ? 9999 : old_kara_m; + KARATSUBA_SQR_CUTOFF = (ix == 0) ? 9999 : old_kara_s; + + log = fopen((ix == 0) ? "logs/mult.log" : "logs/mult_kara.log", "w"); + for (cnt = 4; cnt <= 10240 / DIGIT_BIT; cnt += 2) { + SLEEP; + mp_rand(&a, cnt); + mp_rand(&b, cnt); + rr = 0; + tt = -1; + do { + gg = TIMFUNC(); + DO(mp_mul(&a, &b, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100); + printf("Multiplying\t%4d-bit => %9llu/sec, %9llu cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + fprintf(log, "%d %9llu\n", mp_count_bits(&a), tt); + fflush(log); + } + fclose(log); + + log = fopen((ix == 0) ? "logs/sqr.log" : "logs/sqr_kara.log", "w"); + for (cnt = 4; cnt <= 10240 / DIGIT_BIT; cnt += 2) { + SLEEP; + mp_rand(&a, cnt); + rr = 0; + tt = -1; + do { + gg = TIMFUNC(); + DO(mp_sqr(&a, &b)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100); + printf("Squaring\t%4d-bit => %9llu/sec, %9llu cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + fprintf(log, "%d %9llu\n", mp_count_bits(&a), tt); + fflush(log); + } + fclose(log); + + } + exptmod: + + { + char *primes[] = { + /* 2K large moduli */ + "179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586239334100047359817950870678242457666208137217", + "32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638099733077152121140120031150424541696791951097529546801429027668869927491725169", + "1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085902995208257421855249796721729039744118165938433694823325696642096892124547425283", + /* 2K moduli mersenne primes */ + "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", + "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127", + "10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087", + "1475979915214180235084898622737381736312066145333169775147771216478570297878078949377407337049389289382748507531496480477281264838760259191814463365330269540496961201113430156902396093989090226259326935025281409614983499388222831448598601834318536230923772641390209490231836446899608210795482963763094236630945410832793769905399982457186322944729636418890623372171723742105636440368218459649632948538696905872650486914434637457507280441823676813517852099348660847172579408422316678097670224011990280170474894487426924742108823536808485072502240519452587542875349976558572670229633962575212637477897785501552646522609988869914013540483809865681250419497686697771007", + "259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071", + "190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991", + + /* DR moduli */ + "14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368612079", + "101745825697019260773923519755878567461315282017759829107608914364075275235254395622580447400994175578963163918967182013639660669771108475957692810857098847138903161308502419410142185759152435680068435915159402496058513611411688900243039", + "736335108039604595805923406147184530889923370574768772191969612422073040099331944991573923112581267542507986451953227192970402893063850485730703075899286013451337291468249027691733891486704001513279827771740183629161065194874727962517148100775228363421083691764065477590823919364012917984605619526140821797602431", + "38564998830736521417281865696453025806593491967131023221754800625044118265468851210705360385717536794615180260494208076605798671660719333199513807806252394423283413430106003596332513246682903994829528690198205120921557533726473585751382193953592127439965050261476810842071573684505878854588706623484573925925903505747545471088867712185004135201289273405614415899438276535626346098904241020877974002916168099951885406379295536200413493190419727789712076165162175783", + "542189391331696172661670440619180536749994166415993334151601745392193484590296600979602378676624808129613777993466242203025054573692562689251250471628358318743978285860720148446448885701001277560572526947619392551574490839286458454994488665744991822837769918095117129546414124448777033941223565831420390846864429504774477949153794689948747680362212954278693335653935890352619041936727463717926744868338358149568368643403037768649616778526013610493696186055899318268339432671541328195724261329606699831016666359440874843103020666106568222401047720269951530296879490444224546654729111504346660859907296364097126834834235287147", + "1487259134814709264092032648525971038895865645148901180585340454985524155135260217788758027400478312256339496385275012465661575576202252063145698732079880294664220579764848767704076761853197216563262660046602703973050798218246170835962005598561669706844469447435461092542265792444947706769615695252256130901271870341005768912974433684521436211263358097522726462083917939091760026658925757076733484173202927141441492573799914240222628795405623953109131594523623353044898339481494120112723445689647986475279242446083151413667587008191682564376412347964146113898565886683139407005941383669325997475076910488086663256335689181157957571445067490187939553165903773554290260531009121879044170766615232300936675369451260747671432073394867530820527479172464106442450727640226503746586340279816318821395210726268291535648506190714616083163403189943334431056876038286530365757187367147446004855912033137386225053275419626102417236133948503", + "1095121115716677802856811290392395128588168592409109494900178008967955253005183831872715423151551999734857184538199864469605657805519106717529655044054833197687459782636297255219742994736751541815269727940751860670268774903340296040006114013971309257028332849679096824800250742691718610670812374272414086863715763724622797509437062518082383056050144624962776302147890521249477060215148275163688301275847155316042279405557632639366066847442861422164832655874655824221577849928863023018366835675399949740429332468186340518172487073360822220449055340582568461568645259954873303616953776393853174845132081121976327462740354930744487429617202585015510744298530101547706821590188733515880733527449780963163909830077616357506845523215289297624086914545378511082534229620116563260168494523906566709418166011112754529766183554579321224940951177394088465596712620076240067370589036924024728375076210477267488679008016579588696191194060127319035195370137160936882402244399699172017835144537488486396906144217720028992863941288217185353914991583400421682751000603596655790990815525126154394344641336397793791497068253936771017031980867706707490224041075826337383538651825493679503771934836094655802776331664261631740148281763487765852746577808019633679", + + /* generic unrestricted moduli */ + "17933601194860113372237070562165128350027320072176844226673287945873370751245439587792371960615073855669274087805055507977323024886880985062002853331424203", + "2893527720709661239493896562339544088620375736490408468011883030469939904368086092336458298221245707898933583190713188177399401852627749210994595974791782790253946539043962213027074922559572312141181787434278708783207966459019479487", + "347743159439876626079252796797422223177535447388206607607181663903045907591201940478223621722118173270898487582987137708656414344685816179420855160986340457973820182883508387588163122354089264395604796675278966117567294812714812796820596564876450716066283126720010859041484786529056457896367683122960411136319", + "47266428956356393164697365098120418976400602706072312735924071745438532218237979333351774907308168340693326687317443721193266215155735814510792148768576498491199122744351399489453533553203833318691678263241941706256996197460424029012419012634671862283532342656309677173602509498417976091509154360039893165037637034737020327399910409885798185771003505320583967737293415979917317338985837385734747478364242020380416892056650841470869294527543597349250299539682430605173321029026555546832473048600327036845781970289288898317888427517364945316709081173840186150794397479045034008257793436817683392375274635794835245695887", + "436463808505957768574894870394349739623346440601945961161254440072143298152040105676491048248110146278752857839930515766167441407021501229924721335644557342265864606569000117714935185566842453630868849121480179691838399545644365571106757731317371758557990781880691336695584799313313687287468894148823761785582982549586183756806449017542622267874275103877481475534991201849912222670102069951687572917937634467778042874315463238062009202992087620963771759666448266532858079402669920025224220613419441069718482837399612644978839925207109870840278194042158748845445131729137117098529028886770063736487420613144045836803985635654192482395882603511950547826439092832800532152534003936926017612446606135655146445620623395788978726744728503058670046885876251527122350275750995227", + "11424167473351836398078306042624362277956429440521137061889702611766348760692206243140413411077394583180726863277012016602279290144126785129569474909173584789822341986742719230331946072730319555984484911716797058875905400999504305877245849119687509023232790273637466821052576859232452982061831009770786031785669030271542286603956118755585683996118896215213488875253101894663403069677745948305893849505434201763745232895780711972432011344857521691017896316861403206449421332243658855453435784006517202894181640562433575390821384210960117518650374602256601091379644034244332285065935413233557998331562749140202965844219336298970011513882564935538704289446968322281451907487362046511461221329799897350993370560697505809686438782036235372137015731304779072430260986460269894522159103008260495503005267165927542949439526272736586626709581721032189532726389643625590680105784844246152702670169304203783072275089194754889511973916207", + "1214855636816562637502584060163403830270705000634713483015101384881871978446801224798536155406895823305035467591632531067547890948695117172076954220727075688048751022421198712032848890056357845974246560748347918630050853933697792254955890439720297560693579400297062396904306270145886830719309296352765295712183040773146419022875165382778007040109957609739589875590885701126197906063620133954893216612678838507540777138437797705602453719559017633986486649523611975865005712371194067612263330335590526176087004421363598470302731349138773205901447704682181517904064735636518462452242791676541725292378925568296858010151852326316777511935037531017413910506921922450666933202278489024521263798482237150056835746454842662048692127173834433089016107854491097456725016327709663199738238442164843147132789153725513257167915555162094970853584447993125488607696008169807374736711297007473812256272245489405898470297178738029484459690836250560495461579533254473316340608217876781986188705928270735695752830825527963838355419762516246028680280988020401914551825487349990306976304093109384451438813251211051597392127491464898797406789175453067960072008590614886532333015881171367104445044718144312416815712216611576221546455968770801413440778423979", + NULL + }; + log = fopen("logs/expt.log", "w"); + logb = fopen("logs/expt_dr.log", "w"); + logc = fopen("logs/expt_2k.log", "w"); + logd = fopen("logs/expt_2kl.log", "w"); + for (n = 0; primes[n]; n++) { + SLEEP; + mp_read_radix(&a, primes[n], 10); + mp_zero(&b); + for (rr = 0; rr < (unsigned) mp_count_bits(&a); rr++) { + mp_mul_2(&b, &b); + b.dp[0] |= lbit(); + b.used += 1; + } + mp_sub_d(&a, 1, &c); + mp_mod(&b, &c, &b); + mp_set(&c, 3); + rr = 0; + tt = -1; + do { + gg = TIMFUNC(); + DO(mp_exptmod(&c, &b, &a, &d)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 10); + mp_sub_d(&a, 1, &e); + mp_sub(&e, &b, &b); + mp_exptmod(&c, &b, &a, &e); /* c^(p-1-b) mod a */ + mp_mulmod(&e, &d, &a, &d); /* c^b * c^(p-1-b) == c^p-1 == 1 */ + if (mp_cmp_d(&d, 1)) { + printf("Different (%d)!!!\n", mp_count_bits(&a)); + draw(&d); + exit(0); + } + printf("Exponentiating\t%4d-bit => %9llu/sec, %9llu cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + fprintf(n < 4 ? logd : (n < 9) ? logc : (n < 16) ? logb : log, + "%d %9llu\n", mp_count_bits(&a), tt); + } + } + fclose(log); + fclose(logb); + fclose(logc); + fclose(logd); + + log = fopen("logs/invmod.log", "w"); + for (cnt = 4; cnt <= 128; cnt += 4) { + SLEEP; + mp_rand(&a, cnt); + mp_rand(&b, cnt); + + do { + mp_add_d(&b, 1, &b); + mp_gcd(&a, &b, &c); + } while (mp_cmp_d(&c, 1) != MP_EQ); + + rr = 0; + tt = -1; + do { + gg = TIMFUNC(); + DO(mp_invmod(&b, &a, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 1000); + mp_mulmod(&b, &c, &a, &d); + if (mp_cmp_d(&d, 1) != MP_EQ) { + printf("Failed to invert\n"); + return 0; + } + printf("Inverting mod\t%4d-bit => %9llu/sec, %9llu cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + fprintf(log, "%d %9llu\n", cnt * DIGIT_BIT, tt); + } + fclose(log); + + return 0; +} + +/* $Source: /cvs/libtom/libtommath/demo/timing.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/dep.pl b/lib/hcrypto/libtommath/dep.pl new file mode 100644 index 000000000..c39e27ea0 --- /dev/null +++ b/lib/hcrypto/libtommath/dep.pl @@ -0,0 +1,123 @@ +#!/usr/bin/perl +# +# Walk through source, add labels and make classes +# +#use strict; + +my %deplist; + +#open class file and write preamble +open(CLASS, ">tommath_class.h") or die "Couldn't open tommath_class.h for writing\n"; +print CLASS "#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))\n#if defined(LTM2)\n#define LTM3\n#endif\n#if defined(LTM1)\n#define LTM2\n#endif\n#define LTM1\n\n#if defined(LTM_ALL)\n"; + +foreach my $filename (glob "bn*.c") { + my $define = $filename; + +print "Processing $filename\n"; + + # convert filename to upper case so we can use it as a define + $define =~ tr/[a-z]/[A-Z]/; + $define =~ tr/\./_/; + print CLASS "#define $define\n"; + + # now copy text and apply #ifdef as required + my $apply = 0; + open(SRC, "<$filename"); + open(OUT, ">tmp"); + + # first line will be the #ifdef + my $line = ; + if ($line =~ /include/) { + print OUT $line; + } else { + print OUT "#include \n#ifdef $define\n$line"; + $apply = 1; + } + while () { + if (!($_ =~ /tommath\.h/)) { + print OUT $_; + } + } + if ($apply == 1) { + print OUT "#endif\n"; + } + close SRC; + close OUT; + + unlink($filename); + rename("tmp", $filename); +} +print CLASS "#endif\n\n"; + +# now do classes + +foreach my $filename (glob "bn*.c") { + open(SRC, "<$filename") or die "Can't open source file!\n"; + + # convert filename to upper case so we can use it as a define + $filename =~ tr/[a-z]/[A-Z]/; + $filename =~ tr/\./_/; + + print CLASS "#if defined($filename)\n"; + my $list = $filename; + + # scan for mp_* and make classes + while () { + my $line = $_; + while ($line =~ m/(fast_)*(s_)*mp\_[a-z_0-9]*/) { + $line = $'; + # now $& is the match, we want to skip over LTM keywords like + # mp_int, mp_word, mp_digit + if (!($& eq "mp_digit") && !($& eq "mp_word") && !($& eq "mp_int")) { + my $a = $&; + $a =~ tr/[a-z]/[A-Z]/; + $a = "BN_" . $a . "_C"; + if (!($list =~ /$a/)) { + print CLASS " #define $a\n"; + } + $list = $list . "," . $a; + } + } + } + @deplist{$filename} = $list; + + print CLASS "#endif\n\n"; + close SRC; +} + +print CLASS "#ifdef LTM3\n#define LTM_LAST\n#endif\n#include \n#include \n#else\n#define LTM_LAST\n#endif\n"; +close CLASS; + +#now let's make a cool call graph... + +open(OUT,">callgraph.txt"); +$indent = 0; +foreach (keys %deplist) { + $list = ""; + draw_func(@deplist{$_}); + print OUT "\n\n"; +} +close(OUT); + +sub draw_func() +{ + my @funcs = split(",", $_[0]); + if ($list =~ /@funcs[0]/) { + return; + } else { + $list = $list . @funcs[0]; + } + if ($indent == 0) { } + elsif ($indent >= 1) { print OUT "| " x ($indent - 1) . "+--->"; } + print OUT @funcs[0] . "\n"; + shift @funcs; + my $temp = $list; + foreach my $i (@funcs) { + ++$indent; + draw_func(@deplist{$i}); + --$indent; + } + $list = $temp; +} + + diff --git a/lib/hcrypto/libtommath/etc/2kprime.1 b/lib/hcrypto/libtommath/etc/2kprime.1 new file mode 100644 index 000000000..c41ded1f9 --- /dev/null +++ b/lib/hcrypto/libtommath/etc/2kprime.1 @@ -0,0 +1,2 @@ +256-bits (k = 36113) = 115792089237316195423570985008687907853269984665640564039457584007913129603823 +512-bits (k = 38117) = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006045979 diff --git a/lib/hcrypto/libtommath/etc/2kprime.c b/lib/hcrypto/libtommath/etc/2kprime.c new file mode 100644 index 000000000..c09818f9c --- /dev/null +++ b/lib/hcrypto/libtommath/etc/2kprime.c @@ -0,0 +1,84 @@ +/* Makes safe primes of a 2k nature */ +#include +#include + +int sizes[] = {256, 512, 768, 1024, 1536, 2048, 3072, 4096}; + +int main(void) +{ + char buf[2000]; + int x, y; + mp_int q, p; + FILE *out; + clock_t t1; + mp_digit z; + + mp_init_multi(&q, &p, NULL); + + out = fopen("2kprime.1", "w"); + for (x = 0; x < (int)(sizeof(sizes) / sizeof(sizes[0])); x++) { + top: + mp_2expt(&q, sizes[x]); + mp_add_d(&q, 3, &q); + z = -3; + + t1 = clock(); + for(;;) { + mp_sub_d(&q, 4, &q); + z += 4; + + if (z > MP_MASK) { + printf("No primes of size %d found\n", sizes[x]); + break; + } + + if (clock() - t1 > CLOCKS_PER_SEC) { + printf("."); fflush(stdout); +// sleep((clock() - t1 + CLOCKS_PER_SEC/2)/CLOCKS_PER_SEC); + t1 = clock(); + } + + /* quick test on q */ + mp_prime_is_prime(&q, 1, &y); + if (y == 0) { + continue; + } + + /* find (q-1)/2 */ + mp_sub_d(&q, 1, &p); + mp_div_2(&p, &p); + mp_prime_is_prime(&p, 3, &y); + if (y == 0) { + continue; + } + + /* test on q */ + mp_prime_is_prime(&q, 3, &y); + if (y == 0) { + continue; + } + + break; + } + + if (y == 0) { + ++sizes[x]; + goto top; + } + + mp_toradix(&q, buf, 10); + printf("\n\n%d-bits (k = %lu) = %s\n", sizes[x], z, buf); + fprintf(out, "%d-bits (k = %lu) = %s\n", sizes[x], z, buf); fflush(out); + } + + return 0; +} + + + + + + +/* $Source: /cvs/libtom/libtommath/etc/2kprime.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/etc/drprime.c b/lib/hcrypto/libtommath/etc/drprime.c new file mode 100644 index 000000000..e4139850c --- /dev/null +++ b/lib/hcrypto/libtommath/etc/drprime.c @@ -0,0 +1,64 @@ +/* Makes safe primes of a DR nature */ +#include + +int sizes[] = { 1+256/DIGIT_BIT, 1+512/DIGIT_BIT, 1+768/DIGIT_BIT, 1+1024/DIGIT_BIT, 1+2048/DIGIT_BIT, 1+4096/DIGIT_BIT }; +int main(void) +{ + int res, x, y; + char buf[4096]; + FILE *out; + mp_int a, b; + + mp_init(&a); + mp_init(&b); + + out = fopen("drprimes.txt", "w"); + for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) { + top: + printf("Seeking a %d-bit safe prime\n", sizes[x] * DIGIT_BIT); + mp_grow(&a, sizes[x]); + mp_zero(&a); + for (y = 1; y < sizes[x]; y++) { + a.dp[y] = MP_MASK; + } + + /* make a DR modulus */ + a.dp[0] = -1; + a.used = sizes[x]; + + /* now loop */ + res = 0; + for (;;) { + a.dp[0] += 4; + if (a.dp[0] >= MP_MASK) break; + mp_prime_is_prime(&a, 1, &res); + if (res == 0) continue; + printf("."); fflush(stdout); + mp_sub_d(&a, 1, &b); + mp_div_2(&b, &b); + mp_prime_is_prime(&b, 3, &res); + if (res == 0) continue; + mp_prime_is_prime(&a, 3, &res); + if (res == 1) break; + } + + if (res != 1) { + printf("Error not DR modulus\n"); sizes[x] += 1; goto top; + } else { + mp_toradix(&a, buf, 10); + printf("\n\np == %s\n\n", buf); + fprintf(out, "%d-bit prime:\np == %s\n\n", mp_count_bits(&a), buf); fflush(out); + } + } + fclose(out); + + mp_clear(&a); + mp_clear(&b); + + return 0; +} + + +/* $Source: /cvs/libtom/libtommath/etc/drprime.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/etc/drprimes.28 b/lib/hcrypto/libtommath/etc/drprimes.28 new file mode 100644 index 000000000..9d438ad1d --- /dev/null +++ b/lib/hcrypto/libtommath/etc/drprimes.28 @@ -0,0 +1,25 @@ +DR safe primes for 28-bit digits. + +224-bit prime: +p == 26959946667150639794667015087019630673637144422540572481103341844143 + +532-bit prime: +p == 14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368691747 + +784-bit prime: +p == 101745825697019260773923519755878567461315282017759829107608914364075275235254395622580447400994175578963163918967182013639660669771108475957692810857098847138903161308502419410142185759152435680068435915159402496058513611411688900243039 + +1036-bit prime: +p == 736335108039604595805923406147184530889923370574768772191969612422073040099331944991573923112581267542507986451953227192970402893063850485730703075899286013451337291468249027691733891486704001513279827771740183629161065194874727962517148100775228363421083691764065477590823919364012917984605619526140821798437127 + +1540-bit prime: +p == 38564998830736521417281865696453025806593491967131023221754800625044118265468851210705360385717536794615180260494208076605798671660719333199513807806252394423283413430106003596332513246682903994829528690198205120921557533726473585751382193953592127439965050261476810842071573684505878854588706623484573925925903505747545471088867712185004135201289273405614415899438276535626346098904241020877974002916168099951885406379295536200413493190419727789712076165162175783 + +2072-bit prime: +p == 542189391331696172661670440619180536749994166415993334151601745392193484590296600979602378676624808129613777993466242203025054573692562689251250471628358318743978285860720148446448885701001277560572526947619392551574490839286458454994488665744991822837769918095117129546414124448777033941223565831420390846864429504774477949153794689948747680362212954278693335653935890352619041936727463717926744868338358149568368643403037768649616778526013610493696186055899318268339432671541328195724261329606699831016666359440874843103020666106568222401047720269951530296879490444224546654729111504346660859907296364097126834834235287147 + +3080-bit prime: +p == 1487259134814709264092032648525971038895865645148901180585340454985524155135260217788758027400478312256339496385275012465661575576202252063145698732079880294664220579764848767704076761853197216563262660046602703973050798218246170835962005598561669706844469447435461092542265792444947706769615695252256130901271870341005768912974433684521436211263358097522726462083917939091760026658925757076733484173202927141441492573799914240222628795405623953109131594523623353044898339481494120112723445689647986475279242446083151413667587008191682564376412347964146113898565886683139407005941383669325997475076910488086663256335689181157957571445067490187939553165903773554290260531009121879044170766615232300936675369451260747671432073394867530820527479172464106442450727640226503746586340279816318821395210726268291535648506190714616083163403189943334431056876038286530365757187367147446004855912033137386225053275419626102417236133948503 + +4116-bit prime: +p == 1095121115716677802856811290392395128588168592409109494900178008967955253005183831872715423151551999734857184538199864469605657805519106717529655044054833197687459782636297255219742994736751541815269727940751860670268774903340296040006114013971309257028332849679096824800250742691718610670812374272414086863715763724622797509437062518082383056050144624962776302147890521249477060215148275163688301275847155316042279405557632639366066847442861422164832655874655824221577849928863023018366835675399949740429332468186340518172487073360822220449055340582568461568645259954873303616953776393853174845132081121976327462740354930744487429617202585015510744298530101547706821590188733515880733527449780963163909830077616357506845523215289297624086914545378511082534229620116563260168494523906566709418166011112754529766183554579321224940951177394088465596712620076240067370589036924024728375076210477267488679008016579588696191194060127319035195370137160936882402244399699172017835144537488486396906144217720028992863941288217185353914991583400421682751000603596655790990815525126154394344641336397793791497068253936771017031980867706707490224041075826337383538651825493679503771934836094655802776331664261631740148281763487765852746577808019633679 diff --git a/lib/hcrypto/libtommath/etc/drprimes.txt b/lib/hcrypto/libtommath/etc/drprimes.txt new file mode 100644 index 000000000..7c97f67b9 --- /dev/null +++ b/lib/hcrypto/libtommath/etc/drprimes.txt @@ -0,0 +1,9 @@ +300-bit prime: +p == 2037035976334486086268445688409378161051468393665936250636140449354381298610415201576637819 + +540-bit prime: +p == 3599131035634557106248430806148785487095757694641533306480604458089470064537190296255232548883112685719936728506816716098566612844395439751206810991770626477344739 + +780-bit prime: +p == 6359114106063703798370219984742410466332205126109989319225557147754704702203399726411277962562135973685197744935448875852478791860694279747355800678568677946181447581781401213133886609947027230004277244697462656003655947791725966271167 + diff --git a/lib/hcrypto/libtommath/etc/makefile b/lib/hcrypto/libtommath/etc/makefile new file mode 100644 index 000000000..99154d864 --- /dev/null +++ b/lib/hcrypto/libtommath/etc/makefile @@ -0,0 +1,50 @@ +CFLAGS += -Wall -W -Wshadow -O3 -fomit-frame-pointer -funroll-loops -I../ + +# default lib name (requires install with root) +# LIBNAME=-ltommath + +# libname when you can't install the lib with install +LIBNAME=../libtommath.a + +#provable primes +pprime: pprime.o + $(CC) pprime.o $(LIBNAME) -o pprime + +# portable [well requires clock()] tuning app +tune: tune.o + $(CC) tune.o $(LIBNAME) -o tune + +# same app but using RDTSC for higher precision [requires 80586+], coff based gcc installs [e.g. ming, cygwin, djgpp] +tune86: tune.c + nasm -f coff timer.asm + $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86 + +# for cygwin +tune86c: tune.c + nasm -f gnuwin32 timer.asm + $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86 + +#make tune86 for linux or any ELF format +tune86l: tune.c + nasm -f elf -DUSE_ELF timer.asm + $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86l + +# spits out mersenne primes +mersenne: mersenne.o + $(CC) mersenne.o $(LIBNAME) -o mersenne + +# fines DR safe primes for the given config +drprime: drprime.o + $(CC) drprime.o $(LIBNAME) -o drprime + +# fines 2k safe primes for the given config +2kprime: 2kprime.o + $(CC) 2kprime.o $(LIBNAME) -o 2kprime + +mont: mont.o + $(CC) mont.o $(LIBNAME) -o mont + + +clean: + rm -f *.log *.o *.obj *.exe pprime tune mersenne drprime tune86 tune86l mont 2kprime pprime.dat \ + *.da *.dyn *.dpi *~ diff --git a/lib/hcrypto/libtommath/etc/makefile.icc b/lib/hcrypto/libtommath/etc/makefile.icc new file mode 100644 index 000000000..8a1ffffd2 --- /dev/null +++ b/lib/hcrypto/libtommath/etc/makefile.icc @@ -0,0 +1,67 @@ +CC = icc + +CFLAGS += -I../ + +# optimize for SPEED +# +# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4 +# -ax? specifies make code specifically for ? but compatible with IA-32 +# -x? specifies compile solely for ? [not specifically IA-32 compatible] +# +# where ? is +# K - PIII +# W - first P4 [Williamette] +# N - P4 Northwood +# P - P4 Prescott +# B - Blend of P4 and PM [mobile] +# +# Default to just generic max opts +CFLAGS += -O3 -xP -ip + +# default lib name (requires install with root) +# LIBNAME=-ltommath + +# libname when you can't install the lib with install +LIBNAME=../libtommath.a + +#provable primes +pprime: pprime.o + $(CC) pprime.o $(LIBNAME) -o pprime + +# portable [well requires clock()] tuning app +tune: tune.o + $(CC) tune.o $(LIBNAME) -o tune + +# same app but using RDTSC for higher precision [requires 80586+], coff based gcc installs [e.g. ming, cygwin, djgpp] +tune86: tune.c + nasm -f coff timer.asm + $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86 + +# for cygwin +tune86c: tune.c + nasm -f gnuwin32 timer.asm + $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86 + +#make tune86 for linux or any ELF format +tune86l: tune.c + nasm -f elf -DUSE_ELF timer.asm + $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86l + +# spits out mersenne primes +mersenne: mersenne.o + $(CC) mersenne.o $(LIBNAME) -o mersenne + +# fines DR safe primes for the given config +drprime: drprime.o + $(CC) drprime.o $(LIBNAME) -o drprime + +# fines 2k safe primes for the given config +2kprime: 2kprime.o + $(CC) 2kprime.o $(LIBNAME) -o 2kprime + +mont: mont.o + $(CC) mont.o $(LIBNAME) -o mont + + +clean: + rm -f *.log *.o *.obj *.exe pprime tune mersenne drprime tune86 tune86l mont 2kprime pprime.dat *.il diff --git a/lib/hcrypto/libtommath/etc/makefile.msvc b/lib/hcrypto/libtommath/etc/makefile.msvc new file mode 100644 index 000000000..2833372e0 --- /dev/null +++ b/lib/hcrypto/libtommath/etc/makefile.msvc @@ -0,0 +1,23 @@ +#MSVC Makefile +# +#Tom St Denis + +CFLAGS = /I../ /Ox /DWIN32 /W3 + +pprime: pprime.obj + cl pprime.obj ../tommath.lib + +mersenne: mersenne.obj + cl mersenne.obj ../tommath.lib + +tune: tune.obj + cl tune.obj ../tommath.lib + +mont: mont.obj + cl mont.obj ../tommath.lib + +drprime: drprime.obj + cl drprime.obj ../tommath.lib + +2kprime: 2kprime.obj + cl 2kprime.obj ../tommath.lib diff --git a/lib/hcrypto/libtommath/etc/mersenne.c b/lib/hcrypto/libtommath/etc/mersenne.c new file mode 100644 index 000000000..6a6497acf --- /dev/null +++ b/lib/hcrypto/libtommath/etc/mersenne.c @@ -0,0 +1,144 @@ +/* Finds Mersenne primes using the Lucas-Lehmer test + * + * Tom St Denis, tomstdenis@gmail.com + */ +#include +#include + +int +is_mersenne (long s, int *pp) +{ + mp_int n, u; + int res, k; + + *pp = 0; + + if ((res = mp_init (&n)) != MP_OKAY) { + return res; + } + + if ((res = mp_init (&u)) != MP_OKAY) { + goto LBL_N; + } + + /* n = 2^s - 1 */ + if ((res = mp_2expt(&n, s)) != MP_OKAY) { + goto LBL_MU; + } + if ((res = mp_sub_d (&n, 1, &n)) != MP_OKAY) { + goto LBL_MU; + } + + /* set u=4 */ + mp_set (&u, 4); + + /* for k=1 to s-2 do */ + for (k = 1; k <= s - 2; k++) { + /* u = u^2 - 2 mod n */ + if ((res = mp_sqr (&u, &u)) != MP_OKAY) { + goto LBL_MU; + } + if ((res = mp_sub_d (&u, 2, &u)) != MP_OKAY) { + goto LBL_MU; + } + + /* make sure u is positive */ + while (u.sign == MP_NEG) { + if ((res = mp_add (&u, &n, &u)) != MP_OKAY) { + goto LBL_MU; + } + } + + /* reduce */ + if ((res = mp_reduce_2k (&u, &n, 1)) != MP_OKAY) { + goto LBL_MU; + } + } + + /* if u == 0 then its prime */ + if (mp_iszero (&u) == 1) { + mp_prime_is_prime(&n, 8, pp); + if (*pp != 1) printf("FAILURE\n"); + } + + res = MP_OKAY; +LBL_MU:mp_clear (&u); +LBL_N:mp_clear (&n); + return res; +} + +/* square root of a long < 65536 */ +long +i_sqrt (long x) +{ + long x1, x2; + + x2 = 16; + do { + x1 = x2; + x2 = x1 - ((x1 * x1) - x) / (2 * x1); + } while (x1 != x2); + + if (x1 * x1 > x) { + --x1; + } + + return x1; +} + +/* is the long prime by brute force */ +int +isprime (long k) +{ + long y, z; + + y = i_sqrt (k); + for (z = 2; z <= y; z++) { + if ((k % z) == 0) + return 0; + } + return 1; +} + + +int +main (void) +{ + int pp; + long k; + clock_t tt; + + k = 3; + + for (;;) { + /* start time */ + tt = clock (); + + /* test if 2^k - 1 is prime */ + if (is_mersenne (k, &pp) != MP_OKAY) { + printf ("Whoa error\n"); + return -1; + } + + if (pp == 1) { + /* count time */ + tt = clock () - tt; + + /* display if prime */ + printf ("2^%-5ld - 1 is prime, test took %ld ticks\n", k, tt); + } + + /* goto next odd exponent */ + k += 2; + + /* but make sure its prime */ + while (isprime (k) == 0) { + k += 2; + } + } + return 0; +} + +/* $Source: /cvs/libtom/libtommath/etc/mersenne.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/03/31 14:18:47 $ */ diff --git a/lib/hcrypto/libtommath/etc/mont.c b/lib/hcrypto/libtommath/etc/mont.c new file mode 100644 index 000000000..393be4c9d --- /dev/null +++ b/lib/hcrypto/libtommath/etc/mont.c @@ -0,0 +1,50 @@ +/* tests the montgomery routines */ +#include + +int main(void) +{ + mp_int modulus, R, p, pp; + mp_digit mp; + long x, y; + + srand(time(NULL)); + mp_init_multi(&modulus, &R, &p, &pp, NULL); + + /* loop through various sizes */ + for (x = 4; x < 256; x++) { + printf("DIGITS == %3ld...", x); fflush(stdout); + + /* make up the odd modulus */ + mp_rand(&modulus, x); + modulus.dp[0] |= 1; + + /* now find the R value */ + mp_montgomery_calc_normalization(&R, &modulus); + mp_montgomery_setup(&modulus, &mp); + + /* now run through a bunch tests */ + for (y = 0; y < 1000; y++) { + mp_rand(&p, x/2); /* p = random */ + mp_mul(&p, &R, &pp); /* pp = R * p */ + mp_montgomery_reduce(&pp, &modulus, mp); + + /* should be equal to p */ + if (mp_cmp(&pp, &p) != MP_EQ) { + printf("FAILURE!\n"); + exit(-1); + } + } + printf("PASSED\n"); + } + + return 0; +} + + + + + + +/* $Source: /cvs/libtom/libtommath/etc/mont.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/etc/pprime.c b/lib/hcrypto/libtommath/etc/pprime.c new file mode 100644 index 000000000..317e2a0fc --- /dev/null +++ b/lib/hcrypto/libtommath/etc/pprime.c @@ -0,0 +1,400 @@ +/* Generates provable primes + * + * See http://gmail.com:8080/papers/pp.pdf for more info. + * + * Tom St Denis, tomstdenis@gmail.com, http://tom.gmail.com + */ +#include +#include "tommath.h" + +int n_prime; +FILE *primes; + +/* fast square root */ +static mp_digit +i_sqrt (mp_word x) +{ + mp_word x1, x2; + + x2 = x; + do { + x1 = x2; + x2 = x1 - ((x1 * x1) - x) / (2 * x1); + } while (x1 != x2); + + if (x1 * x1 > x) { + --x1; + } + + return x1; +} + + +/* generates a prime digit */ +static void gen_prime (void) +{ + mp_digit r, x, y, next; + FILE *out; + + out = fopen("pprime.dat", "wb"); + + /* write first set of primes */ + r = 3; fwrite(&r, 1, sizeof(mp_digit), out); + r = 5; fwrite(&r, 1, sizeof(mp_digit), out); + r = 7; fwrite(&r, 1, sizeof(mp_digit), out); + r = 11; fwrite(&r, 1, sizeof(mp_digit), out); + r = 13; fwrite(&r, 1, sizeof(mp_digit), out); + r = 17; fwrite(&r, 1, sizeof(mp_digit), out); + r = 19; fwrite(&r, 1, sizeof(mp_digit), out); + r = 23; fwrite(&r, 1, sizeof(mp_digit), out); + r = 29; fwrite(&r, 1, sizeof(mp_digit), out); + r = 31; fwrite(&r, 1, sizeof(mp_digit), out); + + /* get square root, since if 'r' is composite its factors must be < than this */ + y = i_sqrt (r); + next = (y + 1) * (y + 1); + + for (;;) { + do { + r += 2; /* next candidate */ + r &= MP_MASK; + if (r < 31) break; + + /* update sqrt ? */ + if (next <= r) { + ++y; + next = (y + 1) * (y + 1); + } + + /* loop if divisible by 3,5,7,11,13,17,19,23,29 */ + if ((r % 3) == 0) { + x = 0; + continue; + } + if ((r % 5) == 0) { + x = 0; + continue; + } + if ((r % 7) == 0) { + x = 0; + continue; + } + if ((r % 11) == 0) { + x = 0; + continue; + } + if ((r % 13) == 0) { + x = 0; + continue; + } + if ((r % 17) == 0) { + x = 0; + continue; + } + if ((r % 19) == 0) { + x = 0; + continue; + } + if ((r % 23) == 0) { + x = 0; + continue; + } + if ((r % 29) == 0) { + x = 0; + continue; + } + + /* now check if r is divisible by x + k={1,7,11,13,17,19,23,29} */ + for (x = 30; x <= y; x += 30) { + if ((r % (x + 1)) == 0) { + x = 0; + break; + } + if ((r % (x + 7)) == 0) { + x = 0; + break; + } + if ((r % (x + 11)) == 0) { + x = 0; + break; + } + if ((r % (x + 13)) == 0) { + x = 0; + break; + } + if ((r % (x + 17)) == 0) { + x = 0; + break; + } + if ((r % (x + 19)) == 0) { + x = 0; + break; + } + if ((r % (x + 23)) == 0) { + x = 0; + break; + } + if ((r % (x + 29)) == 0) { + x = 0; + break; + } + } + } while (x == 0); + if (r > 31) { fwrite(&r, 1, sizeof(mp_digit), out); printf("%9d\r", r); fflush(stdout); } + if (r < 31) break; + } + + fclose(out); +} + +void load_tab(void) +{ + primes = fopen("pprime.dat", "rb"); + if (primes == NULL) { + gen_prime(); + primes = fopen("pprime.dat", "rb"); + } + fseek(primes, 0, SEEK_END); + n_prime = ftell(primes) / sizeof(mp_digit); +} + +mp_digit prime_digit(void) +{ + int n; + mp_digit d; + + n = abs(rand()) % n_prime; + fseek(primes, n * sizeof(mp_digit), SEEK_SET); + fread(&d, 1, sizeof(mp_digit), primes); + return d; +} + + +/* makes a prime of at least k bits */ +int +pprime (int k, int li, mp_int * p, mp_int * q) +{ + mp_int a, b, c, n, x, y, z, v; + int res, ii; + static const mp_digit bases[] = { 2, 3, 5, 7, 11, 13, 17, 19 }; + + /* single digit ? */ + if (k <= (int) DIGIT_BIT) { + mp_set (p, prime_digit ()); + return MP_OKAY; + } + + if ((res = mp_init (&c)) != MP_OKAY) { + return res; + } + + if ((res = mp_init (&v)) != MP_OKAY) { + goto LBL_C; + } + + /* product of first 50 primes */ + if ((res = + mp_read_radix (&v, + "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190", + 10)) != MP_OKAY) { + goto LBL_V; + } + + if ((res = mp_init (&a)) != MP_OKAY) { + goto LBL_V; + } + + /* set the prime */ + mp_set (&a, prime_digit ()); + + if ((res = mp_init (&b)) != MP_OKAY) { + goto LBL_A; + } + + if ((res = mp_init (&n)) != MP_OKAY) { + goto LBL_B; + } + + if ((res = mp_init (&x)) != MP_OKAY) { + goto LBL_N; + } + + if ((res = mp_init (&y)) != MP_OKAY) { + goto LBL_X; + } + + if ((res = mp_init (&z)) != MP_OKAY) { + goto LBL_Y; + } + + /* now loop making the single digit */ + while (mp_count_bits (&a) < k) { + fprintf (stderr, "prime has %4d bits left\r", k - mp_count_bits (&a)); + fflush (stderr); + top: + mp_set (&b, prime_digit ()); + + /* now compute z = a * b * 2 */ + if ((res = mp_mul (&a, &b, &z)) != MP_OKAY) { /* z = a * b */ + goto LBL_Z; + } + + if ((res = mp_copy (&z, &c)) != MP_OKAY) { /* c = a * b */ + goto LBL_Z; + } + + if ((res = mp_mul_2 (&z, &z)) != MP_OKAY) { /* z = 2 * a * b */ + goto LBL_Z; + } + + /* n = z + 1 */ + if ((res = mp_add_d (&z, 1, &n)) != MP_OKAY) { /* n = z + 1 */ + goto LBL_Z; + } + + /* check (n, v) == 1 */ + if ((res = mp_gcd (&n, &v, &y)) != MP_OKAY) { /* y = (n, v) */ + goto LBL_Z; + } + + if (mp_cmp_d (&y, 1) != MP_EQ) + goto top; + + /* now try base x=bases[ii] */ + for (ii = 0; ii < li; ii++) { + mp_set (&x, bases[ii]); + + /* compute x^a mod n */ + if ((res = mp_exptmod (&x, &a, &n, &y)) != MP_OKAY) { /* y = x^a mod n */ + goto LBL_Z; + } + + /* if y == 1 loop */ + if (mp_cmp_d (&y, 1) == MP_EQ) + continue; + + /* now x^2a mod n */ + if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2a mod n */ + goto LBL_Z; + } + + if (mp_cmp_d (&y, 1) == MP_EQ) + continue; + + /* compute x^b mod n */ + if ((res = mp_exptmod (&x, &b, &n, &y)) != MP_OKAY) { /* y = x^b mod n */ + goto LBL_Z; + } + + /* if y == 1 loop */ + if (mp_cmp_d (&y, 1) == MP_EQ) + continue; + + /* now x^2b mod n */ + if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2b mod n */ + goto LBL_Z; + } + + if (mp_cmp_d (&y, 1) == MP_EQ) + continue; + + /* compute x^c mod n == x^ab mod n */ + if ((res = mp_exptmod (&x, &c, &n, &y)) != MP_OKAY) { /* y = x^ab mod n */ + goto LBL_Z; + } + + /* if y == 1 loop */ + if (mp_cmp_d (&y, 1) == MP_EQ) + continue; + + /* now compute (x^c mod n)^2 */ + if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2ab mod n */ + goto LBL_Z; + } + + /* y should be 1 */ + if (mp_cmp_d (&y, 1) != MP_EQ) + continue; + break; + } + + /* no bases worked? */ + if (ii == li) + goto top; + +{ + char buf[4096]; + + mp_toradix(&n, buf, 10); + printf("Certificate of primality for:\n%s\n\n", buf); + mp_toradix(&a, buf, 10); + printf("A == \n%s\n\n", buf); + mp_toradix(&b, buf, 10); + printf("B == \n%s\n\nG == %d\n", buf, bases[ii]); + printf("----------------------------------------------------------------\n"); +} + + /* a = n */ + mp_copy (&n, &a); + } + + /* get q to be the order of the large prime subgroup */ + mp_sub_d (&n, 1, q); + mp_div_2 (q, q); + mp_div (q, &b, q, NULL); + + mp_exch (&n, p); + + res = MP_OKAY; +LBL_Z:mp_clear (&z); +LBL_Y:mp_clear (&y); +LBL_X:mp_clear (&x); +LBL_N:mp_clear (&n); +LBL_B:mp_clear (&b); +LBL_A:mp_clear (&a); +LBL_V:mp_clear (&v); +LBL_C:mp_clear (&c); + return res; +} + + +int +main (void) +{ + mp_int p, q; + char buf[4096]; + int k, li; + clock_t t1; + + srand (time (NULL)); + load_tab(); + + printf ("Enter # of bits: \n"); + fgets (buf, sizeof (buf), stdin); + sscanf (buf, "%d", &k); + + printf ("Enter number of bases to try (1 to 8):\n"); + fgets (buf, sizeof (buf), stdin); + sscanf (buf, "%d", &li); + + + mp_init (&p); + mp_init (&q); + + t1 = clock (); + pprime (k, li, &p, &q); + t1 = clock () - t1; + + printf ("\n\nTook %ld ticks, %d bits\n", t1, mp_count_bits (&p)); + + mp_toradix (&p, buf, 10); + printf ("P == %s\n", buf); + mp_toradix (&q, buf, 10); + printf ("Q == %s\n", buf); + + return 0; +} + +/* $Source: /cvs/libtom/libtommath/etc/pprime.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/03/31 14:18:47 $ */ diff --git a/lib/hcrypto/libtommath/etc/prime.1024 b/lib/hcrypto/libtommath/etc/prime.1024 new file mode 100644 index 000000000..5636e2da0 --- /dev/null +++ b/lib/hcrypto/libtommath/etc/prime.1024 @@ -0,0 +1,414 @@ +Enter # of bits: +Enter number of bases to try (1 to 8): +Certificate of primality for: +36360080703173363 + +A == +89963569 + +B == +202082249 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +4851595597739856136987139 + +A == +36360080703173363 + +B == +66715963 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +19550639734462621430325731591027 + +A == +4851595597739856136987139 + +B == +2014867 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +10409036141344317165691858509923818734539 + +A == +19550639734462621430325731591027 + +B == +266207047 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1049829549988285012736475602118094726647504414203 + +A == +10409036141344317165691858509923818734539 + +B == +50428759 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +77194737385528288387712399596835459931920358844586615003 + +A == +1049829549988285012736475602118094726647504414203 + +B == +36765367 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +35663756695365208574443215955488689578374232732893628896541201763 + +A == +77194737385528288387712399596835459931920358844586615003 + +B == +230998627 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +16711831463502165169495622246023119698415848120292671294127567620396469803 + +A == +35663756695365208574443215955488689578374232732893628896541201763 + +B == +234297127 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +6163534781560285962890718925972249753147470953579266394395432475622345597103528739 + +A == +16711831463502165169495622246023119698415848120292671294127567620396469803 + +B == +184406323 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +814258256205243497704094951432575867360065658372158511036259934640748088306764553488803787 + +A == +6163534781560285962890718925972249753147470953579266394395432475622345597103528739 + +B == +66054487 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +176469695533271657902814176811660357049007467856432383037590673407330246967781451723764079581998187 + +A == +814258256205243497704094951432575867360065658372158511036259934640748088306764553488803787 + +B == +108362239 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +44924492859445516541759485198544012102424796403707253610035148063863073596051272171194806669756971406400419 + +A == +176469695533271657902814176811660357049007467856432383037590673407330246967781451723764079581998187 + +B == +127286707 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +20600996927219343383225424320134474929609459588323857796871086845924186191561749519858600696159932468024710985371059 + +A == +44924492859445516541759485198544012102424796403707253610035148063863073596051272171194806669756971406400419 + +B == +229284691 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +6295696427695493110141186605837397185848992307978456138112526915330347715236378041486547994708748840844217371233735072572979 + +A == +20600996927219343383225424320134474929609459588323857796871086845924186191561749519858600696159932468024710985371059 + +B == +152800771 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +3104984078042317488749073016454213579257792635142218294052134804187631661145261015102617582090263808696699966840735333252107678792123 + +A == +6295696427695493110141186605837397185848992307978456138112526915330347715236378041486547994708748840844217371233735072572979 + +B == +246595759 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +26405175827665701256325699315126705508919255051121452292124404943796947287968603975320562847910946802396632302209435206627913466015741799499 + +A == +3104984078042317488749073016454213579257792635142218294052134804187631661145261015102617582090263808696699966840735333252107678792123 + +B == +4252063 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +11122146237908413610034600609460545703591095894418599759742741406628055069007082998134905595800236452010905900391505454890446585211975124558601770163 + +A == +26405175827665701256325699315126705508919255051121452292124404943796947287968603975320562847910946802396632302209435206627913466015741799499 + +B == +210605419 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1649861642047798890580354082088712649911849362201343649289384923147797960364736011515757482030049342943790127685185806092659832129486307035500638595572396187 + +A == +11122146237908413610034600609460545703591095894418599759742741406628055069007082998134905595800236452010905900391505454890446585211975124558601770163 + +B == +74170111 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +857983367126266717607389719637086684134462613006415859877666235955788392464081914127715967940968197765042399904117392707518175220864852816390004264107201177394565363 + +A == +1649861642047798890580354082088712649911849362201343649289384923147797960364736011515757482030049342943790127685185806092659832129486307035500638595572396187 + +B == +260016763 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +175995909353623703257072120479340610010337144085688850745292031336724691277374210929188442230237711063783727092685448718515661641054886101716698390145283196296702450566161283 + +A == +857983367126266717607389719637086684134462613006415859877666235955788392464081914127715967940968197765042399904117392707518175220864852816390004264107201177394565363 + +B == +102563707 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +48486002551155667224487059713350447239190772068092630563272168418880661006593537218144160068395218642353495339720640699721703003648144463556291315694787862009052641640656933232794283 + +A == +175995909353623703257072120479340610010337144085688850745292031336724691277374210929188442230237711063783727092685448718515661641054886101716698390145283196296702450566161283 + +B == +137747527 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +13156468011529105025061495011938518171328604045212410096476697450506055664012861932372156505805788068791146986282263016790631108386790291275939575123375304599622623328517354163964228279867403 + +A == +48486002551155667224487059713350447239190772068092630563272168418880661006593537218144160068395218642353495339720640699721703003648144463556291315694787862009052641640656933232794283 + +B == +135672847 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +6355194692790533601105154341731997464407930009404822926832136060319955058388106456084549316415200519472481147942263916585428906582726749131479465958107142228236909665306781538860053107680830113869123 + +A == +13156468011529105025061495011938518171328604045212410096476697450506055664012861932372156505805788068791146986282263016790631108386790291275939575123375304599622623328517354163964228279867403 + +B == +241523587 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +3157116676535430302794438027544146642863331358530722860333745617571010460905857862561870488000265751138954271040017454405707755458702044884023184574412221802502351503929935224995314581932097706874819348858083 + +A == +6355194692790533601105154341731997464407930009404822926832136060319955058388106456084549316415200519472481147942263916585428906582726749131479465958107142228236909665306781538860053107680830113869123 + +B == +248388667 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +390533129219992506725320633489467713907837370444962163378727819939092929448752905310115311180032249230394348337568973177802874166228132778126338883671958897238722734394783244237133367055422297736215754829839364158067 + +A == +3157116676535430302794438027544146642863331358530722860333745617571010460905857862561870488000265751138954271040017454405707755458702044884023184574412221802502351503929935224995314581932097706874819348858083 + +B == +61849651 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +48583654555070224891047847050732516652910250240135992225139515777200432486685999462997073444468380434359929499498804723793106565291183220444221080449740542884172281158126259373095216435009661050109711341419005972852770440739 + +A == +390533129219992506725320633489467713907837370444962163378727819939092929448752905310115311180032249230394348337568973177802874166228132778126338883671958897238722734394783244237133367055422297736215754829839364158067 + +B == +62201707 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +25733035251905120039135866524384525138869748427727001128764704499071378939227862068500633813538831598776578372709963673670934388213622433800015759585470542686333039614931682098922935087822950084908715298627996115185849260703525317419 + +A == +48583654555070224891047847050732516652910250240135992225139515777200432486685999462997073444468380434359929499498804723793106565291183220444221080449740542884172281158126259373095216435009661050109711341419005972852770440739 + +B == +264832231 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +2804594464939948901906623499531073917980499195397462605359913717827014360538186518540781517129548650937632008683280555602633122170458773895504894807182664540529077836857897972175530148107545939211339044386106111633510166695386323426241809387 + +A == +25733035251905120039135866524384525138869748427727001128764704499071378939227862068500633813538831598776578372709963673670934388213622433800015759585470542686333039614931682098922935087822950084908715298627996115185849260703525317419 + +B == +54494047 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +738136612083433720096707308165797114449914259256979340471077690416567237592465306112484843530074782721390528773594351482384711900456440808251196845265132086486672447136822046628407467459921823150600138073268385534588238548865012638209515923513516547 + +A == +2804594464939948901906623499531073917980499195397462605359913717827014360538186518540781517129548650937632008683280555602633122170458773895504894807182664540529077836857897972175530148107545939211339044386106111633510166695386323426241809387 + +B == +131594179 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +392847529056126766528615419937165193421166694172790666626558750047057558168124866940509180171236517681470100877687445134633784815352076138790217228749332398026714192707447855731679485746120589851992221508292976900578299504461333767437280988393026452846013683 + +A == +738136612083433720096707308165797114449914259256979340471077690416567237592465306112484843530074782721390528773594351482384711900456440808251196845265132086486672447136822046628407467459921823150600138073268385534588238548865012638209515923513516547 + +B == +266107603 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +168459393231883505975876919268398655632763956627405508859662408056221544310200546265681845397346956580604208064328814319465940958080244889692368602591598503944015835190587740756859842792554282496742843600573336023639256008687581291233481455395123454655488735304365627 + +A == +392847529056126766528615419937165193421166694172790666626558750047057558168124866940509180171236517681470100877687445134633784815352076138790217228749332398026714192707447855731679485746120589851992221508292976900578299504461333767437280988393026452846013683 + +B == +214408111 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +14865774288636941404884923981945833072113667565310054952177860608355263252462409554658728941191929400198053290113492910272458441655458514080123870132092365833472436407455910185221474386718838138135065780840839893113912689594815485706154461164071775481134379794909690501684643 + +A == +168459393231883505975876919268398655632763956627405508859662408056221544310200546265681845397346956580604208064328814319465940958080244889692368602591598503944015835190587740756859842792554282496742843600573336023639256008687581291233481455395123454655488735304365627 + +B == +44122723 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1213301773203241614897109856134894783021668292000023984098824423682568173639394290886185366993108292039068940333907505157813934962357206131450244004178619265868614859794316361031904412926604138893775068853175215502104744339658944443630407632290152772487455298652998368296998719996019 + +A == +14865774288636941404884923981945833072113667565310054952177860608355263252462409554658728941191929400198053290113492910272458441655458514080123870132092365833472436407455910185221474386718838138135065780840839893113912689594815485706154461164071775481134379794909690501684643 + +B == +40808563 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +186935245989515158127969129347464851990429060640910951266513740972248428651109062997368144722015290092846666943896556191257222521203647606911446635194198213436423080005867489516421559330500722264446765608763224572386410155413161172707802334865729654109050873820610813855041667633843601286843 + +A == +1213301773203241614897109856134894783021668292000023984098824423682568173639394290886185366993108292039068940333907505157813934962357206131450244004178619265868614859794316361031904412926604138893775068853175215502104744339658944443630407632290152772487455298652998368296998719996019 + +B == +77035759 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +83142661079751490510739960019112406284111408348732592580459037404394946037094409915127399165633756159385609671956087845517678367844901424617866988187132480585966721962585586730693443536100138246516868613250009028187662080828012497191775172228832247706080044971423654632146928165751885302331924491683 + +A == +186935245989515158127969129347464851990429060640910951266513740972248428651109062997368144722015290092846666943896556191257222521203647606911446635194198213436423080005867489516421559330500722264446765608763224572386410155413161172707802334865729654109050873820610813855041667633843601286843 + +B == +222383587 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443 + +A == +83142661079751490510739960019112406284111408348732592580459037404394946037094409915127399165633756159385609671956087845517678367844901424617866988187132480585966721962585586730693443536100138246516868613250009028187662080828012497191775172228832247706080044971423654632146928165751885302331924491683 + +B == +23407687 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1663606652988091811284014366560171522582683318514519379924950390627250155440313691226744227787921928894551755219495501365555370027257568506349958010457682898612082048959464465369892842603765280317696116552850664773291371490339084156052244256635115997453399761029567033971998617303988376172539172702246575225837054723 + +A == +3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443 + +B == +213701827 + +G == 2 +---------------------------------------------------------------- + + +Took 33057 ticks, 1048 bits +P == 1663606652988091811284014366560171522582683318514519379924950390627250155440313691226744227787921928894551755219495501365555370027257568506349958010457682898612082048959464465369892842603765280317696116552850664773291371490339084156052244256635115997453399761029567033971998617303988376172539172702246575225837054723 +Q == 3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443 diff --git a/lib/hcrypto/libtommath/etc/prime.512 b/lib/hcrypto/libtommath/etc/prime.512 new file mode 100644 index 000000000..cb6ec302f --- /dev/null +++ b/lib/hcrypto/libtommath/etc/prime.512 @@ -0,0 +1,205 @@ +Enter # of bits: +Enter number of bases to try (1 to 8): +Certificate of primality for: +85933926807634727 + +A == +253758023 + +B == +169322581 + +G == 5 +---------------------------------------------------------------- +Certificate of primality for: +23930198825086241462113799 + +A == +85933926807634727 + +B == +139236037 + +G == 11 +---------------------------------------------------------------- +Certificate of primality for: +6401844647261612602378676572510019 + +A == +23930198825086241462113799 + +B == +133760791 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +269731366027728777712034888684015329354259 + +A == +6401844647261612602378676572510019 + +B == +21066691 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +37942338209025571690075025099189467992329684223707 + +A == +269731366027728777712034888684015329354259 + +B == +70333567 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +15306904714258982484473490774101705363308327436988160248323 + +A == +37942338209025571690075025099189467992329684223707 + +B == +201712723 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1616744757018513392810355191503853040357155275733333124624513530099 + +A == +15306904714258982484473490774101705363308327436988160248323 + +B == +52810963 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +464222094814208047161771036072622485188658077940154689939306386289983787983 + +A == +1616744757018513392810355191503853040357155275733333124624513530099 + +B == +143566909 + +G == 5 +---------------------------------------------------------------- +Certificate of primality for: +187429931674053784626487560729643601208757374994177258429930699354770049369025096447 + +A == +464222094814208047161771036072622485188658077940154689939306386289983787983 + +B == +201875281 + +G == 5 +---------------------------------------------------------------- +Certificate of primality for: +100579220846502621074093727119851331775052664444339632682598589456666938521976625305832917563 + +A == +187429931674053784626487560729643601208757374994177258429930699354770049369025096447 + +B == +268311523 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1173616081309758475197022137833792133815753368965945885089720153370737965497134878651384030219765163 + +A == +100579220846502621074093727119851331775052664444339632682598589456666938521976625305832917563 + +B == +5834287 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +191456913489905913185935197655672585713573070349044195411728114905691721186574907738081340754373032735283623 + +A == +1173616081309758475197022137833792133815753368965945885089720153370737965497134878651384030219765163 + +B == +81567097 + +G == 5 +---------------------------------------------------------------- +Certificate of primality for: +57856530489201750164178576399448868489243874083056587683743345599898489554401618943240901541005080049321706789987519 + +A == +191456913489905913185935197655672585713573070349044195411728114905691721186574907738081340754373032735283623 + +B == +151095433 + +G == 7 +---------------------------------------------------------------- +Certificate of primality for: +13790529750452576698109671710773784949185621244122040804792403407272729038377767162233653248852099545134831722512085881814803 + +A == +57856530489201750164178576399448868489243874083056587683743345599898489554401618943240901541005080049321706789987519 + +B == +119178679 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +7075985989000817742677547821106534174334812111605018857703825637170140040509067704269696198231266351631132464035671858077052876058979 + +A == +13790529750452576698109671710773784949185621244122040804792403407272729038377767162233653248852099545134831722512085881814803 + +B == +256552363 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1227273006232588072907488910282307435921226646895131225407452056677899411162892829564455154080310937471747140942360789623819327234258162420463 + +A == +7075985989000817742677547821106534174334812111605018857703825637170140040509067704269696198231266351631132464035671858077052876058979 + +B == +86720989 + +G == 5 +---------------------------------------------------------------- +Certificate of primality for: +446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763 + +A == +1227273006232588072907488910282307435921226646895131225407452056677899411162892829564455154080310937471747140942360789623819327234258162420463 + +B == +182015287 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +5290203010849586596974953717018896543907195901082056939587768479377028575911127944611236020459652034082251335583308070846379514569838984811187823420951275243 + +A == +446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763 + +B == +5920567 + +G == 2 +---------------------------------------------------------------- + + +Took 3454 ticks, 521 bits +P == 5290203010849586596974953717018896543907195901082056939587768479377028575911127944611236020459652034082251335583308070846379514569838984811187823420951275243 +Q == 446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763 diff --git a/lib/hcrypto/libtommath/etc/timer.asm b/lib/hcrypto/libtommath/etc/timer.asm new file mode 100644 index 000000000..35890d985 --- /dev/null +++ b/lib/hcrypto/libtommath/etc/timer.asm @@ -0,0 +1,37 @@ +; x86 timer in NASM +; +; Tom St Denis, tomstdenis@iahu.ca +[bits 32] +[section .data] +time dd 0, 0 + +[section .text] + +%ifdef USE_ELF +[global t_start] +t_start: +%else +[global _t_start] +_t_start: +%endif + push edx + push eax + rdtsc + mov [time+0],edx + mov [time+4],eax + pop eax + pop edx + ret + +%ifdef USE_ELF +[global t_read] +t_read: +%else +[global _t_read] +_t_read: +%endif + rdtsc + sub eax,[time+4] + sbb edx,[time+0] + ret + \ No newline at end of file diff --git a/lib/hcrypto/libtommath/etc/tune.c b/lib/hcrypto/libtommath/etc/tune.c new file mode 100644 index 000000000..d4a502c8f --- /dev/null +++ b/lib/hcrypto/libtommath/etc/tune.c @@ -0,0 +1,142 @@ +/* Tune the Karatsuba parameters + * + * Tom St Denis, tomstdenis@gmail.com + */ +#include +#include + +/* how many times todo each size mult. Depends on your computer. For slow computers + * this can be low like 5 or 10. For fast [re: Athlon] should be 25 - 50 or so + */ +#define TIMES (1UL<<14UL) + +/* RDTSC from Scott Duplichan */ +static ulong64 TIMFUNC (void) + { + #if defined __GNUC__ + #if defined(__i386__) || defined(__x86_64__) + unsigned long long a; + __asm__ __volatile__ ("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n"::"m"(a):"%eax","%edx"); + return a; + #else /* gcc-IA64 version */ + unsigned long result; + __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); + while (__builtin_expect ((int) result == -1, 0)) + __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); + return result; + #endif + + // Microsoft and Intel Windows compilers + #elif defined _M_IX86 + __asm rdtsc + #elif defined _M_AMD64 + return __rdtsc (); + #elif defined _M_IA64 + #if defined __INTEL_COMPILER + #include + #endif + return __getReg (3116); + #else + #error need rdtsc function for this build + #endif + } + + +#ifndef X86_TIMER + +/* generic ISO C timer */ +ulong64 LBL_T; +void t_start(void) { LBL_T = TIMFUNC(); } +ulong64 t_read(void) { return TIMFUNC() - LBL_T; } + +#else +extern void t_start(void); +extern ulong64 t_read(void); +#endif + +ulong64 time_mult(int size, int s) +{ + unsigned long x; + mp_int a, b, c; + ulong64 t1; + + mp_init (&a); + mp_init (&b); + mp_init (&c); + + mp_rand (&a, size); + mp_rand (&b, size); + + if (s == 1) { + KARATSUBA_MUL_CUTOFF = size; + } else { + KARATSUBA_MUL_CUTOFF = 100000; + } + + t_start(); + for (x = 0; x < TIMES; x++) { + mp_mul(&a,&b,&c); + } + t1 = t_read(); + mp_clear (&a); + mp_clear (&b); + mp_clear (&c); + return t1; +} + +ulong64 time_sqr(int size, int s) +{ + unsigned long x; + mp_int a, b; + ulong64 t1; + + mp_init (&a); + mp_init (&b); + + mp_rand (&a, size); + + if (s == 1) { + KARATSUBA_SQR_CUTOFF = size; + } else { + KARATSUBA_SQR_CUTOFF = 100000; + } + + t_start(); + for (x = 0; x < TIMES; x++) { + mp_sqr(&a,&b); + } + t1 = t_read(); + mp_clear (&a); + mp_clear (&b); + return t1; +} + +int +main (void) +{ + ulong64 t1, t2; + int x, y; + + for (x = 8; ; x += 2) { + t1 = time_mult(x, 0); + t2 = time_mult(x, 1); + printf("%d: %9llu %9llu, %9llu\n", x, t1, t2, t2 - t1); + if (t2 < t1) break; + } + y = x; + + for (x = 8; ; x += 2) { + t1 = time_sqr(x, 0); + t2 = time_sqr(x, 1); + printf("%d: %9llu %9llu, %9llu\n", x, t1, t2, t2 - t1); + if (t2 < t1) break; + } + printf("KARATSUBA_MUL_CUTOFF = %d\n", y); + printf("KARATSUBA_SQR_CUTOFF = %d\n", x); + + return 0; +} + +/* $Source: /cvs/libtom/libtommath/etc/tune.c,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2006/03/31 14:18:47 $ */ diff --git a/lib/hcrypto/libtommath/gen.pl b/lib/hcrypto/libtommath/gen.pl new file mode 100644 index 000000000..72365912e --- /dev/null +++ b/lib/hcrypto/libtommath/gen.pl @@ -0,0 +1,17 @@ +#!/usr/bin/perl -w +# +# Generates a "single file" you can use to quickly +# add the whole source without any makefile troubles +# +use strict; + +open( OUT, ">mpi.c" ) or die "Couldn't open mpi.c for writing: $!"; +foreach my $filename (glob "bn*.c") { + open( SRC, "<$filename" ) or die "Couldn't open $filename for reading: $!"; + print OUT "/* Start: $filename */\n"; + print OUT while ; + print OUT "\n/* End: $filename */\n\n"; + close SRC or die "Error closing $filename after reading: $!"; +} +print OUT "\n/* EOF */\n"; +close OUT or die "Error closing mpi.c after writing: $!"; \ No newline at end of file diff --git a/lib/hcrypto/libtommath/libtommath.dsp b/lib/hcrypto/libtommath/libtommath.dsp new file mode 100644 index 000000000..71ac2433e --- /dev/null +++ b/lib/hcrypto/libtommath/libtommath.dsp @@ -0,0 +1,572 @@ +# Microsoft Developer Studio Project File - Name="libtommath" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libtommath - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libtommath.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libtommath.mak" CFG="libtommath - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libtommath - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libtommath - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "libtommath" +# PROP Scc_LocalPath "." +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libtommath - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Release\tommath.lib" + +!ELSEIF "$(CFG)" == "libtommath - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\tommath.lib" + +!ENDIF + +# Begin Target + +# Name "libtommath - Win32 Release" +# Name "libtommath - Win32 Debug" +# Begin Source File + +SOURCE=.\bn_error.c +# End Source File +# Begin Source File + +SOURCE=.\bn_fast_mp_invmod.c +# End Source File +# Begin Source File + +SOURCE=.\bn_fast_mp_montgomery_reduce.c +# End Source File +# Begin Source File + +SOURCE=.\bn_fast_s_mp_mul_digs.c +# End Source File +# Begin Source File + +SOURCE=.\bn_fast_s_mp_mul_high_digs.c +# End Source File +# Begin Source File + +SOURCE=.\bn_fast_s_mp_sqr.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_2expt.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_abs.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_add.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_add_d.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_addmod.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_and.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_clamp.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_clear.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_clear_multi.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_cmp.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_cmp_d.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_cmp_mag.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_cnt_lsb.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_copy.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_count_bits.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_div.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_div_2.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_div_2d.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_div_3.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_div_d.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_dr_is_modulus.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_dr_reduce.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_dr_setup.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_exch.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_expt_d.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_exptmod.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_exptmod_fast.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_exteuclid.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_fread.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_fwrite.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_gcd.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_get_int.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_grow.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_init.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_init_copy.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_init_multi.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_init_set.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_init_set_int.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_init_size.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_invmod.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_invmod_slow.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_is_square.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_jacobi.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_karatsuba_mul.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_karatsuba_sqr.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_lcm.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_lshd.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_mod.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_mod_2d.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_mod_d.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_montgomery_calc_normalization.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_montgomery_reduce.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_montgomery_setup.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_mul.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_mul_2.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_mul_2d.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_mul_d.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_mulmod.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_n_root.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_neg.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_or.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_prime_fermat.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_prime_is_divisible.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_prime_is_prime.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_prime_miller_rabin.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_prime_next_prime.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_prime_rabin_miller_trials.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_prime_random_ex.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_radix_size.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_radix_smap.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_rand.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_read_radix.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_read_signed_bin.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_read_unsigned_bin.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_reduce.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_reduce_2k.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_reduce_2k_l.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_reduce_2k_setup.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_reduce_2k_setup_l.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_reduce_is_2k.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_reduce_is_2k_l.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_reduce_setup.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_rshd.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_set.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_set_int.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_shrink.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_signed_bin_size.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_sqr.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_sqrmod.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_sqrt.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_sub.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_sub_d.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_submod.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_to_signed_bin.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_to_signed_bin_n.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_to_unsigned_bin.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_to_unsigned_bin_n.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_toom_mul.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_toom_sqr.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_toradix.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_toradix_n.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_unsigned_bin_size.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_xor.c +# End Source File +# Begin Source File + +SOURCE=.\bn_mp_zero.c +# End Source File +# Begin Source File + +SOURCE=.\bn_prime_tab.c +# End Source File +# Begin Source File + +SOURCE=.\bn_reverse.c +# End Source File +# Begin Source File + +SOURCE=.\bn_s_mp_add.c +# End Source File +# Begin Source File + +SOURCE=.\bn_s_mp_exptmod.c +# End Source File +# Begin Source File + +SOURCE=.\bn_s_mp_mul_digs.c +# End Source File +# Begin Source File + +SOURCE=.\bn_s_mp_mul_high_digs.c +# End Source File +# Begin Source File + +SOURCE=.\bn_s_mp_sqr.c +# End Source File +# Begin Source File + +SOURCE=.\bn_s_mp_sub.c +# End Source File +# Begin Source File + +SOURCE=.\bncore.c +# End Source File +# Begin Source File + +SOURCE=.\tommath.h +# End Source File +# Begin Source File + +SOURCE=.\tommath_class.h +# End Source File +# Begin Source File + +SOURCE=.\tommath_superclass.h +# End Source File +# End Target +# End Project diff --git a/lib/hcrypto/libtommath/logs/README b/lib/hcrypto/libtommath/logs/README new file mode 100644 index 000000000..ea20c8137 --- /dev/null +++ b/lib/hcrypto/libtommath/logs/README @@ -0,0 +1,13 @@ +To use the pretty graphs you have to first build/run the ltmtest from the root directory of the package. +Todo this type + +make timing ; ltmtest + +in the root. It will run for a while [about ten minutes on most PCs] and produce a series of .log files in logs/. + +After doing that run "gnuplot graphs.dem" to make the PNGs. If you managed todo that all so far just open index.html to view +them all :-) + +Have fun + +Tom \ No newline at end of file diff --git a/lib/hcrypto/libtommath/logs/add.log b/lib/hcrypto/libtommath/logs/add.log new file mode 100644 index 000000000..43503ac13 --- /dev/null +++ b/lib/hcrypto/libtommath/logs/add.log @@ -0,0 +1,16 @@ +480 87 +960 111 +1440 135 +1920 159 +2400 200 +2880 224 +3360 248 +3840 272 +4320 296 +4800 320 +5280 344 +5760 368 +6240 392 +6720 416 +7200 440 +7680 464 diff --git a/lib/hcrypto/libtommath/logs/addsub.png b/lib/hcrypto/libtommath/logs/addsub.png new file mode 100644 index 0000000000000000000000000000000000000000..a5679ac563e6cf347bccc70fb4694ef684375ffc GIT binary patch literal 6254 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 VShh6eoxKL~m#3?r%Q~loCIB}}tf2q^ literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/logs/expt.log b/lib/hcrypto/libtommath/logs/expt.log new file mode 100644 index 000000000..70932abc4 --- /dev/null +++ b/lib/hcrypto/libtommath/logs/expt.log @@ -0,0 +1,7 @@ +513 1435869 +769 3544970 +1025 7791638 +2049 46902238 +2561 85334899 +3073 141451412 +4097 308770310 diff --git a/lib/hcrypto/libtommath/logs/expt.png b/lib/hcrypto/libtommath/logs/expt.png new file mode 100644 index 0000000000000000000000000000000000000000..9ee8bb769feaa56ee7cffbbd5c7d39ebdb4799d3 GIT binary patch literal 6605 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 + +LibTomMath Log Plots + + + +

Addition and Subtraction

+
+
+ +

Multipliers

+
+
+ +

Exptmod

+
+
+ +

Modular Inverse

+
+
+ + + +/* $Source: /cvs/libtom/libtommath/logs/index.html,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/logs/invmod.log b/lib/hcrypto/libtommath/logs/invmod.log new file mode 100644 index 000000000..e69de29bb diff --git a/lib/hcrypto/libtommath/logs/invmod.png b/lib/hcrypto/libtommath/logs/invmod.png new file mode 100644 index 0000000000000000000000000000000000000000..0a8a4ad77170380b229a454283696e6cd4910fd0 GIT binary patch literal 4918 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 U$&a5fFfcH9y85}Sb4q9e02Qlr#Q*>R literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/logs/mult.log b/lib/hcrypto/libtommath/logs/mult.log new file mode 100644 index 000000000..33563fc67 --- /dev/null +++ b/lib/hcrypto/libtommath/logs/mult.log @@ -0,0 +1,84 @@ +271 555 +390 855 +508 1161 +631 1605 +749 2117 +871 2687 +991 3329 +1108 4084 +1231 4786 +1351 5624 +1470 6392 +1586 7364 +1710 8218 +1830 9255 +1951 10217 +2067 11461 +2191 12463 +2308 13677 +2430 14800 +2551 16232 +2671 17460 +2791 18899 +2902 20247 +3028 21902 +3151 23240 +3267 24927 +3391 26441 +3511 28277 +3631 29838 +3749 31751 +3869 33673 +3989 35431 +4111 37518 +4231 39426 +4349 41504 +4471 43567 +4591 45786 +4711 47876 +4831 50299 +4951 52427 +5071 54785 +5189 57241 +5307 59730 +5431 62194 +5551 64761 +5670 67322 +5789 70073 +5907 72663 +6030 75437 +6151 78242 +6268 81202 +6389 83948 +6509 86985 +6631 89903 +6747 93184 +6869 96044 +6991 99286 +7109 102395 +7229 105917 +7351 108940 +7470 112490 +7589 115702 +7711 119508 +7831 122632 +7951 126410 +8071 129808 +8190 133895 +8311 137146 +8431 141218 +8549 144732 +8667 149131 +8790 152462 +8911 156754 +9030 160479 +9149 165138 +9271 168601 +9391 173185 +9511 176988 +9627 181976 +9751 185539 +9870 190388 +9991 194335 +10110 199605 +10228 203298 diff --git a/lib/hcrypto/libtommath/logs/mult.png b/lib/hcrypto/libtommath/logs/mult.png new file mode 100644 index 0000000000000000000000000000000000000000..4f7a4eed7b7f12e3713b6b3f7a2191305be31612 GIT binary patch literal 6770 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 literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/logs/mult_kara.log b/lib/hcrypto/libtommath/logs/mult_kara.log new file mode 100644 index 000000000..7136c7931 --- /dev/null +++ b/lib/hcrypto/libtommath/logs/mult_kara.log @@ -0,0 +1,84 @@ +271 560 +391 870 +511 1159 +631 1605 +750 2111 +871 2737 +991 3361 +1111 4054 +1231 4778 +1351 5600 +1471 6404 +1591 7323 +1710 8255 +1831 9239 +1948 10257 +2070 11397 +2190 12531 +2308 13665 +2429 14870 +2550 16175 +2671 17539 +2787 18879 +2911 20350 +3031 21807 +3150 23415 +3270 24897 +3388 26567 +3511 28205 +3627 30076 +3751 31744 +3869 33657 +3991 35425 +4111 37522 +4229 39363 +4351 41503 +4470 43491 +4590 45827 +4711 47795 +4828 50166 +4951 52318 +5070 54911 +5191 57036 +5308 58237 +5431 60248 +5551 62678 +5671 64786 +5791 67294 +5908 69343 +6031 71607 +6151 74166 +6271 76590 +6391 78734 +6511 81175 +6631 83742 +6750 86403 +6868 88873 +6990 91150 +7110 94211 +7228 96922 +7351 99445 +7469 102216 +7589 104968 +7711 108113 +7827 110758 +7950 113714 +8071 116511 +8186 119643 +8310 122679 +8425 125581 +8551 128715 +8669 131778 +8788 135116 +8910 138138 +9031 141628 +9148 144754 +9268 148367 +9391 151551 +9511 155033 +9631 158652 +9751 162125 +9871 165248 +9988 168627 +10111 172427 +10231 176412 diff --git a/lib/hcrypto/libtommath/logs/sqr.log b/lib/hcrypto/libtommath/logs/sqr.log new file mode 100644 index 000000000..cd29fc5c1 --- /dev/null +++ b/lib/hcrypto/libtommath/logs/sqr.log @@ -0,0 +1,84 @@ +265 562 +389 882 +509 1207 +631 1572 +750 1990 +859 2433 +991 2894 +1109 3555 +1230 4228 +1350 5018 +1471 5805 +1591 6579 +1709 7415 +1829 8329 +1949 9225 +2071 10139 +2188 11239 +2309 12178 +2431 13212 +2551 14294 +2671 15551 +2791 16512 +2911 17718 +3030 18876 +3150 20259 +3270 21374 +3391 22650 +3511 23948 +3631 25493 +3750 26756 +3870 28225 +3989 29705 +4110 31409 +4230 32834 +4351 34327 +4471 35818 +4591 37636 +4711 39228 +4830 40868 +4949 42393 +5070 44541 +5191 46269 +5310 48162 +5429 49728 +5548 51985 +5671 53948 +5791 55885 +5910 57584 +6031 60082 +6150 62239 +6270 64309 +6390 66014 +6511 68766 +6631 71012 +6750 73172 +6871 74952 +6991 77909 +7111 80371 +7231 82666 +7351 84531 +7469 87698 +7589 90318 +7711 225384 +7830 232428 +7950 240009 +8070 246522 +8190 253662 +8310 260961 +8431 269253 +8549 275743 +8671 283769 +8789 290811 +8911 300034 +9030 306873 +9149 315085 +9270 323944 +9390 332390 +9508 337519 +9631 348986 +9749 356904 +9871 367013 +9989 373831 +10108 381033 +10230 393475 diff --git a/lib/hcrypto/libtommath/logs/sqr_kara.log b/lib/hcrypto/libtommath/logs/sqr_kara.log new file mode 100644 index 000000000..06355a76d --- /dev/null +++ b/lib/hcrypto/libtommath/logs/sqr_kara.log @@ -0,0 +1,84 @@ +271 560 +388 878 +511 1179 +629 1625 +751 1988 +871 2423 +989 2896 +1111 3561 +1231 4209 +1350 5015 +1470 5804 +1591 6556 +1709 7420 +1831 8263 +1951 9173 +2070 10153 +2191 11229 +2310 12167 +2431 13211 +2550 14309 +2671 15524 +2788 16525 +2910 17712 +3028 18822 +3148 20220 +3271 21343 +3391 22652 +3511 23944 +3630 25485 +3750 26778 +3868 28201 +3990 29653 +4111 31393 +4225 32841 +4350 34328 +4471 35786 +4590 37652 +4711 39245 +4830 40876 +4951 42433 +5068 44547 +5191 46321 +5311 48140 +5430 49727 +5550 52034 +5671 53954 +5791 55921 +5908 57597 +6031 60084 +6148 62226 +6270 64295 +6390 66045 +6511 68779 +6629 71003 +6751 73169 +6871 74992 +6991 77895 +7110 80376 +7231 82628 +7351 84468 +7470 87664 +7591 90284 +7711 91352 +7828 93995 +7950 96276 +8071 98691 +8190 101256 +8308 103631 +8431 105222 +8550 108343 +8671 110281 +8787 112764 +8911 115397 +9031 117690 +9151 120266 +9271 122715 +9391 124624 +9510 127937 +9630 130313 +9750 132914 +9871 136129 +9991 138517 +10108 141525 +10231 144225 diff --git a/lib/hcrypto/libtommath/logs/sub.log b/lib/hcrypto/libtommath/logs/sub.log new file mode 100644 index 000000000..9f84fa2ef --- /dev/null +++ b/lib/hcrypto/libtommath/logs/sub.log @@ -0,0 +1,16 @@ +480 94 +960 116 +1440 140 +1920 164 +2400 205 +2880 229 +3360 253 +3840 277 +4320 299 +4800 321 +5280 345 +5760 371 +6240 395 +6720 419 +7200 441 +7680 465 diff --git a/lib/hcrypto/libtommath/makefile b/lib/hcrypto/libtommath/makefile new file mode 100644 index 000000000..3e254d475 --- /dev/null +++ b/lib/hcrypto/libtommath/makefile @@ -0,0 +1,186 @@ +#Makefile for GCC +# +#Tom St Denis + +#version of library +VERSION=0.41 + +CFLAGS += -I./ -Wall -W -Wshadow -Wsign-compare + +ifndef MAKE + MAKE=make +endif + +ifndef IGNORE_SPEED + +#for speed +CFLAGS += -O3 -funroll-loops + +#for size +#CFLAGS += -Os + +#x86 optimizations [should be valid for any GCC install though] +CFLAGS += -fomit-frame-pointer + +#debug +#CFLAGS += -g3 + +endif + +#install as this user +ifndef INSTALL_GROUP + GROUP=wheel +else + GROUP=$(INSTALL_GROUP) +endif + +ifndef INSTALL_USER + USER=root +else + USER=$(INSTALL_USER) +endif + +#default files to install +ifndef LIBNAME + LIBNAME=libtommath.a +endif + +default: ${LIBNAME} + +HEADERS=tommath.h tommath_class.h tommath_superclass.h + +#LIBPATH-The directory for libtommath to be installed to. +#INCPATH-The directory to install the header files for libtommath. +#DATAPATH-The directory to install the pdf docs. +DESTDIR= +LIBPATH=/usr/lib +INCPATH=/usr/include +DATAPATH=/usr/share/doc/libtommath/pdf + +OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \ +bn_mp_clamp.o bn_mp_zero.o bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \ +bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \ +bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \ +bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \ +bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \ +bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \ +bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \ +bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \ +bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \ +bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \ +bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \ +bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \ +bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o \ +bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \ +bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \ +bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \ +bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \ +bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \ +bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \ +bn_mp_reduce_2k_l.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_2k_setup_l.o \ +bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \ +bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \ +bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \ +bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \ +bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \ +bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o + +$(LIBNAME): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $(OBJECTS) + ranlib $@ + +#make a profiled library (takes a while!!!) +# +# This will build the library with profile generation +# then run the test demo and rebuild the library. +# +# So far I've seen improvements in the MP math +profiled: + make CFLAGS="$(CFLAGS) -fprofile-arcs -DTESTING" timing + ./ltmtest + rm -f *.a *.o ltmtest + make CFLAGS="$(CFLAGS) -fbranch-probabilities" + +#make a single object profiled library +profiled_single: + perl gen.pl + $(CC) $(CFLAGS) -fprofile-arcs -DTESTING -c mpi.c -o mpi.o + $(CC) $(CFLAGS) -DTESTING -DTIMER demo/timing.c mpi.o -o ltmtest + ./ltmtest + rm -f *.o ltmtest + $(CC) $(CFLAGS) -fbranch-probabilities -DTESTING -c mpi.c -o mpi.o + $(AR) $(ARFLAGS) $(LIBNAME) mpi.o + ranlib $(LIBNAME) + +install: $(LIBNAME) + install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH) + install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH) + install -g $(GROUP) -o $(USER) $(LIBNAME) $(DESTDIR)$(LIBPATH) + install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH) + +test: $(LIBNAME) demo/demo.o + $(CC) $(CFLAGS) demo/demo.o $(LIBNAME) -o test + +mtest: test + cd mtest ; $(CC) $(CFLAGS) mtest.c -o mtest + +timing: $(LIBNAME) + $(CC) $(CFLAGS) -DTIMER demo/timing.c $(LIBNAME) -o ltmtest + +# makes the LTM book DVI file, requires tetex, perl and makeindex [part of tetex I think] +docdvi: tommath.src + cd pics ; MAKE=${MAKE} ${MAKE} + echo "hello" > tommath.ind + perl booker.pl + latex tommath > /dev/null + latex tommath > /dev/null + makeindex tommath + latex tommath > /dev/null + +# poster, makes the single page PDF poster +poster: poster.tex + pdflatex poster + rm -f poster.aux poster.log + +# makes the LTM book PDF file, requires tetex, cleans up the LaTeX temp files +docs: docdvi + dvipdf tommath + rm -f tommath.log tommath.aux tommath.dvi tommath.idx tommath.toc tommath.lof tommath.ind tommath.ilg + cd pics ; MAKE=${MAKE} ${MAKE} clean + +#LTM user manual +mandvi: bn.tex + echo "hello" > bn.ind + latex bn > /dev/null + latex bn > /dev/null + makeindex bn + latex bn > /dev/null + +#LTM user manual [pdf] +manual: mandvi + pdflatex bn >/dev/null + rm -f bn.aux bn.dvi bn.log bn.idx bn.lof bn.out bn.toc + +pretty: + perl pretty.build + +clean: + rm -f *.bat *.pdf *.o *.a *.obj *.lib *.exe *.dll etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \ + *.idx *.toc *.log *.aux *.dvi *.lof *.ind *.ilg *.ps *.log *.s mpi.c *.da *.dyn *.dpi tommath.tex `find . -type f | grep [~] | xargs` *.lo *.la + rm -rf .libs + cd etc ; MAKE=${MAKE} ${MAKE} clean + cd pics ; MAKE=${MAKE} ${MAKE} clean + +#zipup the project (take that!) +no_oops: clean + cd .. ; cvs commit + echo Scanning for scratch/dirty files + find . -type f | grep -v CVS | xargs -n 1 bash mess.sh + +zipup: clean manual poster docs + perl gen.pl ; mv mpi.c pre_gen/ ; \ + cd .. ; rm -rf ltm* libtommath-$(VERSION) ; mkdir libtommath-$(VERSION) ; \ + cp -R ./libtommath/* ./libtommath-$(VERSION)/ ; \ + tar -c libtommath-$(VERSION)/* | bzip2 -9vvc > ltm-$(VERSION).tar.bz2 ; \ + zip -9 -r ltm-$(VERSION).zip libtommath-$(VERSION)/* ; \ + mv -f ltm* ~ ; rm -rf libtommath-$(VERSION) diff --git a/lib/hcrypto/libtommath/makefile.bcc b/lib/hcrypto/libtommath/makefile.bcc new file mode 100644 index 000000000..67743d962 --- /dev/null +++ b/lib/hcrypto/libtommath/makefile.bcc @@ -0,0 +1,44 @@ +# +# Borland C++Builder Makefile (makefile.bcc) +# + + +LIB = tlib +CC = bcc32 +CFLAGS = -c -O2 -I. + +OBJECTS=bncore.obj bn_mp_init.obj bn_mp_clear.obj bn_mp_exch.obj bn_mp_grow.obj bn_mp_shrink.obj \ +bn_mp_clamp.obj bn_mp_zero.obj bn_mp_set.obj bn_mp_set_int.obj bn_mp_init_size.obj bn_mp_copy.obj \ +bn_mp_init_copy.obj bn_mp_abs.obj bn_mp_neg.obj bn_mp_cmp_mag.obj bn_mp_cmp.obj bn_mp_cmp_d.obj \ +bn_mp_rshd.obj bn_mp_lshd.obj bn_mp_mod_2d.obj bn_mp_div_2d.obj bn_mp_mul_2d.obj bn_mp_div_2.obj \ +bn_mp_mul_2.obj bn_s_mp_add.obj bn_s_mp_sub.obj bn_fast_s_mp_mul_digs.obj bn_s_mp_mul_digs.obj \ +bn_fast_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs.obj bn_fast_s_mp_sqr.obj bn_s_mp_sqr.obj \ +bn_mp_add.obj bn_mp_sub.obj bn_mp_karatsuba_mul.obj bn_mp_mul.obj bn_mp_karatsuba_sqr.obj \ +bn_mp_sqr.obj bn_mp_div.obj bn_mp_mod.obj bn_mp_add_d.obj bn_mp_sub_d.obj bn_mp_mul_d.obj \ +bn_mp_div_d.obj bn_mp_mod_d.obj bn_mp_expt_d.obj bn_mp_addmod.obj bn_mp_submod.obj \ +bn_mp_mulmod.obj bn_mp_sqrmod.obj bn_mp_gcd.obj bn_mp_lcm.obj bn_fast_mp_invmod.obj bn_mp_invmod.obj \ +bn_mp_reduce.obj bn_mp_montgomery_setup.obj bn_fast_mp_montgomery_reduce.obj bn_mp_montgomery_reduce.obj \ +bn_mp_exptmod_fast.obj bn_mp_exptmod.obj bn_mp_2expt.obj bn_mp_n_root.obj bn_mp_jacobi.obj bn_reverse.obj \ +bn_mp_count_bits.obj bn_mp_read_unsigned_bin.obj bn_mp_read_signed_bin.obj bn_mp_to_unsigned_bin.obj \ +bn_mp_to_signed_bin.obj bn_mp_unsigned_bin_size.obj bn_mp_signed_bin_size.obj \ +bn_mp_xor.obj bn_mp_and.obj bn_mp_or.obj bn_mp_rand.obj bn_mp_montgomery_calc_normalization.obj \ +bn_mp_prime_is_divisible.obj bn_prime_tab.obj bn_mp_prime_fermat.obj bn_mp_prime_miller_rabin.obj \ +bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj \ +bn_mp_dr_is_modulus.obj bn_mp_dr_setup.obj bn_mp_reduce_setup.obj \ +bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \ +bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \ +bn_mp_reduce_2k_l.obj bn_mp_reduce_is_2k_l.obj bn_mp_reduce_2k_setup_l.obj \ +bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \ +bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \ +bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_exteuclid.obj bn_mp_toradix_n.obj \ +bn_mp_prime_random_ex.obj bn_mp_get_int.obj bn_mp_sqrt.obj bn_mp_is_square.obj \ +bn_mp_init_set.obj bn_mp_init_set_int.obj bn_mp_invmod_slow.obj bn_mp_prime_rabin_miller_trials.obj \ +bn_mp_to_signed_bin_n.obj bn_mp_to_unsigned_bin_n.obj + +TARGET = libtommath.lib + +$(TARGET): $(OBJECTS) + +.c.obj: + $(CC) $(CFLAGS) $< + $(LIB) $(TARGET) -+$@ diff --git a/lib/hcrypto/libtommath/makefile.cygwin_dll b/lib/hcrypto/libtommath/makefile.cygwin_dll new file mode 100644 index 000000000..85a9b2053 --- /dev/null +++ b/lib/hcrypto/libtommath/makefile.cygwin_dll @@ -0,0 +1,55 @@ +#Makefile for Cygwin-GCC +# +#This makefile will build a Windows DLL [doesn't require cygwin to run] in the file +#libtommath.dll. The import library is in libtommath.dll.a. Remember to add +#"-Wl,--enable-auto-import" to your client build to avoid the auto-import warnings +# +#Tom St Denis +CFLAGS += -I./ -Wall -W -Wshadow -O3 -funroll-loops -mno-cygwin + +#x86 optimizations [should be valid for any GCC install though] +CFLAGS += -fomit-frame-pointer + +default: windll + +OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \ +bn_mp_clamp.o bn_mp_zero.o bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \ +bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \ +bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \ +bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \ +bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \ +bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \ +bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \ +bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \ +bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \ +bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \ +bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \ +bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \ +bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o \ +bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \ +bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \ +bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \ +bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \ +bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \ +bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \ +bn_mp_reduce_2k_l.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_2k_setup_l.o \ +bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \ +bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \ +bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \ +bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \ +bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \ +bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o + +# make a Windows DLL via Cygwin +windll: $(OBJECTS) + gcc -mno-cygwin -mdll -o libtommath.dll -Wl,--out-implib=libtommath.dll.a -Wl,--export-all-symbols *.o + ranlib libtommath.dll.a + +# build the test program using the windows DLL +test: $(OBJECTS) windll + gcc $(CFLAGS) demo/demo.c libtommath.dll.a -Wl,--enable-auto-import -o test -s + cd mtest ; $(CC) -O3 -fomit-frame-pointer -funroll-loops mtest.c -o mtest -s + +/* $Source: /cvs/libtom/libtommath/makefile.cygwin_dll,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:45 $ */ diff --git a/lib/hcrypto/libtommath/makefile.icc b/lib/hcrypto/libtommath/makefile.icc new file mode 100644 index 000000000..cf70ab0c2 --- /dev/null +++ b/lib/hcrypto/libtommath/makefile.icc @@ -0,0 +1,116 @@ +#Makefile for ICC +# +#Tom St Denis +CC=icc + +CFLAGS += -I./ + +# optimize for SPEED +# +# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4 +# -ax? specifies make code specifically for ? but compatible with IA-32 +# -x? specifies compile solely for ? [not specifically IA-32 compatible] +# +# where ? is +# K - PIII +# W - first P4 [Williamette] +# N - P4 Northwood +# P - P4 Prescott +# B - Blend of P4 and PM [mobile] +# +# Default to just generic max opts +CFLAGS += -O3 -xP -ip + +#install as this user +USER=root +GROUP=root + +default: libtommath.a + +#default files to install +LIBNAME=libtommath.a +HEADERS=tommath.h + +#LIBPATH-The directory for libtomcrypt to be installed to. +#INCPATH-The directory to install the header files for libtommath. +#DATAPATH-The directory to install the pdf docs. +DESTDIR= +LIBPATH=/usr/lib +INCPATH=/usr/include +DATAPATH=/usr/share/doc/libtommath/pdf + +OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \ +bn_mp_clamp.o bn_mp_zero.o bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \ +bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \ +bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \ +bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \ +bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \ +bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \ +bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \ +bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \ +bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \ +bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \ +bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \ +bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \ +bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o \ +bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \ +bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \ +bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \ +bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \ +bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \ +bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \ +bn_mp_reduce_2k_l.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_2k_setup_l.o \ +bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \ +bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \ +bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \ +bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \ +bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \ +bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o + +libtommath.a: $(OBJECTS) + $(AR) $(ARFLAGS) libtommath.a $(OBJECTS) + ranlib libtommath.a + +#make a profiled library (takes a while!!!) +# +# This will build the library with profile generation +# then run the test demo and rebuild the library. +# +# So far I've seen improvements in the MP math +profiled: + make -f makefile.icc CFLAGS="$(CFLAGS) -prof_gen -DTESTING" timing + ./ltmtest + rm -f *.a *.o ltmtest + make -f makefile.icc CFLAGS="$(CFLAGS) -prof_use" + +#make a single object profiled library +profiled_single: + perl gen.pl + $(CC) $(CFLAGS) -prof_gen -DTESTING -c mpi.c -o mpi.o + $(CC) $(CFLAGS) -DTESTING -DTIMER demo/demo.c mpi.o -o ltmtest + ./ltmtest + rm -f *.o ltmtest + $(CC) $(CFLAGS) -prof_use -ip -DTESTING -c mpi.c -o mpi.o + $(AR) $(ARFLAGS) libtommath.a mpi.o + ranlib libtommath.a + +install: libtommath.a + install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH) + install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH) + install -g $(GROUP) -o $(USER) $(LIBNAME) $(DESTDIR)$(LIBPATH) + install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH) + +test: libtommath.a demo/demo.o + $(CC) demo/demo.o libtommath.a -o test + +mtest: test + cd mtest ; $(CC) $(CFLAGS) mtest.c -o mtest + +timing: libtommath.a + $(CC) $(CFLAGS) -DTIMER demo/timing.c libtommath.a -o ltmtest + +clean: + rm -f *.bat *.pdf *.o *.a *.obj *.lib *.exe *.dll etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \ + *.idx *.toc *.log *.aux *.dvi *.lof *.ind *.ilg *.ps *.log *.s mpi.c *.il etc/*.il *.dyn + cd etc ; make clean + cd pics ; make clean diff --git a/lib/hcrypto/libtommath/makefile.msvc b/lib/hcrypto/libtommath/makefile.msvc new file mode 100644 index 000000000..5edebec92 --- /dev/null +++ b/lib/hcrypto/libtommath/makefile.msvc @@ -0,0 +1,40 @@ +#MSVC Makefile +# +#Tom St Denis + +CFLAGS = /I. /Ox /DWIN32 /W3 /Fo$@ + +default: library + +OBJECTS=bncore.obj bn_mp_init.obj bn_mp_clear.obj bn_mp_exch.obj bn_mp_grow.obj bn_mp_shrink.obj \ +bn_mp_clamp.obj bn_mp_zero.obj bn_mp_set.obj bn_mp_set_int.obj bn_mp_init_size.obj bn_mp_copy.obj \ +bn_mp_init_copy.obj bn_mp_abs.obj bn_mp_neg.obj bn_mp_cmp_mag.obj bn_mp_cmp.obj bn_mp_cmp_d.obj \ +bn_mp_rshd.obj bn_mp_lshd.obj bn_mp_mod_2d.obj bn_mp_div_2d.obj bn_mp_mul_2d.obj bn_mp_div_2.obj \ +bn_mp_mul_2.obj bn_s_mp_add.obj bn_s_mp_sub.obj bn_fast_s_mp_mul_digs.obj bn_s_mp_mul_digs.obj \ +bn_fast_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs.obj bn_fast_s_mp_sqr.obj bn_s_mp_sqr.obj \ +bn_mp_add.obj bn_mp_sub.obj bn_mp_karatsuba_mul.obj bn_mp_mul.obj bn_mp_karatsuba_sqr.obj \ +bn_mp_sqr.obj bn_mp_div.obj bn_mp_mod.obj bn_mp_add_d.obj bn_mp_sub_d.obj bn_mp_mul_d.obj \ +bn_mp_div_d.obj bn_mp_mod_d.obj bn_mp_expt_d.obj bn_mp_addmod.obj bn_mp_submod.obj \ +bn_mp_mulmod.obj bn_mp_sqrmod.obj bn_mp_gcd.obj bn_mp_lcm.obj bn_fast_mp_invmod.obj bn_mp_invmod.obj \ +bn_mp_reduce.obj bn_mp_montgomery_setup.obj bn_fast_mp_montgomery_reduce.obj bn_mp_montgomery_reduce.obj \ +bn_mp_exptmod_fast.obj bn_mp_exptmod.obj bn_mp_2expt.obj bn_mp_n_root.obj bn_mp_jacobi.obj bn_reverse.obj \ +bn_mp_count_bits.obj bn_mp_read_unsigned_bin.obj bn_mp_read_signed_bin.obj bn_mp_to_unsigned_bin.obj \ +bn_mp_to_signed_bin.obj bn_mp_unsigned_bin_size.obj bn_mp_signed_bin_size.obj \ +bn_mp_xor.obj bn_mp_and.obj bn_mp_or.obj bn_mp_rand.obj bn_mp_montgomery_calc_normalization.obj \ +bn_mp_prime_is_divisible.obj bn_prime_tab.obj bn_mp_prime_fermat.obj bn_mp_prime_miller_rabin.obj \ +bn_mp_prime_is_prime.obj bn_mp_prime_next_prime.obj bn_mp_dr_reduce.obj \ +bn_mp_dr_is_modulus.obj bn_mp_dr_setup.obj bn_mp_reduce_setup.obj \ +bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \ +bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \ +bn_mp_reduce_2k_l.obj bn_mp_reduce_is_2k_l.obj bn_mp_reduce_2k_setup_l.obj \ +bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \ +bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \ +bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_exteuclid.obj bn_mp_toradix_n.obj \ +bn_mp_prime_random_ex.obj bn_mp_get_int.obj bn_mp_sqrt.obj bn_mp_is_square.obj \ +bn_mp_init_set.obj bn_mp_init_set_int.obj bn_mp_invmod_slow.obj bn_mp_prime_rabin_miller_trials.obj \ +bn_mp_to_signed_bin_n.obj bn_mp_to_unsigned_bin_n.obj + +HEADERS=tommath.h tommath_class.h tommath_superclass.h + +library: $(OBJECTS) + lib /out:tommath.lib $(OBJECTS) diff --git a/lib/hcrypto/libtommath/makefile.shared b/lib/hcrypto/libtommath/makefile.shared new file mode 100644 index 000000000..f17bbbd48 --- /dev/null +++ b/lib/hcrypto/libtommath/makefile.shared @@ -0,0 +1,102 @@ +#Makefile for GCC +# +#Tom St Denis +VERSION=0:41 + +CC = libtool --mode=compile --tag=CC gcc + +CFLAGS += -I./ -Wall -W -Wshadow -Wsign-compare + +ifndef IGNORE_SPEED + +#for speed +CFLAGS += -O3 -funroll-loops + +#for size +#CFLAGS += -Os + +#x86 optimizations [should be valid for any GCC install though] +CFLAGS += -fomit-frame-pointer + +endif + +#install as this user +ifndef INSTALL_GROUP + GROUP=wheel +else + GROUP=$(INSTALL_GROUP) +endif + +ifndef INSTALL_USER + USER=root +else + USER=$(INSTALL_USER) +endif + +default: libtommath.la + +#default files to install +ifndef LIBNAME + LIBNAME=libtommath.la +endif +ifndef LIBNAME_S + LIBNAME_S=libtommath.a +endif +HEADERS=tommath.h tommath_class.h tommath_superclass.h + +#LIBPATH-The directory for libtommath to be installed to. +#INCPATH-The directory to install the header files for libtommath. +#DATAPATH-The directory to install the pdf docs. +DESTDIR= +LIBPATH=/usr/lib +INCPATH=/usr/include +DATAPATH=/usr/share/doc/libtommath/pdf + +OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \ +bn_mp_clamp.o bn_mp_zero.o bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \ +bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \ +bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \ +bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \ +bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \ +bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \ +bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \ +bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \ +bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \ +bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \ +bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \ +bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \ +bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o \ +bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \ +bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \ +bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \ +bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \ +bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \ +bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \ +bn_mp_reduce_2k_l.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_2k_setup_l.o \ +bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \ +bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \ +bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_exteuclid.o bn_mp_toradix_n.o \ +bn_mp_prime_random_ex.o bn_mp_get_int.o bn_mp_sqrt.o bn_mp_is_square.o bn_mp_init_set.o \ +bn_mp_init_set_int.o bn_mp_invmod_slow.o bn_mp_prime_rabin_miller_trials.o \ +bn_mp_to_signed_bin_n.o bn_mp_to_unsigned_bin_n.o + +objs: $(OBJECTS) + +$(LIBNAME): $(OBJECTS) + libtool --mode=link gcc *.lo -o $(LIBNAME) -rpath $(LIBPATH) -version-info $(VERSION) + +install: $(LIBNAME) + install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(LIBPATH) + libtool --mode=install install -c $(LIBNAME) $(DESTDIR)$(LIBPATH)/$(LIBNAME) + install -d -g $(GROUP) -o $(USER) $(DESTDIR)$(INCPATH) + install -g $(GROUP) -o $(USER) $(HEADERS) $(DESTDIR)$(INCPATH) + +test: $(LIBNAME) demo/demo.o + gcc $(CFLAGS) -c demo/demo.c -o demo/demo.o + libtool --mode=link gcc -o test demo/demo.o $(LIBNAME_S) + +mtest: test + cd mtest ; gcc $(CFLAGS) mtest.c -o mtest + +timing: $(LIBNAME) + gcc $(CFLAGS) -DTIMER demo/timing.c $(LIBNAME_S) -o ltmtest diff --git a/lib/hcrypto/libtommath/mess.sh b/lib/hcrypto/libtommath/mess.sh new file mode 100644 index 000000000..bf639ce3b --- /dev/null +++ b/lib/hcrypto/libtommath/mess.sh @@ -0,0 +1,4 @@ +#!/bin/bash +if cvs log $1 >/dev/null 2>/dev/null; then exit 0; else echo "$1 shouldn't be here" ; exit 1; fi + + diff --git a/lib/hcrypto/libtommath/mtest/logtab.h b/lib/hcrypto/libtommath/mtest/logtab.h new file mode 100644 index 000000000..bbefaefc0 --- /dev/null +++ b/lib/hcrypto/libtommath/mtest/logtab.h @@ -0,0 +1,24 @@ +const float s_logv_2[] = { + 0.000000000, 0.000000000, 1.000000000, 0.630929754, /* 0 1 2 3 */ + 0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4 5 6 7 */ + 0.333333333, 0.315464877, 0.301029996, 0.289064826, /* 8 9 10 11 */ + 0.278942946, 0.270238154, 0.262649535, 0.255958025, /* 12 13 14 15 */ + 0.250000000, 0.244650542, 0.239812467, 0.235408913, /* 16 17 18 19 */ + 0.231378213, 0.227670249, 0.224243824, 0.221064729, /* 20 21 22 23 */ + 0.218104292, 0.215338279, 0.212746054, 0.210309918, /* 24 25 26 27 */ + 0.208014598, 0.205846832, 0.203795047, 0.201849087, /* 28 29 30 31 */ + 0.200000000, 0.198239863, 0.196561632, 0.194959022, /* 32 33 34 35 */ + 0.193426404, 0.191958720, 0.190551412, 0.189200360, /* 36 37 38 39 */ + 0.187901825, 0.186652411, 0.185449023, 0.184288833, /* 40 41 42 43 */ + 0.183169251, 0.182087900, 0.181042597, 0.180031327, /* 44 45 46 47 */ + 0.179052232, 0.178103594, 0.177183820, 0.176291434, /* 48 49 50 51 */ + 0.175425064, 0.174583430, 0.173765343, 0.172969690, /* 52 53 54 55 */ + 0.172195434, 0.171441601, 0.170707280, 0.169991616, /* 56 57 58 59 */ + 0.169293808, 0.168613099, 0.167948779, 0.167300179, /* 60 61 62 63 */ + 0.166666667 +}; + + +/* $Source: /cvs/libtom/libtommath/mtest/logtab.h,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/mtest/mpi-config.h b/lib/hcrypto/libtommath/mtest/mpi-config.h new file mode 100644 index 000000000..6049c25ba --- /dev/null +++ b/lib/hcrypto/libtommath/mtest/mpi-config.h @@ -0,0 +1,90 @@ +/* Default configuration for MPI library */ +/* $Id: mpi-config.h,v 1.2 2005/05/05 14:38:47 tom Exp $ */ + +#ifndef MPI_CONFIG_H_ +#define MPI_CONFIG_H_ + +/* + For boolean options, + 0 = no + 1 = yes + + Other options are documented individually. + + */ + +#ifndef MP_IOFUNC +#define MP_IOFUNC 0 /* include mp_print() ? */ +#endif + +#ifndef MP_MODARITH +#define MP_MODARITH 1 /* include modular arithmetic ? */ +#endif + +#ifndef MP_NUMTH +#define MP_NUMTH 1 /* include number theoretic functions? */ +#endif + +#ifndef MP_LOGTAB +#define MP_LOGTAB 1 /* use table of logs instead of log()? */ +#endif + +#ifndef MP_MEMSET +#define MP_MEMSET 1 /* use memset() to zero buffers? */ +#endif + +#ifndef MP_MEMCPY +#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */ +#endif + +#ifndef MP_CRYPTO +#define MP_CRYPTO 1 /* erase memory on free? */ +#endif + +#ifndef MP_ARGCHK +/* + 0 = no parameter checks + 1 = runtime checks, continue execution and return an error to caller + 2 = assertions; dump core on parameter errors + */ +#define MP_ARGCHK 2 /* how to check input arguments */ +#endif + +#ifndef MP_DEBUG +#define MP_DEBUG 0 /* print diagnostic output? */ +#endif + +#ifndef MP_DEFPREC +#define MP_DEFPREC 64 /* default precision, in digits */ +#endif + +#ifndef MP_MACRO +#define MP_MACRO 1 /* use macros for frequent calls? */ +#endif + +#ifndef MP_SQUARE +#define MP_SQUARE 1 /* use separate squaring code? */ +#endif + +#ifndef MP_PTAB_SIZE +/* + When building mpprime.c, we build in a table of small prime + values to use for primality testing. The more you include, + the more space they take up. See primes.c for the possible + values (currently 16, 32, 64, 128, 256, and 6542) + */ +#define MP_PTAB_SIZE 128 /* how many built-in primes? */ +#endif + +#ifndef MP_COMPAT_MACROS +#define MP_COMPAT_MACROS 1 /* define compatibility macros? */ +#endif + +#endif /* ifndef MPI_CONFIG_H_ */ + + +/* crc==3287762869, version==2, Sat Feb 02 06:43:53 2002 */ + +/* $Source: /cvs/libtom/libtommath/mtest/mpi-config.h,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/mtest/mpi-types.h b/lib/hcrypto/libtommath/mtest/mpi-types.h new file mode 100644 index 000000000..026de589d --- /dev/null +++ b/lib/hcrypto/libtommath/mtest/mpi-types.h @@ -0,0 +1,20 @@ +/* Type definitions generated by 'types.pl' */ +typedef char mp_sign; +typedef unsigned short mp_digit; /* 2 byte type */ +typedef unsigned int mp_word; /* 4 byte type */ +typedef unsigned int mp_size; +typedef int mp_err; + +#define MP_DIGIT_BIT (CHAR_BIT*sizeof(mp_digit)) +#define MP_DIGIT_MAX USHRT_MAX +#define MP_WORD_BIT (CHAR_BIT*sizeof(mp_word)) +#define MP_WORD_MAX UINT_MAX + +#define MP_DIGIT_SIZE 2 +#define DIGIT_FMT "%04X" +#define RADIX (MP_DIGIT_MAX+1) + + +/* $Source: /cvs/libtom/libtommath/mtest/mpi-types.h,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/mtest/mpi.c b/lib/hcrypto/libtommath/mtest/mpi.c new file mode 100644 index 000000000..7c712dd62 --- /dev/null +++ b/lib/hcrypto/libtommath/mtest/mpi.c @@ -0,0 +1,3985 @@ +/* + mpi.c + + by Michael J. Fromberger + Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved + + Arbitrary precision integer arithmetic library + + $Id: mpi.c,v 1.2 2005/05/05 14:38:47 tom Exp $ + */ + +#include "mpi.h" +#include +#include +#include + +#if MP_DEBUG +#include + +#define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);} +#else +#define DIAG(T,V) +#endif + +/* + If MP_LOGTAB is not defined, use the math library to compute the + logarithms on the fly. Otherwise, use the static table below. + Pick which works best for your system. + */ +#if MP_LOGTAB + +/* {{{ s_logv_2[] - log table for 2 in various bases */ + +/* + A table of the logs of 2 for various bases (the 0 and 1 entries of + this table are meaningless and should not be referenced). + + This table is used to compute output lengths for the mp_toradix() + function. Since a number n in radix r takes up about log_r(n) + digits, we estimate the output size by taking the least integer + greater than log_r(n), where: + + log_r(n) = log_2(n) * log_r(2) + + This table, therefore, is a table of log_r(2) for 2 <= r <= 36, + which are the output bases supported. + */ + +#include "logtab.h" + +/* }}} */ +#define LOG_V_2(R) s_logv_2[(R)] + +#else + +#include +#define LOG_V_2(R) (log(2.0)/log(R)) + +#endif + +/* Default precision for newly created mp_int's */ +static unsigned int s_mp_defprec = MP_DEFPREC; + +/* {{{ Digit arithmetic macros */ + +/* + When adding and multiplying digits, the results can be larger than + can be contained in an mp_digit. Thus, an mp_word is used. These + macros mask off the upper and lower digits of the mp_word (the + mp_word may be more than 2 mp_digits wide, but we only concern + ourselves with the low-order 2 mp_digits) + + If your mp_word DOES have more than 2 mp_digits, you need to + uncomment the first line, and comment out the second. + */ + +/* #define CARRYOUT(W) (((W)>>DIGIT_BIT)&MP_DIGIT_MAX) */ +#define CARRYOUT(W) ((W)>>DIGIT_BIT) +#define ACCUM(W) ((W)&MP_DIGIT_MAX) + +/* }}} */ + +/* {{{ Comparison constants */ + +#define MP_LT -1 +#define MP_EQ 0 +#define MP_GT 1 + +/* }}} */ + +/* {{{ Constant strings */ + +/* Constant strings returned by mp_strerror() */ +static const char *mp_err_string[] = { + "unknown result code", /* say what? */ + "boolean true", /* MP_OKAY, MP_YES */ + "boolean false", /* MP_NO */ + "out of memory", /* MP_MEM */ + "argument out of range", /* MP_RANGE */ + "invalid input parameter", /* MP_BADARG */ + "result is undefined" /* MP_UNDEF */ +}; + +/* Value to digit maps for radix conversion */ + +/* s_dmap_1 - standard digits and letters */ +static const char *s_dmap_1 = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; + +#if 0 +/* s_dmap_2 - base64 ordering for digits */ +static const char *s_dmap_2 = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +#endif + +/* }}} */ + +/* {{{ Static function declarations */ + +/* + If MP_MACRO is false, these will be defined as actual functions; + otherwise, suitable macro definitions will be used. This works + around the fact that ANSI C89 doesn't support an 'inline' keyword + (although I hear C9x will ... about bloody time). At present, the + macro definitions are identical to the function bodies, but they'll + expand in place, instead of generating a function call. + + I chose these particular functions to be made into macros because + some profiling showed they are called a lot on a typical workload, + and yet they are primarily housekeeping. + */ +#if MP_MACRO == 0 + void s_mp_setz(mp_digit *dp, mp_size count); /* zero digits */ + void s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count); /* copy */ + void *s_mp_alloc(size_t nb, size_t ni); /* general allocator */ + void s_mp_free(void *ptr); /* general free function */ +#else + + /* Even if these are defined as macros, we need to respect the settings + of the MP_MEMSET and MP_MEMCPY configuration options... + */ + #if MP_MEMSET == 0 + #define s_mp_setz(dp, count) \ + {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;} + #else + #define s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit)) + #endif /* MP_MEMSET */ + + #if MP_MEMCPY == 0 + #define s_mp_copy(sp, dp, count) \ + {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];} + #else + #define s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit)) + #endif /* MP_MEMCPY */ + + #define s_mp_alloc(nb, ni) calloc(nb, ni) + #define s_mp_free(ptr) {if(ptr) free(ptr);} +#endif /* MP_MACRO */ + +mp_err s_mp_grow(mp_int *mp, mp_size min); /* increase allocated size */ +mp_err s_mp_pad(mp_int *mp, mp_size min); /* left pad with zeroes */ + +void s_mp_clamp(mp_int *mp); /* clip leading zeroes */ + +void s_mp_exch(mp_int *a, mp_int *b); /* swap a and b in place */ + +mp_err s_mp_lshd(mp_int *mp, mp_size p); /* left-shift by p digits */ +void s_mp_rshd(mp_int *mp, mp_size p); /* right-shift by p digits */ +void s_mp_div_2d(mp_int *mp, mp_digit d); /* divide by 2^d in place */ +void s_mp_mod_2d(mp_int *mp, mp_digit d); /* modulo 2^d in place */ +mp_err s_mp_mul_2d(mp_int *mp, mp_digit d); /* multiply by 2^d in place*/ +void s_mp_div_2(mp_int *mp); /* divide by 2 in place */ +mp_err s_mp_mul_2(mp_int *mp); /* multiply by 2 in place */ +mp_digit s_mp_norm(mp_int *a, mp_int *b); /* normalize for division */ +mp_err s_mp_add_d(mp_int *mp, mp_digit d); /* unsigned digit addition */ +mp_err s_mp_sub_d(mp_int *mp, mp_digit d); /* unsigned digit subtract */ +mp_err s_mp_mul_d(mp_int *mp, mp_digit d); /* unsigned digit multiply */ +mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r); + /* unsigned digit divide */ +mp_err s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu); + /* Barrett reduction */ +mp_err s_mp_add(mp_int *a, mp_int *b); /* magnitude addition */ +mp_err s_mp_sub(mp_int *a, mp_int *b); /* magnitude subtract */ +mp_err s_mp_mul(mp_int *a, mp_int *b); /* magnitude multiply */ +#if 0 +void s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len); + /* multiply buffers in place */ +#endif +#if MP_SQUARE +mp_err s_mp_sqr(mp_int *a); /* magnitude square */ +#else +#define s_mp_sqr(a) s_mp_mul(a, a) +#endif +mp_err s_mp_div(mp_int *a, mp_int *b); /* magnitude divide */ +mp_err s_mp_2expt(mp_int *a, mp_digit k); /* a = 2^k */ +int s_mp_cmp(mp_int *a, mp_int *b); /* magnitude comparison */ +int s_mp_cmp_d(mp_int *a, mp_digit d); /* magnitude digit compare */ +int s_mp_ispow2(mp_int *v); /* is v a power of 2? */ +int s_mp_ispow2d(mp_digit d); /* is d a power of 2? */ + +int s_mp_tovalue(char ch, int r); /* convert ch to value */ +char s_mp_todigit(int val, int r, int low); /* convert val to digit */ +int s_mp_outlen(int bits, int r); /* output length in bytes */ + +/* }}} */ + +/* {{{ Default precision manipulation */ + +unsigned int mp_get_prec(void) +{ + return s_mp_defprec; + +} /* end mp_get_prec() */ + +void mp_set_prec(unsigned int prec) +{ + if(prec == 0) + s_mp_defprec = MP_DEFPREC; + else + s_mp_defprec = prec; + +} /* end mp_set_prec() */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ mp_init(mp) */ + +/* + mp_init(mp) + + Initialize a new zero-valued mp_int. Returns MP_OKAY if successful, + MP_MEM if memory could not be allocated for the structure. + */ + +mp_err mp_init(mp_int *mp) +{ + return mp_init_size(mp, s_mp_defprec); + +} /* end mp_init() */ + +/* }}} */ + +/* {{{ mp_init_array(mp[], count) */ + +mp_err mp_init_array(mp_int mp[], int count) +{ + mp_err res; + int pos; + + ARGCHK(mp !=NULL && count > 0, MP_BADARG); + + for(pos = 0; pos < count; ++pos) { + if((res = mp_init(&mp[pos])) != MP_OKAY) + goto CLEANUP; + } + + return MP_OKAY; + + CLEANUP: + while(--pos >= 0) + mp_clear(&mp[pos]); + + return res; + +} /* end mp_init_array() */ + +/* }}} */ + +/* {{{ mp_init_size(mp, prec) */ + +/* + mp_init_size(mp, prec) + + Initialize a new zero-valued mp_int with at least the given + precision; returns MP_OKAY if successful, or MP_MEM if memory could + not be allocated for the structure. + */ + +mp_err mp_init_size(mp_int *mp, mp_size prec) +{ + ARGCHK(mp != NULL && prec > 0, MP_BADARG); + + if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit))) == NULL) + return MP_MEM; + + SIGN(mp) = MP_ZPOS; + USED(mp) = 1; + ALLOC(mp) = prec; + + return MP_OKAY; + +} /* end mp_init_size() */ + +/* }}} */ + +/* {{{ mp_init_copy(mp, from) */ + +/* + mp_init_copy(mp, from) + + Initialize mp as an exact copy of from. Returns MP_OKAY if + successful, MP_MEM if memory could not be allocated for the new + structure. + */ + +mp_err mp_init_copy(mp_int *mp, mp_int *from) +{ + ARGCHK(mp != NULL && from != NULL, MP_BADARG); + + if(mp == from) + return MP_OKAY; + + if((DIGITS(mp) = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL) + return MP_MEM; + + s_mp_copy(DIGITS(from), DIGITS(mp), USED(from)); + USED(mp) = USED(from); + ALLOC(mp) = USED(from); + SIGN(mp) = SIGN(from); + + return MP_OKAY; + +} /* end mp_init_copy() */ + +/* }}} */ + +/* {{{ mp_copy(from, to) */ + +/* + mp_copy(from, to) + + Copies the mp_int 'from' to the mp_int 'to'. It is presumed that + 'to' has already been initialized (if not, use mp_init_copy() + instead). If 'from' and 'to' are identical, nothing happens. + */ + +mp_err mp_copy(mp_int *from, mp_int *to) +{ + ARGCHK(from != NULL && to != NULL, MP_BADARG); + + if(from == to) + return MP_OKAY; + + { /* copy */ + mp_digit *tmp; + + /* + If the allocated buffer in 'to' already has enough space to hold + all the used digits of 'from', we'll re-use it to avoid hitting + the memory allocater more than necessary; otherwise, we'd have + to grow anyway, so we just allocate a hunk and make the copy as + usual + */ + if(ALLOC(to) >= USED(from)) { + s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from)); + s_mp_copy(DIGITS(from), DIGITS(to), USED(from)); + + } else { + if((tmp = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL) + return MP_MEM; + + s_mp_copy(DIGITS(from), tmp, USED(from)); + + if(DIGITS(to) != NULL) { +#if MP_CRYPTO + s_mp_setz(DIGITS(to), ALLOC(to)); +#endif + s_mp_free(DIGITS(to)); + } + + DIGITS(to) = tmp; + ALLOC(to) = USED(from); + } + + /* Copy the precision and sign from the original */ + USED(to) = USED(from); + SIGN(to) = SIGN(from); + } /* end copy */ + + return MP_OKAY; + +} /* end mp_copy() */ + +/* }}} */ + +/* {{{ mp_exch(mp1, mp2) */ + +/* + mp_exch(mp1, mp2) + + Exchange mp1 and mp2 without allocating any intermediate memory + (well, unless you count the stack space needed for this call and the + locals it creates...). This cannot fail. + */ + +void mp_exch(mp_int *mp1, mp_int *mp2) +{ +#if MP_ARGCHK == 2 + assert(mp1 != NULL && mp2 != NULL); +#else + if(mp1 == NULL || mp2 == NULL) + return; +#endif + + s_mp_exch(mp1, mp2); + +} /* end mp_exch() */ + +/* }}} */ + +/* {{{ mp_clear(mp) */ + +/* + mp_clear(mp) + + Release the storage used by an mp_int, and void its fields so that + if someone calls mp_clear() again for the same int later, we won't + get tollchocked. + */ + +void mp_clear(mp_int *mp) +{ + if(mp == NULL) + return; + + if(DIGITS(mp) != NULL) { +#if MP_CRYPTO + s_mp_setz(DIGITS(mp), ALLOC(mp)); +#endif + s_mp_free(DIGITS(mp)); + DIGITS(mp) = NULL; + } + + USED(mp) = 0; + ALLOC(mp) = 0; + +} /* end mp_clear() */ + +/* }}} */ + +/* {{{ mp_clear_array(mp[], count) */ + +void mp_clear_array(mp_int mp[], int count) +{ + ARGCHK(mp != NULL && count > 0, MP_BADARG); + + while(--count >= 0) + mp_clear(&mp[count]); + +} /* end mp_clear_array() */ + +/* }}} */ + +/* {{{ mp_zero(mp) */ + +/* + mp_zero(mp) + + Set mp to zero. Does not change the allocated size of the structure, + and therefore cannot fail (except on a bad argument, which we ignore) + */ +void mp_zero(mp_int *mp) +{ + if(mp == NULL) + return; + + s_mp_setz(DIGITS(mp), ALLOC(mp)); + USED(mp) = 1; + SIGN(mp) = MP_ZPOS; + +} /* end mp_zero() */ + +/* }}} */ + +/* {{{ mp_set(mp, d) */ + +void mp_set(mp_int *mp, mp_digit d) +{ + if(mp == NULL) + return; + + mp_zero(mp); + DIGIT(mp, 0) = d; + +} /* end mp_set() */ + +/* }}} */ + +/* {{{ mp_set_int(mp, z) */ + +mp_err mp_set_int(mp_int *mp, long z) +{ + int ix; + unsigned long v = abs(z); + mp_err res; + + ARGCHK(mp != NULL, MP_BADARG); + + mp_zero(mp); + if(z == 0) + return MP_OKAY; /* shortcut for zero */ + + for(ix = sizeof(long) - 1; ix >= 0; ix--) { + + if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY) + return res; + + res = s_mp_add_d(mp, + (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX)); + if(res != MP_OKAY) + return res; + + } + + if(z < 0) + SIGN(mp) = MP_NEG; + + return MP_OKAY; + +} /* end mp_set_int() */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ Digit arithmetic */ + +/* {{{ mp_add_d(a, d, b) */ + +/* + mp_add_d(a, d, b) + + Compute the sum b = a + d, for a single digit d. Respects the sign of + its primary addend (single digits are unsigned anyway). + */ + +mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b) +{ + mp_err res = MP_OKAY; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if((res = mp_copy(a, b)) != MP_OKAY) + return res; + + if(SIGN(b) == MP_ZPOS) { + res = s_mp_add_d(b, d); + } else if(s_mp_cmp_d(b, d) >= 0) { + res = s_mp_sub_d(b, d); + } else { + SIGN(b) = MP_ZPOS; + + DIGIT(b, 0) = d - DIGIT(b, 0); + } + + return res; + +} /* end mp_add_d() */ + +/* }}} */ + +/* {{{ mp_sub_d(a, d, b) */ + +/* + mp_sub_d(a, d, b) + + Compute the difference b = a - d, for a single digit d. Respects the + sign of its subtrahend (single digits are unsigned anyway). + */ + +mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b) +{ + mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if((res = mp_copy(a, b)) != MP_OKAY) + return res; + + if(SIGN(b) == MP_NEG) { + if((res = s_mp_add_d(b, d)) != MP_OKAY) + return res; + + } else if(s_mp_cmp_d(b, d) >= 0) { + if((res = s_mp_sub_d(b, d)) != MP_OKAY) + return res; + + } else { + mp_neg(b, b); + + DIGIT(b, 0) = d - DIGIT(b, 0); + SIGN(b) = MP_NEG; + } + + if(s_mp_cmp_d(b, 0) == 0) + SIGN(b) = MP_ZPOS; + + return MP_OKAY; + +} /* end mp_sub_d() */ + +/* }}} */ + +/* {{{ mp_mul_d(a, d, b) */ + +/* + mp_mul_d(a, d, b) + + Compute the product b = a * d, for a single digit d. Respects the sign + of its multiplicand (single digits are unsigned anyway) + */ + +mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b) +{ + mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if(d == 0) { + mp_zero(b); + return MP_OKAY; + } + + if((res = mp_copy(a, b)) != MP_OKAY) + return res; + + res = s_mp_mul_d(b, d); + + return res; + +} /* end mp_mul_d() */ + +/* }}} */ + +/* {{{ mp_mul_2(a, c) */ + +mp_err mp_mul_2(mp_int *a, mp_int *c) +{ + mp_err res; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if((res = mp_copy(a, c)) != MP_OKAY) + return res; + + return s_mp_mul_2(c); + +} /* end mp_mul_2() */ + +/* }}} */ + +/* {{{ mp_div_d(a, d, q, r) */ + +/* + mp_div_d(a, d, q, r) + + Compute the quotient q = a / d and remainder r = a mod d, for a + single digit d. Respects the sign of its divisor (single digits are + unsigned anyway). + */ + +mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r) +{ + mp_err res; + mp_digit rem; + int pow; + + ARGCHK(a != NULL, MP_BADARG); + + if(d == 0) + return MP_RANGE; + + /* Shortcut for powers of two ... */ + if((pow = s_mp_ispow2d(d)) >= 0) { + mp_digit mask; + + mask = (1 << pow) - 1; + rem = DIGIT(a, 0) & mask; + + if(q) { + mp_copy(a, q); + s_mp_div_2d(q, pow); + } + + if(r) + *r = rem; + + return MP_OKAY; + } + + /* + If the quotient is actually going to be returned, we'll try to + avoid hitting the memory allocator by copying the dividend into it + and doing the division there. This can't be any _worse_ than + always copying, and will sometimes be better (since it won't make + another copy) + + If it's not going to be returned, we need to allocate a temporary + to hold the quotient, which will just be discarded. + */ + if(q) { + if((res = mp_copy(a, q)) != MP_OKAY) + return res; + + res = s_mp_div_d(q, d, &rem); + if(s_mp_cmp_d(q, 0) == MP_EQ) + SIGN(q) = MP_ZPOS; + + } else { + mp_int qp; + + if((res = mp_init_copy(&qp, a)) != MP_OKAY) + return res; + + res = s_mp_div_d(&qp, d, &rem); + if(s_mp_cmp_d(&qp, 0) == 0) + SIGN(&qp) = MP_ZPOS; + + mp_clear(&qp); + } + + if(r) + *r = rem; + + return res; + +} /* end mp_div_d() */ + +/* }}} */ + +/* {{{ mp_div_2(a, c) */ + +/* + mp_div_2(a, c) + + Compute c = a / 2, disregarding the remainder. + */ + +mp_err mp_div_2(mp_int *a, mp_int *c) +{ + mp_err res; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if((res = mp_copy(a, c)) != MP_OKAY) + return res; + + s_mp_div_2(c); + + return MP_OKAY; + +} /* end mp_div_2() */ + +/* }}} */ + +/* {{{ mp_expt_d(a, d, b) */ + +mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c) +{ + mp_int s, x; + mp_err res; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if((res = mp_init(&s)) != MP_OKAY) + return res; + if((res = mp_init_copy(&x, a)) != MP_OKAY) + goto X; + + DIGIT(&s, 0) = 1; + + while(d != 0) { + if(d & 1) { + if((res = s_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; + } + + d >>= 1; + + if((res = s_mp_sqr(&x)) != MP_OKAY) + goto CLEANUP; + } + + s_mp_exch(&s, c); + +CLEANUP: + mp_clear(&x); +X: + mp_clear(&s); + + return res; + +} /* end mp_expt_d() */ + +/* }}} */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ Full arithmetic */ + +/* {{{ mp_abs(a, b) */ + +/* + mp_abs(a, b) + + Compute b = |a|. 'a' and 'b' may be identical. + */ + +mp_err mp_abs(mp_int *a, mp_int *b) +{ + mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if((res = mp_copy(a, b)) != MP_OKAY) + return res; + + SIGN(b) = MP_ZPOS; + + return MP_OKAY; + +} /* end mp_abs() */ + +/* }}} */ + +/* {{{ mp_neg(a, b) */ + +/* + mp_neg(a, b) + + Compute b = -a. 'a' and 'b' may be identical. + */ + +mp_err mp_neg(mp_int *a, mp_int *b) +{ + mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if((res = mp_copy(a, b)) != MP_OKAY) + return res; + + if(s_mp_cmp_d(b, 0) == MP_EQ) + SIGN(b) = MP_ZPOS; + else + SIGN(b) = (SIGN(b) == MP_NEG) ? MP_ZPOS : MP_NEG; + + return MP_OKAY; + +} /* end mp_neg() */ + +/* }}} */ + +/* {{{ mp_add(a, b, c) */ + +/* + mp_add(a, b, c) + + Compute c = a + b. All parameters may be identical. + */ + +mp_err mp_add(mp_int *a, mp_int *b, mp_int *c) +{ + mp_err res; + int cmp; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + if(SIGN(a) == SIGN(b)) { /* same sign: add values, keep sign */ + + /* Commutativity of addition lets us do this in either order, + so we avoid having to use a temporary even if the result + is supposed to replace the output + */ + if(c == b) { + if((res = s_mp_add(c, a)) != MP_OKAY) + return res; + } else { + if(c != a && (res = mp_copy(a, c)) != MP_OKAY) + return res; + + if((res = s_mp_add(c, b)) != MP_OKAY) + return res; + } + + } else if((cmp = s_mp_cmp(a, b)) > 0) { /* different sign: a > b */ + + /* If the output is going to be clobbered, we will use a temporary + variable; otherwise, we'll do it without touching the memory + allocator at all, if possible + */ + if(c == b) { + mp_int tmp; + + if((res = mp_init_copy(&tmp, a)) != MP_OKAY) + return res; + if((res = s_mp_sub(&tmp, b)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + s_mp_exch(&tmp, c); + mp_clear(&tmp); + + } else { + + if(c != a && (res = mp_copy(a, c)) != MP_OKAY) + return res; + if((res = s_mp_sub(c, b)) != MP_OKAY) + return res; + + } + + } else if(cmp == 0) { /* different sign, a == b */ + + mp_zero(c); + return MP_OKAY; + + } else { /* different sign: a < b */ + + /* See above... */ + if(c == a) { + mp_int tmp; + + if((res = mp_init_copy(&tmp, b)) != MP_OKAY) + return res; + if((res = s_mp_sub(&tmp, a)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + s_mp_exch(&tmp, c); + mp_clear(&tmp); + + } else { + + if(c != b && (res = mp_copy(b, c)) != MP_OKAY) + return res; + if((res = s_mp_sub(c, a)) != MP_OKAY) + return res; + + } + } + + if(USED(c) == 1 && DIGIT(c, 0) == 0) + SIGN(c) = MP_ZPOS; + + return MP_OKAY; + +} /* end mp_add() */ + +/* }}} */ + +/* {{{ mp_sub(a, b, c) */ + +/* + mp_sub(a, b, c) + + Compute c = a - b. All parameters may be identical. + */ + +mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c) +{ + mp_err res; + int cmp; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + if(SIGN(a) != SIGN(b)) { + if(c == a) { + if((res = s_mp_add(c, b)) != MP_OKAY) + return res; + } else { + if(c != b && ((res = mp_copy(b, c)) != MP_OKAY)) + return res; + if((res = s_mp_add(c, a)) != MP_OKAY) + return res; + SIGN(c) = SIGN(a); + } + + } else if((cmp = s_mp_cmp(a, b)) > 0) { /* Same sign, a > b */ + if(c == b) { + mp_int tmp; + + if((res = mp_init_copy(&tmp, a)) != MP_OKAY) + return res; + if((res = s_mp_sub(&tmp, b)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + s_mp_exch(&tmp, c); + mp_clear(&tmp); + + } else { + if(c != a && ((res = mp_copy(a, c)) != MP_OKAY)) + return res; + + if((res = s_mp_sub(c, b)) != MP_OKAY) + return res; + } + + } else if(cmp == 0) { /* Same sign, equal magnitude */ + mp_zero(c); + return MP_OKAY; + + } else { /* Same sign, b > a */ + if(c == a) { + mp_int tmp; + + if((res = mp_init_copy(&tmp, b)) != MP_OKAY) + return res; + + if((res = s_mp_sub(&tmp, a)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + s_mp_exch(&tmp, c); + mp_clear(&tmp); + + } else { + if(c != b && ((res = mp_copy(b, c)) != MP_OKAY)) + return res; + + if((res = s_mp_sub(c, a)) != MP_OKAY) + return res; + } + + SIGN(c) = !SIGN(b); + } + + if(USED(c) == 1 && DIGIT(c, 0) == 0) + SIGN(c) = MP_ZPOS; + + return MP_OKAY; + +} /* end mp_sub() */ + +/* }}} */ + +/* {{{ mp_mul(a, b, c) */ + +/* + mp_mul(a, b, c) + + Compute c = a * b. All parameters may be identical. + */ + +mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c) +{ + mp_err res; + mp_sign sgn; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + sgn = (SIGN(a) == SIGN(b)) ? MP_ZPOS : MP_NEG; + + if(c == b) { + if((res = s_mp_mul(c, a)) != MP_OKAY) + return res; + + } else { + if((res = mp_copy(a, c)) != MP_OKAY) + return res; + + if((res = s_mp_mul(c, b)) != MP_OKAY) + return res; + } + + if(sgn == MP_ZPOS || s_mp_cmp_d(c, 0) == MP_EQ) + SIGN(c) = MP_ZPOS; + else + SIGN(c) = sgn; + + return MP_OKAY; + +} /* end mp_mul() */ + +/* }}} */ + +/* {{{ mp_mul_2d(a, d, c) */ + +/* + mp_mul_2d(a, d, c) + + Compute c = a * 2^d. a may be the same as c. + */ + +mp_err mp_mul_2d(mp_int *a, mp_digit d, mp_int *c) +{ + mp_err res; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if((res = mp_copy(a, c)) != MP_OKAY) + return res; + + if(d == 0) + return MP_OKAY; + + return s_mp_mul_2d(c, d); + +} /* end mp_mul() */ + +/* }}} */ + +/* {{{ mp_sqr(a, b) */ + +#if MP_SQUARE +mp_err mp_sqr(mp_int *a, mp_int *b) +{ + mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if((res = mp_copy(a, b)) != MP_OKAY) + return res; + + if((res = s_mp_sqr(b)) != MP_OKAY) + return res; + + SIGN(b) = MP_ZPOS; + + return MP_OKAY; + +} /* end mp_sqr() */ +#endif + +/* }}} */ + +/* {{{ mp_div(a, b, q, r) */ + +/* + mp_div(a, b, q, r) + + Compute q = a / b and r = a mod b. Input parameters may be re-used + as output parameters. If q or r is NULL, that portion of the + computation will be discarded (although it will still be computed) + + Pay no attention to the hacker behind the curtain. + */ + +mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r) +{ + mp_err res; + mp_int qtmp, rtmp; + int cmp; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + if(mp_cmp_z(b) == MP_EQ) + return MP_RANGE; + + /* If a <= b, we can compute the solution without division, and + avoid any memory allocation + */ + if((cmp = s_mp_cmp(a, b)) < 0) { + if(r) { + if((res = mp_copy(a, r)) != MP_OKAY) + return res; + } + + if(q) + mp_zero(q); + + return MP_OKAY; + + } else if(cmp == 0) { + + /* Set quotient to 1, with appropriate sign */ + if(q) { + int qneg = (SIGN(a) != SIGN(b)); + + mp_set(q, 1); + if(qneg) + SIGN(q) = MP_NEG; + } + + if(r) + mp_zero(r); + + return MP_OKAY; + } + + /* If we get here, it means we actually have to do some division */ + + /* Set up some temporaries... */ + if((res = mp_init_copy(&qtmp, a)) != MP_OKAY) + return res; + if((res = mp_init_copy(&rtmp, b)) != MP_OKAY) + goto CLEANUP; + + if((res = s_mp_div(&qtmp, &rtmp)) != MP_OKAY) + goto CLEANUP; + + /* Compute the signs for the output */ + SIGN(&rtmp) = SIGN(a); /* Sr = Sa */ + if(SIGN(a) == SIGN(b)) + SIGN(&qtmp) = MP_ZPOS; /* Sq = MP_ZPOS if Sa = Sb */ + else + SIGN(&qtmp) = MP_NEG; /* Sq = MP_NEG if Sa != Sb */ + + if(s_mp_cmp_d(&qtmp, 0) == MP_EQ) + SIGN(&qtmp) = MP_ZPOS; + if(s_mp_cmp_d(&rtmp, 0) == MP_EQ) + SIGN(&rtmp) = MP_ZPOS; + + /* Copy output, if it is needed */ + if(q) + s_mp_exch(&qtmp, q); + + if(r) + s_mp_exch(&rtmp, r); + +CLEANUP: + mp_clear(&rtmp); + mp_clear(&qtmp); + + return res; + +} /* end mp_div() */ + +/* }}} */ + +/* {{{ mp_div_2d(a, d, q, r) */ + +mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r) +{ + mp_err res; + + ARGCHK(a != NULL, MP_BADARG); + + if(q) { + if((res = mp_copy(a, q)) != MP_OKAY) + return res; + + s_mp_div_2d(q, d); + } + + if(r) { + if((res = mp_copy(a, r)) != MP_OKAY) + return res; + + s_mp_mod_2d(r, d); + } + + return MP_OKAY; + +} /* end mp_div_2d() */ + +/* }}} */ + +/* {{{ mp_expt(a, b, c) */ + +/* + mp_expt(a, b, c) + + Compute c = a ** b, that is, raise a to the b power. Uses a + standard iterative square-and-multiply technique. + */ + +mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c) +{ + mp_int s, x; + mp_err res; + mp_digit d; + int dig, bit; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + if(mp_cmp_z(b) < 0) + return MP_RANGE; + + if((res = mp_init(&s)) != MP_OKAY) + return res; + + mp_set(&s, 1); + + if((res = mp_init_copy(&x, a)) != MP_OKAY) + goto X; + + /* Loop over low-order digits in ascending order */ + for(dig = 0; dig < (USED(b) - 1); dig++) { + d = DIGIT(b, dig); + + /* Loop over bits of each non-maximal digit */ + for(bit = 0; bit < DIGIT_BIT; bit++) { + if(d & 1) { + if((res = s_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; + } + + d >>= 1; + + if((res = s_mp_sqr(&x)) != MP_OKAY) + goto CLEANUP; + } + } + + /* Consider now the last digit... */ + d = DIGIT(b, dig); + + while(d) { + if(d & 1) { + if((res = s_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; + } + + d >>= 1; + + if((res = s_mp_sqr(&x)) != MP_OKAY) + goto CLEANUP; + } + + if(mp_iseven(b)) + SIGN(&s) = SIGN(a); + + res = mp_copy(&s, c); + +CLEANUP: + mp_clear(&x); +X: + mp_clear(&s); + + return res; + +} /* end mp_expt() */ + +/* }}} */ + +/* {{{ mp_2expt(a, k) */ + +/* Compute a = 2^k */ + +mp_err mp_2expt(mp_int *a, mp_digit k) +{ + ARGCHK(a != NULL, MP_BADARG); + + return s_mp_2expt(a, k); + +} /* end mp_2expt() */ + +/* }}} */ + +/* {{{ mp_mod(a, m, c) */ + +/* + mp_mod(a, m, c) + + Compute c = a (mod m). Result will always be 0 <= c < m. + */ + +mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c) +{ + mp_err res; + int mag; + + ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG); + + if(SIGN(m) == MP_NEG) + return MP_RANGE; + + /* + If |a| > m, we need to divide to get the remainder and take the + absolute value. + + If |a| < m, we don't need to do any division, just copy and adjust + the sign (if a is negative). + + If |a| == m, we can simply set the result to zero. + + This order is intended to minimize the average path length of the + comparison chain on common workloads -- the most frequent cases are + that |a| != m, so we do those first. + */ + if((mag = s_mp_cmp(a, m)) > 0) { + if((res = mp_div(a, m, NULL, c)) != MP_OKAY) + return res; + + if(SIGN(c) == MP_NEG) { + if((res = mp_add(c, m, c)) != MP_OKAY) + return res; + } + + } else if(mag < 0) { + if((res = mp_copy(a, c)) != MP_OKAY) + return res; + + if(mp_cmp_z(a) < 0) { + if((res = mp_add(c, m, c)) != MP_OKAY) + return res; + + } + + } else { + mp_zero(c); + + } + + return MP_OKAY; + +} /* end mp_mod() */ + +/* }}} */ + +/* {{{ mp_mod_d(a, d, c) */ + +/* + mp_mod_d(a, d, c) + + Compute c = a (mod d). Result will always be 0 <= c < d + */ +mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c) +{ + mp_err res; + mp_digit rem; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if(s_mp_cmp_d(a, d) > 0) { + if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY) + return res; + + } else { + if(SIGN(a) == MP_NEG) + rem = d - DIGIT(a, 0); + else + rem = DIGIT(a, 0); + } + + if(c) + *c = rem; + + return MP_OKAY; + +} /* end mp_mod_d() */ + +/* }}} */ + +/* {{{ mp_sqrt(a, b) */ + +/* + mp_sqrt(a, b) + + Compute the integer square root of a, and store the result in b. + Uses an integer-arithmetic version of Newton's iterative linear + approximation technique to determine this value; the result has the + following two properties: + + b^2 <= a + (b+1)^2 >= a + + It is a range error to pass a negative value. + */ +mp_err mp_sqrt(mp_int *a, mp_int *b) +{ + mp_int x, t; + mp_err res; + + ARGCHK(a != NULL && b != NULL, MP_BADARG); + + /* Cannot take square root of a negative value */ + if(SIGN(a) == MP_NEG) + return MP_RANGE; + + /* Special cases for zero and one, trivial */ + if(mp_cmp_d(a, 0) == MP_EQ || mp_cmp_d(a, 1) == MP_EQ) + return mp_copy(a, b); + + /* Initialize the temporaries we'll use below */ + if((res = mp_init_size(&t, USED(a))) != MP_OKAY) + return res; + + /* Compute an initial guess for the iteration as a itself */ + if((res = mp_init_copy(&x, a)) != MP_OKAY) + goto X; + +s_mp_rshd(&x, (USED(&x)/2)+1); +mp_add_d(&x, 1, &x); + + for(;;) { + /* t = (x * x) - a */ + mp_copy(&x, &t); /* can't fail, t is big enough for original x */ + if((res = mp_sqr(&t, &t)) != MP_OKAY || + (res = mp_sub(&t, a, &t)) != MP_OKAY) + goto CLEANUP; + + /* t = t / 2x */ + s_mp_mul_2(&x); + if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY) + goto CLEANUP; + s_mp_div_2(&x); + + /* Terminate the loop, if the quotient is zero */ + if(mp_cmp_z(&t) == MP_EQ) + break; + + /* x = x - t */ + if((res = mp_sub(&x, &t, &x)) != MP_OKAY) + goto CLEANUP; + + } + + /* Copy result to output parameter */ + mp_sub_d(&x, 1, &x); + s_mp_exch(&x, b); + + CLEANUP: + mp_clear(&x); + X: + mp_clear(&t); + + return res; + +} /* end mp_sqrt() */ + +/* }}} */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ Modular arithmetic */ + +#if MP_MODARITH +/* {{{ mp_addmod(a, b, m, c) */ + +/* + mp_addmod(a, b, m, c) + + Compute c = (a + b) mod m + */ + +mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c) +{ + mp_err res; + + ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG); + + if((res = mp_add(a, b, c)) != MP_OKAY) + return res; + if((res = mp_mod(c, m, c)) != MP_OKAY) + return res; + + return MP_OKAY; + +} + +/* }}} */ + +/* {{{ mp_submod(a, b, m, c) */ + +/* + mp_submod(a, b, m, c) + + Compute c = (a - b) mod m + */ + +mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c) +{ + mp_err res; + + ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG); + + if((res = mp_sub(a, b, c)) != MP_OKAY) + return res; + if((res = mp_mod(c, m, c)) != MP_OKAY) + return res; + + return MP_OKAY; + +} + +/* }}} */ + +/* {{{ mp_mulmod(a, b, m, c) */ + +/* + mp_mulmod(a, b, m, c) + + Compute c = (a * b) mod m + */ + +mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c) +{ + mp_err res; + + ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG); + + if((res = mp_mul(a, b, c)) != MP_OKAY) + return res; + if((res = mp_mod(c, m, c)) != MP_OKAY) + return res; + + return MP_OKAY; + +} + +/* }}} */ + +/* {{{ mp_sqrmod(a, m, c) */ + +#if MP_SQUARE +mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c) +{ + mp_err res; + + ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG); + + if((res = mp_sqr(a, c)) != MP_OKAY) + return res; + if((res = mp_mod(c, m, c)) != MP_OKAY) + return res; + + return MP_OKAY; + +} /* end mp_sqrmod() */ +#endif + +/* }}} */ + +/* {{{ mp_exptmod(a, b, m, c) */ + +/* + mp_exptmod(a, b, m, c) + + Compute c = (a ** b) mod m. Uses a standard square-and-multiply + method with modular reductions at each step. (This is basically the + same code as mp_expt(), except for the addition of the reductions) + + The modular reductions are done using Barrett's algorithm (see + s_mp_reduce() below for details) + */ + +mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c) +{ + mp_int s, x, mu; + mp_err res; + mp_digit d, *db = DIGITS(b); + mp_size ub = USED(b); + int dig, bit; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0) + return MP_RANGE; + + if((res = mp_init(&s)) != MP_OKAY) + return res; + if((res = mp_init_copy(&x, a)) != MP_OKAY) + goto X; + if((res = mp_mod(&x, m, &x)) != MP_OKAY || + (res = mp_init(&mu)) != MP_OKAY) + goto MU; + + mp_set(&s, 1); + + /* mu = b^2k / m */ + s_mp_add_d(&mu, 1); + s_mp_lshd(&mu, 2 * USED(m)); + if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY) + goto CLEANUP; + + /* Loop over digits of b in ascending order, except highest order */ + for(dig = 0; dig < (ub - 1); dig++) { + d = *db++; + + /* Loop over the bits of the lower-order digits */ + for(bit = 0; bit < DIGIT_BIT; bit++) { + if(d & 1) { + if((res = s_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; + if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY) + goto CLEANUP; + } + + d >>= 1; + + if((res = s_mp_sqr(&x)) != MP_OKAY) + goto CLEANUP; + if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY) + goto CLEANUP; + } + } + + /* Now do the last digit... */ + d = *db; + + while(d) { + if(d & 1) { + if((res = s_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; + if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY) + goto CLEANUP; + } + + d >>= 1; + + if((res = s_mp_sqr(&x)) != MP_OKAY) + goto CLEANUP; + if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY) + goto CLEANUP; + } + + s_mp_exch(&s, c); + + CLEANUP: + mp_clear(&mu); + MU: + mp_clear(&x); + X: + mp_clear(&s); + + return res; + +} /* end mp_exptmod() */ + +/* }}} */ + +/* {{{ mp_exptmod_d(a, d, m, c) */ + +mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c) +{ + mp_int s, x; + mp_err res; + + ARGCHK(a != NULL && c != NULL, MP_BADARG); + + if((res = mp_init(&s)) != MP_OKAY) + return res; + if((res = mp_init_copy(&x, a)) != MP_OKAY) + goto X; + + mp_set(&s, 1); + + while(d != 0) { + if(d & 1) { + if((res = s_mp_mul(&s, &x)) != MP_OKAY || + (res = mp_mod(&s, m, &s)) != MP_OKAY) + goto CLEANUP; + } + + d /= 2; + + if((res = s_mp_sqr(&x)) != MP_OKAY || + (res = mp_mod(&x, m, &x)) != MP_OKAY) + goto CLEANUP; + } + + s_mp_exch(&s, c); + +CLEANUP: + mp_clear(&x); +X: + mp_clear(&s); + + return res; + +} /* end mp_exptmod_d() */ + +/* }}} */ +#endif /* if MP_MODARITH */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ Comparison functions */ + +/* {{{ mp_cmp_z(a) */ + +/* + mp_cmp_z(a) + + Compare a <=> 0. Returns <0 if a<0, 0 if a=0, >0 if a>0. + */ + +int mp_cmp_z(mp_int *a) +{ + if(SIGN(a) == MP_NEG) + return MP_LT; + else if(USED(a) == 1 && DIGIT(a, 0) == 0) + return MP_EQ; + else + return MP_GT; + +} /* end mp_cmp_z() */ + +/* }}} */ + +/* {{{ mp_cmp_d(a, d) */ + +/* + mp_cmp_d(a, d) + + Compare a <=> d. Returns <0 if a0 if a>d + */ + +int mp_cmp_d(mp_int *a, mp_digit d) +{ + ARGCHK(a != NULL, MP_EQ); + + if(SIGN(a) == MP_NEG) + return MP_LT; + + return s_mp_cmp_d(a, d); + +} /* end mp_cmp_d() */ + +/* }}} */ + +/* {{{ mp_cmp(a, b) */ + +int mp_cmp(mp_int *a, mp_int *b) +{ + ARGCHK(a != NULL && b != NULL, MP_EQ); + + if(SIGN(a) == SIGN(b)) { + int mag; + + if((mag = s_mp_cmp(a, b)) == MP_EQ) + return MP_EQ; + + if(SIGN(a) == MP_ZPOS) + return mag; + else + return -mag; + + } else if(SIGN(a) == MP_ZPOS) { + return MP_GT; + } else { + return MP_LT; + } + +} /* end mp_cmp() */ + +/* }}} */ + +/* {{{ mp_cmp_mag(a, b) */ + +/* + mp_cmp_mag(a, b) + + Compares |a| <=> |b|, and returns an appropriate comparison result + */ + +int mp_cmp_mag(mp_int *a, mp_int *b) +{ + ARGCHK(a != NULL && b != NULL, MP_EQ); + + return s_mp_cmp(a, b); + +} /* end mp_cmp_mag() */ + +/* }}} */ + +/* {{{ mp_cmp_int(a, z) */ + +/* + This just converts z to an mp_int, and uses the existing comparison + routines. This is sort of inefficient, but it's not clear to me how + frequently this wil get used anyway. For small positive constants, + you can always use mp_cmp_d(), and for zero, there is mp_cmp_z(). + */ +int mp_cmp_int(mp_int *a, long z) +{ + mp_int tmp; + int out; + + ARGCHK(a != NULL, MP_EQ); + + mp_init(&tmp); mp_set_int(&tmp, z); + out = mp_cmp(a, &tmp); + mp_clear(&tmp); + + return out; + +} /* end mp_cmp_int() */ + +/* }}} */ + +/* {{{ mp_isodd(a) */ + +/* + mp_isodd(a) + + Returns a true (non-zero) value if a is odd, false (zero) otherwise. + */ +int mp_isodd(mp_int *a) +{ + ARGCHK(a != NULL, 0); + + return (DIGIT(a, 0) & 1); + +} /* end mp_isodd() */ + +/* }}} */ + +/* {{{ mp_iseven(a) */ + +int mp_iseven(mp_int *a) +{ + return !mp_isodd(a); + +} /* end mp_iseven() */ + +/* }}} */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ Number theoretic functions */ + +#if MP_NUMTH +/* {{{ mp_gcd(a, b, c) */ + +/* + Like the old mp_gcd() function, except computes the GCD using the + binary algorithm due to Josef Stein in 1961 (via Knuth). + */ +mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c) +{ + mp_err res; + mp_int u, v, t; + mp_size k = 0; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ) + return MP_RANGE; + if(mp_cmp_z(a) == MP_EQ) { + return mp_copy(b, c); + } else if(mp_cmp_z(b) == MP_EQ) { + return mp_copy(a, c); + } + + if((res = mp_init(&t)) != MP_OKAY) + return res; + if((res = mp_init_copy(&u, a)) != MP_OKAY) + goto U; + if((res = mp_init_copy(&v, b)) != MP_OKAY) + goto V; + + SIGN(&u) = MP_ZPOS; + SIGN(&v) = MP_ZPOS; + + /* Divide out common factors of 2 until at least 1 of a, b is even */ + while(mp_iseven(&u) && mp_iseven(&v)) { + s_mp_div_2(&u); + s_mp_div_2(&v); + ++k; + } + + /* Initialize t */ + if(mp_isodd(&u)) { + if((res = mp_copy(&v, &t)) != MP_OKAY) + goto CLEANUP; + + /* t = -v */ + if(SIGN(&v) == MP_ZPOS) + SIGN(&t) = MP_NEG; + else + SIGN(&t) = MP_ZPOS; + + } else { + if((res = mp_copy(&u, &t)) != MP_OKAY) + goto CLEANUP; + + } + + for(;;) { + while(mp_iseven(&t)) { + s_mp_div_2(&t); + } + + if(mp_cmp_z(&t) == MP_GT) { + if((res = mp_copy(&t, &u)) != MP_OKAY) + goto CLEANUP; + + } else { + if((res = mp_copy(&t, &v)) != MP_OKAY) + goto CLEANUP; + + /* v = -t */ + if(SIGN(&t) == MP_ZPOS) + SIGN(&v) = MP_NEG; + else + SIGN(&v) = MP_ZPOS; + } + + if((res = mp_sub(&u, &v, &t)) != MP_OKAY) + goto CLEANUP; + + if(s_mp_cmp_d(&t, 0) == MP_EQ) + break; + } + + s_mp_2expt(&v, k); /* v = 2^k */ + res = mp_mul(&u, &v, c); /* c = u * v */ + + CLEANUP: + mp_clear(&v); + V: + mp_clear(&u); + U: + mp_clear(&t); + + return res; + +} /* end mp_bgcd() */ + +/* }}} */ + +/* {{{ mp_lcm(a, b, c) */ + +/* We compute the least common multiple using the rule: + + ab = [a, b](a, b) + + ... by computing the product, and dividing out the gcd. + */ + +mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c) +{ + mp_int gcd, prod; + mp_err res; + + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); + + /* Set up temporaries */ + if((res = mp_init(&gcd)) != MP_OKAY) + return res; + if((res = mp_init(&prod)) != MP_OKAY) + goto GCD; + + if((res = mp_mul(a, b, &prod)) != MP_OKAY) + goto CLEANUP; + if((res = mp_gcd(a, b, &gcd)) != MP_OKAY) + goto CLEANUP; + + res = mp_div(&prod, &gcd, c, NULL); + + CLEANUP: + mp_clear(&prod); + GCD: + mp_clear(&gcd); + + return res; + +} /* end mp_lcm() */ + +/* }}} */ + +/* {{{ mp_xgcd(a, b, g, x, y) */ + +/* + mp_xgcd(a, b, g, x, y) + + Compute g = (a, b) and values x and y satisfying Bezout's identity + (that is, ax + by = g). This uses the extended binary GCD algorithm + based on the Stein algorithm used for mp_gcd() + */ + +mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y) +{ + mp_int gx, xc, yc, u, v, A, B, C, D; + mp_int *clean[9]; + mp_err res; + int last = -1; + + if(mp_cmp_z(b) == 0) + return MP_RANGE; + + /* Initialize all these variables we need */ + if((res = mp_init(&u)) != MP_OKAY) goto CLEANUP; + clean[++last] = &u; + if((res = mp_init(&v)) != MP_OKAY) goto CLEANUP; + clean[++last] = &v; + if((res = mp_init(&gx)) != MP_OKAY) goto CLEANUP; + clean[++last] = &gx; + if((res = mp_init(&A)) != MP_OKAY) goto CLEANUP; + clean[++last] = &A; + if((res = mp_init(&B)) != MP_OKAY) goto CLEANUP; + clean[++last] = &B; + if((res = mp_init(&C)) != MP_OKAY) goto CLEANUP; + clean[++last] = &C; + if((res = mp_init(&D)) != MP_OKAY) goto CLEANUP; + clean[++last] = &D; + if((res = mp_init_copy(&xc, a)) != MP_OKAY) goto CLEANUP; + clean[++last] = &xc; + mp_abs(&xc, &xc); + if((res = mp_init_copy(&yc, b)) != MP_OKAY) goto CLEANUP; + clean[++last] = &yc; + mp_abs(&yc, &yc); + + mp_set(&gx, 1); + + /* Divide by two until at least one of them is even */ + while(mp_iseven(&xc) && mp_iseven(&yc)) { + s_mp_div_2(&xc); + s_mp_div_2(&yc); + if((res = s_mp_mul_2(&gx)) != MP_OKAY) + goto CLEANUP; + } + + mp_copy(&xc, &u); + mp_copy(&yc, &v); + mp_set(&A, 1); mp_set(&D, 1); + + /* Loop through binary GCD algorithm */ + for(;;) { + while(mp_iseven(&u)) { + s_mp_div_2(&u); + + if(mp_iseven(&A) && mp_iseven(&B)) { + s_mp_div_2(&A); s_mp_div_2(&B); + } else { + if((res = mp_add(&A, &yc, &A)) != MP_OKAY) goto CLEANUP; + s_mp_div_2(&A); + if((res = mp_sub(&B, &xc, &B)) != MP_OKAY) goto CLEANUP; + s_mp_div_2(&B); + } + } + + while(mp_iseven(&v)) { + s_mp_div_2(&v); + + if(mp_iseven(&C) && mp_iseven(&D)) { + s_mp_div_2(&C); s_mp_div_2(&D); + } else { + if((res = mp_add(&C, &yc, &C)) != MP_OKAY) goto CLEANUP; + s_mp_div_2(&C); + if((res = mp_sub(&D, &xc, &D)) != MP_OKAY) goto CLEANUP; + s_mp_div_2(&D); + } + } + + if(mp_cmp(&u, &v) >= 0) { + if((res = mp_sub(&u, &v, &u)) != MP_OKAY) goto CLEANUP; + if((res = mp_sub(&A, &C, &A)) != MP_OKAY) goto CLEANUP; + if((res = mp_sub(&B, &D, &B)) != MP_OKAY) goto CLEANUP; + + } else { + if((res = mp_sub(&v, &u, &v)) != MP_OKAY) goto CLEANUP; + if((res = mp_sub(&C, &A, &C)) != MP_OKAY) goto CLEANUP; + if((res = mp_sub(&D, &B, &D)) != MP_OKAY) goto CLEANUP; + + } + + /* If we're done, copy results to output */ + if(mp_cmp_z(&u) == 0) { + if(x) + if((res = mp_copy(&C, x)) != MP_OKAY) goto CLEANUP; + + if(y) + if((res = mp_copy(&D, y)) != MP_OKAY) goto CLEANUP; + + if(g) + if((res = mp_mul(&gx, &v, g)) != MP_OKAY) goto CLEANUP; + + break; + } + } + + CLEANUP: + while(last >= 0) + mp_clear(clean[last--]); + + return res; + +} /* end mp_xgcd() */ + +/* }}} */ + +/* {{{ mp_invmod(a, m, c) */ + +/* + mp_invmod(a, m, c) + + Compute c = a^-1 (mod m), if there is an inverse for a (mod m). + This is equivalent to the question of whether (a, m) = 1. If not, + MP_UNDEF is returned, and there is no inverse. + */ + +mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c) +{ + mp_int g, x; + mp_err res; + + ARGCHK(a && m && c, MP_BADARG); + + if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0) + return MP_RANGE; + + if((res = mp_init(&g)) != MP_OKAY) + return res; + if((res = mp_init(&x)) != MP_OKAY) + goto X; + + if((res = mp_xgcd(a, m, &g, &x, NULL)) != MP_OKAY) + goto CLEANUP; + + if(mp_cmp_d(&g, 1) != MP_EQ) { + res = MP_UNDEF; + goto CLEANUP; + } + + res = mp_mod(&x, m, c); + SIGN(c) = SIGN(a); + +CLEANUP: + mp_clear(&x); +X: + mp_clear(&g); + + return res; + +} /* end mp_invmod() */ + +/* }}} */ +#endif /* if MP_NUMTH */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ mp_print(mp, ofp) */ + +#if MP_IOFUNC +/* + mp_print(mp, ofp) + + Print a textual representation of the given mp_int on the output + stream 'ofp'. Output is generated using the internal radix. + */ + +void mp_print(mp_int *mp, FILE *ofp) +{ + int ix; + + if(mp == NULL || ofp == NULL) + return; + + fputc((SIGN(mp) == MP_NEG) ? '-' : '+', ofp); + + for(ix = USED(mp) - 1; ix >= 0; ix--) { + fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix)); + } + +} /* end mp_print() */ + +#endif /* if MP_IOFUNC */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* {{{ More I/O Functions */ + +/* {{{ mp_read_signed_bin(mp, str, len) */ + +/* + mp_read_signed_bin(mp, str, len) + + Read in a raw value (base 256) into the given mp_int + */ + +mp_err mp_read_signed_bin(mp_int *mp, unsigned char *str, int len) +{ + mp_err res; + + ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG); + + if((res = mp_read_unsigned_bin(mp, str + 1, len - 1)) == MP_OKAY) { + /* Get sign from first byte */ + if(str[0]) + SIGN(mp) = MP_NEG; + else + SIGN(mp) = MP_ZPOS; + } + + return res; + +} /* end mp_read_signed_bin() */ + +/* }}} */ + +/* {{{ mp_signed_bin_size(mp) */ + +int mp_signed_bin_size(mp_int *mp) +{ + ARGCHK(mp != NULL, 0); + + return mp_unsigned_bin_size(mp) + 1; + +} /* end mp_signed_bin_size() */ + +/* }}} */ + +/* {{{ mp_to_signed_bin(mp, str) */ + +mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str) +{ + ARGCHK(mp != NULL && str != NULL, MP_BADARG); + + /* Caller responsible for allocating enough memory (use mp_raw_size(mp)) */ + str[0] = (char)SIGN(mp); + + return mp_to_unsigned_bin(mp, str + 1); + +} /* end mp_to_signed_bin() */ + +/* }}} */ + +/* {{{ mp_read_unsigned_bin(mp, str, len) */ + +/* + mp_read_unsigned_bin(mp, str, len) + + Read in an unsigned value (base 256) into the given mp_int + */ + +mp_err mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len) +{ + int ix; + mp_err res; + + ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG); + + mp_zero(mp); + + for(ix = 0; ix < len; ix++) { + if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY) + return res; + + if((res = mp_add_d(mp, str[ix], mp)) != MP_OKAY) + return res; + } + + return MP_OKAY; + +} /* end mp_read_unsigned_bin() */ + +/* }}} */ + +/* {{{ mp_unsigned_bin_size(mp) */ + +int mp_unsigned_bin_size(mp_int *mp) +{ + mp_digit topdig; + int count; + + ARGCHK(mp != NULL, 0); + + /* Special case for the value zero */ + if(USED(mp) == 1 && DIGIT(mp, 0) == 0) + return 1; + + count = (USED(mp) - 1) * sizeof(mp_digit); + topdig = DIGIT(mp, USED(mp) - 1); + + while(topdig != 0) { + ++count; + topdig >>= CHAR_BIT; + } + + return count; + +} /* end mp_unsigned_bin_size() */ + +/* }}} */ + +/* {{{ mp_to_unsigned_bin(mp, str) */ + +mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str) +{ + mp_digit *dp, *end, d; + unsigned char *spos; + + ARGCHK(mp != NULL && str != NULL, MP_BADARG); + + dp = DIGITS(mp); + end = dp + USED(mp) - 1; + spos = str; + + /* Special case for zero, quick test */ + if(dp == end && *dp == 0) { + *str = '\0'; + return MP_OKAY; + } + + /* Generate digits in reverse order */ + while(dp < end) { + int ix; + + d = *dp; + for(ix = 0; ix < sizeof(mp_digit); ++ix) { + *spos = d & UCHAR_MAX; + d >>= CHAR_BIT; + ++spos; + } + + ++dp; + } + + /* Now handle last digit specially, high order zeroes are not written */ + d = *end; + while(d != 0) { + *spos = d & UCHAR_MAX; + d >>= CHAR_BIT; + ++spos; + } + + /* Reverse everything to get digits in the correct order */ + while(--spos > str) { + unsigned char t = *str; + *str = *spos; + *spos = t; + + ++str; + } + + return MP_OKAY; + +} /* end mp_to_unsigned_bin() */ + +/* }}} */ + +/* {{{ mp_count_bits(mp) */ + +int mp_count_bits(mp_int *mp) +{ + int len; + mp_digit d; + + ARGCHK(mp != NULL, MP_BADARG); + + len = DIGIT_BIT * (USED(mp) - 1); + d = DIGIT(mp, USED(mp) - 1); + + while(d != 0) { + ++len; + d >>= 1; + } + + return len; + +} /* end mp_count_bits() */ + +/* }}} */ + +/* {{{ mp_read_radix(mp, str, radix) */ + +/* + mp_read_radix(mp, str, radix) + + Read an integer from the given string, and set mp to the resulting + value. The input is presumed to be in base 10. Leading non-digit + characters are ignored, and the function reads until a non-digit + character or the end of the string. + */ + +mp_err mp_read_radix(mp_int *mp, unsigned char *str, int radix) +{ + int ix = 0, val = 0; + mp_err res; + mp_sign sig = MP_ZPOS; + + ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX, + MP_BADARG); + + mp_zero(mp); + + /* Skip leading non-digit characters until a digit or '-' or '+' */ + while(str[ix] && + (s_mp_tovalue(str[ix], radix) < 0) && + str[ix] != '-' && + str[ix] != '+') { + ++ix; + } + + if(str[ix] == '-') { + sig = MP_NEG; + ++ix; + } else if(str[ix] == '+') { + sig = MP_ZPOS; /* this is the default anyway... */ + ++ix; + } + + while((val = s_mp_tovalue(str[ix], radix)) >= 0) { + if((res = s_mp_mul_d(mp, radix)) != MP_OKAY) + return res; + if((res = s_mp_add_d(mp, val)) != MP_OKAY) + return res; + ++ix; + } + + if(s_mp_cmp_d(mp, 0) == MP_EQ) + SIGN(mp) = MP_ZPOS; + else + SIGN(mp) = sig; + + return MP_OKAY; + +} /* end mp_read_radix() */ + +/* }}} */ + +/* {{{ mp_radix_size(mp, radix) */ + +int mp_radix_size(mp_int *mp, int radix) +{ + int len; + ARGCHK(mp != NULL, 0); + + len = s_mp_outlen(mp_count_bits(mp), radix) + 1; /* for NUL terminator */ + + if(mp_cmp_z(mp) < 0) + ++len; /* for sign */ + + return len; + +} /* end mp_radix_size() */ + +/* }}} */ + +/* {{{ mp_value_radix_size(num, qty, radix) */ + +/* num = number of digits + qty = number of bits per digit + radix = target base + + Return the number of digits in the specified radix that would be + needed to express 'num' digits of 'qty' bits each. + */ +int mp_value_radix_size(int num, int qty, int radix) +{ + ARGCHK(num >= 0 && qty > 0 && radix >= 2 && radix <= MAX_RADIX, 0); + + return s_mp_outlen(num * qty, radix); + +} /* end mp_value_radix_size() */ + +/* }}} */ + +/* {{{ mp_toradix(mp, str, radix) */ + +mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix) +{ + int ix, pos = 0; + + ARGCHK(mp != NULL && str != NULL, MP_BADARG); + ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE); + + if(mp_cmp_z(mp) == MP_EQ) { + str[0] = '0'; + str[1] = '\0'; + } else { + mp_err res; + mp_int tmp; + mp_sign sgn; + mp_digit rem, rdx = (mp_digit)radix; + char ch; + + if((res = mp_init_copy(&tmp, mp)) != MP_OKAY) + return res; + + /* Save sign for later, and take absolute value */ + sgn = SIGN(&tmp); SIGN(&tmp) = MP_ZPOS; + + /* Generate output digits in reverse order */ + while(mp_cmp_z(&tmp) != 0) { + if((res = s_mp_div_d(&tmp, rdx, &rem)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + /* Generate digits, use capital letters */ + ch = s_mp_todigit(rem, radix, 0); + + str[pos++] = ch; + } + + /* Add - sign if original value was negative */ + if(sgn == MP_NEG) + str[pos++] = '-'; + + /* Add trailing NUL to end the string */ + str[pos--] = '\0'; + + /* Reverse the digits and sign indicator */ + ix = 0; + while(ix < pos) { + char tmp = str[ix]; + + str[ix] = str[pos]; + str[pos] = tmp; + ++ix; + --pos; + } + + mp_clear(&tmp); + } + + return MP_OKAY; + +} /* end mp_toradix() */ + +/* }}} */ + +/* {{{ mp_char2value(ch, r) */ + +int mp_char2value(char ch, int r) +{ + return s_mp_tovalue(ch, r); + +} /* end mp_tovalue() */ + +/* }}} */ + +/* }}} */ + +/* {{{ mp_strerror(ec) */ + +/* + mp_strerror(ec) + + Return a string describing the meaning of error code 'ec'. The + string returned is allocated in static memory, so the caller should + not attempt to modify or free the memory associated with this + string. + */ +const char *mp_strerror(mp_err ec) +{ + int aec = (ec < 0) ? -ec : ec; + + /* Code values are negative, so the senses of these comparisons + are accurate */ + if(ec < MP_LAST_CODE || ec > MP_OKAY) { + return mp_err_string[0]; /* unknown error code */ + } else { + return mp_err_string[aec + 1]; + } + +} /* end mp_strerror() */ + +/* }}} */ + +/*========================================================================*/ +/*------------------------------------------------------------------------*/ +/* Static function definitions (internal use only) */ + +/* {{{ Memory management */ + +/* {{{ s_mp_grow(mp, min) */ + +/* Make sure there are at least 'min' digits allocated to mp */ +mp_err s_mp_grow(mp_int *mp, mp_size min) +{ + if(min > ALLOC(mp)) { + mp_digit *tmp; + + /* Set min to next nearest default precision block size */ + min = ((min + (s_mp_defprec - 1)) / s_mp_defprec) * s_mp_defprec; + + if((tmp = s_mp_alloc(min, sizeof(mp_digit))) == NULL) + return MP_MEM; + + s_mp_copy(DIGITS(mp), tmp, USED(mp)); + +#if MP_CRYPTO + s_mp_setz(DIGITS(mp), ALLOC(mp)); +#endif + s_mp_free(DIGITS(mp)); + DIGITS(mp) = tmp; + ALLOC(mp) = min; + } + + return MP_OKAY; + +} /* end s_mp_grow() */ + +/* }}} */ + +/* {{{ s_mp_pad(mp, min) */ + +/* Make sure the used size of mp is at least 'min', growing if needed */ +mp_err s_mp_pad(mp_int *mp, mp_size min) +{ + if(min > USED(mp)) { + mp_err res; + + /* Make sure there is room to increase precision */ + if(min > ALLOC(mp) && (res = s_mp_grow(mp, min)) != MP_OKAY) + return res; + + /* Increase precision; should already be 0-filled */ + USED(mp) = min; + } + + return MP_OKAY; + +} /* end s_mp_pad() */ + +/* }}} */ + +/* {{{ s_mp_setz(dp, count) */ + +#if MP_MACRO == 0 +/* Set 'count' digits pointed to by dp to be zeroes */ +void s_mp_setz(mp_digit *dp, mp_size count) +{ +#if MP_MEMSET == 0 + int ix; + + for(ix = 0; ix < count; ix++) + dp[ix] = 0; +#else + memset(dp, 0, count * sizeof(mp_digit)); +#endif + +} /* end s_mp_setz() */ +#endif + +/* }}} */ + +/* {{{ s_mp_copy(sp, dp, count) */ + +#if MP_MACRO == 0 +/* Copy 'count' digits from sp to dp */ +void s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count) +{ +#if MP_MEMCPY == 0 + int ix; + + for(ix = 0; ix < count; ix++) + dp[ix] = sp[ix]; +#else + memcpy(dp, sp, count * sizeof(mp_digit)); +#endif + +} /* end s_mp_copy() */ +#endif + +/* }}} */ + +/* {{{ s_mp_alloc(nb, ni) */ + +#if MP_MACRO == 0 +/* Allocate ni records of nb bytes each, and return a pointer to that */ +void *s_mp_alloc(size_t nb, size_t ni) +{ + return calloc(nb, ni); + +} /* end s_mp_alloc() */ +#endif + +/* }}} */ + +/* {{{ s_mp_free(ptr) */ + +#if MP_MACRO == 0 +/* Free the memory pointed to by ptr */ +void s_mp_free(void *ptr) +{ + if(ptr) + free(ptr); + +} /* end s_mp_free() */ +#endif + +/* }}} */ + +/* {{{ s_mp_clamp(mp) */ + +/* Remove leading zeroes from the given value */ +void s_mp_clamp(mp_int *mp) +{ + mp_size du = USED(mp); + mp_digit *zp = DIGITS(mp) + du - 1; + + while(du > 1 && !*zp--) + --du; + + USED(mp) = du; + +} /* end s_mp_clamp() */ + + +/* }}} */ + +/* {{{ s_mp_exch(a, b) */ + +/* Exchange the data for a and b; (b, a) = (a, b) */ +void s_mp_exch(mp_int *a, mp_int *b) +{ + mp_int tmp; + + tmp = *a; + *a = *b; + *b = tmp; + +} /* end s_mp_exch() */ + +/* }}} */ + +/* }}} */ + +/* {{{ Arithmetic helpers */ + +/* {{{ s_mp_lshd(mp, p) */ + +/* + Shift mp leftward by p digits, growing if needed, and zero-filling + the in-shifted digits at the right end. This is a convenient + alternative to multiplication by powers of the radix + */ + +mp_err s_mp_lshd(mp_int *mp, mp_size p) +{ + mp_err res; + mp_size pos; + mp_digit *dp; + int ix; + + if(p == 0) + return MP_OKAY; + + if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY) + return res; + + pos = USED(mp) - 1; + dp = DIGITS(mp); + + /* Shift all the significant figures over as needed */ + for(ix = pos - p; ix >= 0; ix--) + dp[ix + p] = dp[ix]; + + /* Fill the bottom digits with zeroes */ + for(ix = 0; ix < p; ix++) + dp[ix] = 0; + + return MP_OKAY; + +} /* end s_mp_lshd() */ + +/* }}} */ + +/* {{{ s_mp_rshd(mp, p) */ + +/* + Shift mp rightward by p digits. Maintains the invariant that + digits above the precision are all zero. Digits shifted off the + end are lost. Cannot fail. + */ + +void s_mp_rshd(mp_int *mp, mp_size p) +{ + mp_size ix; + mp_digit *dp; + + if(p == 0) + return; + + /* Shortcut when all digits are to be shifted off */ + if(p >= USED(mp)) { + s_mp_setz(DIGITS(mp), ALLOC(mp)); + USED(mp) = 1; + SIGN(mp) = MP_ZPOS; + return; + } + + /* Shift all the significant figures over as needed */ + dp = DIGITS(mp); + for(ix = p; ix < USED(mp); ix++) + dp[ix - p] = dp[ix]; + + /* Fill the top digits with zeroes */ + ix -= p; + while(ix < USED(mp)) + dp[ix++] = 0; + + /* Strip off any leading zeroes */ + s_mp_clamp(mp); + +} /* end s_mp_rshd() */ + +/* }}} */ + +/* {{{ s_mp_div_2(mp) */ + +/* Divide by two -- take advantage of radix properties to do it fast */ +void s_mp_div_2(mp_int *mp) +{ + s_mp_div_2d(mp, 1); + +} /* end s_mp_div_2() */ + +/* }}} */ + +/* {{{ s_mp_mul_2(mp) */ + +mp_err s_mp_mul_2(mp_int *mp) +{ + int ix; + mp_digit kin = 0, kout, *dp = DIGITS(mp); + mp_err res; + + /* Shift digits leftward by 1 bit */ + for(ix = 0; ix < USED(mp); ix++) { + kout = (dp[ix] >> (DIGIT_BIT - 1)) & 1; + dp[ix] = (dp[ix] << 1) | kin; + + kin = kout; + } + + /* Deal with rollover from last digit */ + if(kin) { + if(ix >= ALLOC(mp)) { + if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY) + return res; + dp = DIGITS(mp); + } + + dp[ix] = kin; + USED(mp) += 1; + } + + return MP_OKAY; + +} /* end s_mp_mul_2() */ + +/* }}} */ + +/* {{{ s_mp_mod_2d(mp, d) */ + +/* + Remainder the integer by 2^d, where d is a number of bits. This + amounts to a bitwise AND of the value, and does not require the full + division code + */ +void s_mp_mod_2d(mp_int *mp, mp_digit d) +{ + unsigned int ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT); + unsigned int ix; + mp_digit dmask, *dp = DIGITS(mp); + + if(ndig >= USED(mp)) + return; + + /* Flush all the bits above 2^d in its digit */ + dmask = (1 << nbit) - 1; + dp[ndig] &= dmask; + + /* Flush all digits above the one with 2^d in it */ + for(ix = ndig + 1; ix < USED(mp); ix++) + dp[ix] = 0; + + s_mp_clamp(mp); + +} /* end s_mp_mod_2d() */ + +/* }}} */ + +/* {{{ s_mp_mul_2d(mp, d) */ + +/* + Multiply by the integer 2^d, where d is a number of bits. This + amounts to a bitwise shift of the value, and does not require the + full multiplication code. + */ +mp_err s_mp_mul_2d(mp_int *mp, mp_digit d) +{ + mp_err res; + mp_digit save, next, mask, *dp; + mp_size used; + int ix; + + if((res = s_mp_lshd(mp, d / DIGIT_BIT)) != MP_OKAY) + return res; + + dp = DIGITS(mp); used = USED(mp); + d %= DIGIT_BIT; + + mask = (1 << d) - 1; + + /* If the shift requires another digit, make sure we've got one to + work with */ + if((dp[used - 1] >> (DIGIT_BIT - d)) & mask) { + if((res = s_mp_grow(mp, used + 1)) != MP_OKAY) + return res; + dp = DIGITS(mp); + } + + /* Do the shifting... */ + save = 0; + for(ix = 0; ix < used; ix++) { + next = (dp[ix] >> (DIGIT_BIT - d)) & mask; + dp[ix] = (dp[ix] << d) | save; + save = next; + } + + /* If, at this point, we have a nonzero carryout into the next + digit, we'll increase the size by one digit, and store it... + */ + if(save) { + dp[used] = save; + USED(mp) += 1; + } + + s_mp_clamp(mp); + return MP_OKAY; + +} /* end s_mp_mul_2d() */ + +/* }}} */ + +/* {{{ s_mp_div_2d(mp, d) */ + +/* + Divide the integer by 2^d, where d is a number of bits. This + amounts to a bitwise shift of the value, and does not require the + full division code (used in Barrett reduction, see below) + */ +void s_mp_div_2d(mp_int *mp, mp_digit d) +{ + int ix; + mp_digit save, next, mask, *dp = DIGITS(mp); + + s_mp_rshd(mp, d / DIGIT_BIT); + d %= DIGIT_BIT; + + mask = (1 << d) - 1; + + save = 0; + for(ix = USED(mp) - 1; ix >= 0; ix--) { + next = dp[ix] & mask; + dp[ix] = (dp[ix] >> d) | (save << (DIGIT_BIT - d)); + save = next; + } + + s_mp_clamp(mp); + +} /* end s_mp_div_2d() */ + +/* }}} */ + +/* {{{ s_mp_norm(a, b) */ + +/* + s_mp_norm(a, b) + + Normalize a and b for division, where b is the divisor. In order + that we might make good guesses for quotient digits, we want the + leading digit of b to be at least half the radix, which we + accomplish by multiplying a and b by a constant. This constant is + returned (so that it can be divided back out of the remainder at the + end of the division process). + + We multiply by the smallest power of 2 that gives us a leading digit + at least half the radix. By choosing a power of 2, we simplify the + multiplication and division steps to simple shifts. + */ +mp_digit s_mp_norm(mp_int *a, mp_int *b) +{ + mp_digit t, d = 0; + + t = DIGIT(b, USED(b) - 1); + while(t < (RADIX / 2)) { + t <<= 1; + ++d; + } + + if(d != 0) { + s_mp_mul_2d(a, d); + s_mp_mul_2d(b, d); + } + + return d; + +} /* end s_mp_norm() */ + +/* }}} */ + +/* }}} */ + +/* {{{ Primitive digit arithmetic */ + +/* {{{ s_mp_add_d(mp, d) */ + +/* Add d to |mp| in place */ +mp_err s_mp_add_d(mp_int *mp, mp_digit d) /* unsigned digit addition */ +{ + mp_word w, k = 0; + mp_size ix = 1, used = USED(mp); + mp_digit *dp = DIGITS(mp); + + w = dp[0] + d; + dp[0] = ACCUM(w); + k = CARRYOUT(w); + + while(ix < used && k) { + w = dp[ix] + k; + dp[ix] = ACCUM(w); + k = CARRYOUT(w); + ++ix; + } + + if(k != 0) { + mp_err res; + + if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY) + return res; + + DIGIT(mp, ix) = k; + } + + return MP_OKAY; + +} /* end s_mp_add_d() */ + +/* }}} */ + +/* {{{ s_mp_sub_d(mp, d) */ + +/* Subtract d from |mp| in place, assumes |mp| > d */ +mp_err s_mp_sub_d(mp_int *mp, mp_digit d) /* unsigned digit subtract */ +{ + mp_word w, b = 0; + mp_size ix = 1, used = USED(mp); + mp_digit *dp = DIGITS(mp); + + /* Compute initial subtraction */ + w = (RADIX + dp[0]) - d; + b = CARRYOUT(w) ? 0 : 1; + dp[0] = ACCUM(w); + + /* Propagate borrows leftward */ + while(b && ix < used) { + w = (RADIX + dp[ix]) - b; + b = CARRYOUT(w) ? 0 : 1; + dp[ix] = ACCUM(w); + ++ix; + } + + /* Remove leading zeroes */ + s_mp_clamp(mp); + + /* If we have a borrow out, it's a violation of the input invariant */ + if(b) + return MP_RANGE; + else + return MP_OKAY; + +} /* end s_mp_sub_d() */ + +/* }}} */ + +/* {{{ s_mp_mul_d(a, d) */ + +/* Compute a = a * d, single digit multiplication */ +mp_err s_mp_mul_d(mp_int *a, mp_digit d) +{ + mp_word w, k = 0; + mp_size ix, max; + mp_err res; + mp_digit *dp = DIGITS(a); + + /* + Single-digit multiplication will increase the precision of the + output by at most one digit. However, we can detect when this + will happen -- if the high-order digit of a, times d, gives a + two-digit result, then the precision of the result will increase; + otherwise it won't. We use this fact to avoid calling s_mp_pad() + unless absolutely necessary. + */ + max = USED(a); + w = dp[max - 1] * d; + if(CARRYOUT(w) != 0) { + if((res = s_mp_pad(a, max + 1)) != MP_OKAY) + return res; + dp = DIGITS(a); + } + + for(ix = 0; ix < max; ix++) { + w = (dp[ix] * d) + k; + dp[ix] = ACCUM(w); + k = CARRYOUT(w); + } + + /* If there is a precision increase, take care of it here; the above + test guarantees we have enough storage to do this safely. + */ + if(k) { + dp[max] = k; + USED(a) = max + 1; + } + + s_mp_clamp(a); + + return MP_OKAY; + +} /* end s_mp_mul_d() */ + +/* }}} */ + +/* {{{ s_mp_div_d(mp, d, r) */ + +/* + s_mp_div_d(mp, d, r) + + Compute the quotient mp = mp / d and remainder r = mp mod d, for a + single digit d. If r is null, the remainder will be discarded. + */ + +mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r) +{ + mp_word w = 0, t; + mp_int quot; + mp_err res; + mp_digit *dp = DIGITS(mp), *qp; + int ix; + + if(d == 0) + return MP_RANGE; + + /* Make room for the quotient */ + if((res = mp_init_size(", USED(mp))) != MP_OKAY) + return res; + + USED(") = USED(mp); /* so clamping will work below */ + qp = DIGITS("); + + /* Divide without subtraction */ + for(ix = USED(mp) - 1; ix >= 0; ix--) { + w = (w << DIGIT_BIT) | dp[ix]; + + if(w >= d) { + t = w / d; + w = w % d; + } else { + t = 0; + } + + qp[ix] = t; + } + + /* Deliver the remainder, if desired */ + if(r) + *r = w; + + s_mp_clamp("); + mp_exch(", mp); + mp_clear("); + + return MP_OKAY; + +} /* end s_mp_div_d() */ + +/* }}} */ + +/* }}} */ + +/* {{{ Primitive full arithmetic */ + +/* {{{ s_mp_add(a, b) */ + +/* Compute a = |a| + |b| */ +mp_err s_mp_add(mp_int *a, mp_int *b) /* magnitude addition */ +{ + mp_word w = 0; + mp_digit *pa, *pb; + mp_size ix, used = USED(b); + mp_err res; + + /* Make sure a has enough precision for the output value */ + if((used > USED(a)) && (res = s_mp_pad(a, used)) != MP_OKAY) + return res; + + /* + Add up all digits up to the precision of b. If b had initially + the same precision as a, or greater, we took care of it by the + padding step above, so there is no problem. If b had initially + less precision, we'll have to make sure the carry out is duly + propagated upward among the higher-order digits of the sum. + */ + pa = DIGITS(a); + pb = DIGITS(b); + for(ix = 0; ix < used; ++ix) { + w += *pa + *pb++; + *pa++ = ACCUM(w); + w = CARRYOUT(w); + } + + /* If we run out of 'b' digits before we're actually done, make + sure the carries get propagated upward... + */ + used = USED(a); + while(w && ix < used) { + w += *pa; + *pa++ = ACCUM(w); + w = CARRYOUT(w); + ++ix; + } + + /* If there's an overall carry out, increase precision and include + it. We could have done this initially, but why touch the memory + allocator unless we're sure we have to? + */ + if(w) { + if((res = s_mp_pad(a, used + 1)) != MP_OKAY) + return res; + + DIGIT(a, ix) = w; /* pa may not be valid after s_mp_pad() call */ + } + + return MP_OKAY; + +} /* end s_mp_add() */ + +/* }}} */ + +/* {{{ s_mp_sub(a, b) */ + +/* Compute a = |a| - |b|, assumes |a| >= |b| */ +mp_err s_mp_sub(mp_int *a, mp_int *b) /* magnitude subtract */ +{ + mp_word w = 0; + mp_digit *pa, *pb; + mp_size ix, used = USED(b); + + /* + Subtract and propagate borrow. Up to the precision of b, this + accounts for the digits of b; after that, we just make sure the + carries get to the right place. This saves having to pad b out to + the precision of a just to make the loops work right... + */ + pa = DIGITS(a); + pb = DIGITS(b); + + for(ix = 0; ix < used; ++ix) { + w = (RADIX + *pa) - w - *pb++; + *pa++ = ACCUM(w); + w = CARRYOUT(w) ? 0 : 1; + } + + used = USED(a); + while(ix < used) { + w = RADIX + *pa - w; + *pa++ = ACCUM(w); + w = CARRYOUT(w) ? 0 : 1; + ++ix; + } + + /* Clobber any leading zeroes we created */ + s_mp_clamp(a); + + /* + If there was a borrow out, then |b| > |a| in violation + of our input invariant. We've already done the work, + but we'll at least complain about it... + */ + if(w) + return MP_RANGE; + else + return MP_OKAY; + +} /* end s_mp_sub() */ + +/* }}} */ + +mp_err s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu) +{ + mp_int q; + mp_err res; + mp_size um = USED(m); + + if((res = mp_init_copy(&q, x)) != MP_OKAY) + return res; + + s_mp_rshd(&q, um - 1); /* q1 = x / b^(k-1) */ + s_mp_mul(&q, mu); /* q2 = q1 * mu */ + s_mp_rshd(&q, um + 1); /* q3 = q2 / b^(k+1) */ + + /* x = x mod b^(k+1), quick (no division) */ + s_mp_mod_2d(x, (mp_digit)(DIGIT_BIT * (um + 1))); + + /* q = q * m mod b^(k+1), quick (no division), uses the short multiplier */ +#ifndef SHRT_MUL + s_mp_mul(&q, m); + s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1))); +#else + s_mp_mul_dig(&q, m, um + 1); +#endif + + /* x = x - q */ + if((res = mp_sub(x, &q, x)) != MP_OKAY) + goto CLEANUP; + + /* If x < 0, add b^(k+1) to it */ + if(mp_cmp_z(x) < 0) { + mp_set(&q, 1); + if((res = s_mp_lshd(&q, um + 1)) != MP_OKAY) + goto CLEANUP; + if((res = mp_add(x, &q, x)) != MP_OKAY) + goto CLEANUP; + } + + /* Back off if it's too big */ + while(mp_cmp(x, m) >= 0) { + if((res = s_mp_sub(x, m)) != MP_OKAY) + break; + } + + CLEANUP: + mp_clear(&q); + + return res; + +} /* end s_mp_reduce() */ + + + +/* {{{ s_mp_mul(a, b) */ + +/* Compute a = |a| * |b| */ +mp_err s_mp_mul(mp_int *a, mp_int *b) +{ + mp_word w, k = 0; + mp_int tmp; + mp_err res; + mp_size ix, jx, ua = USED(a), ub = USED(b); + mp_digit *pa, *pb, *pt, *pbt; + + if((res = mp_init_size(&tmp, ua + ub)) != MP_OKAY) + return res; + + /* This has the effect of left-padding with zeroes... */ + USED(&tmp) = ua + ub; + + /* We're going to need the base value each iteration */ + pbt = DIGITS(&tmp); + + /* Outer loop: Digits of b */ + + pb = DIGITS(b); + for(ix = 0; ix < ub; ++ix, ++pb) { + if(*pb == 0) + continue; + + /* Inner product: Digits of a */ + pa = DIGITS(a); + for(jx = 0; jx < ua; ++jx, ++pa) { + pt = pbt + ix + jx; + w = *pb * *pa + k + *pt; + *pt = ACCUM(w); + k = CARRYOUT(w); + } + + pbt[ix + jx] = k; + k = 0; + } + + s_mp_clamp(&tmp); + s_mp_exch(&tmp, a); + + mp_clear(&tmp); + + return MP_OKAY; + +} /* end s_mp_mul() */ + +/* }}} */ + +/* {{{ s_mp_kmul(a, b, out, len) */ + +#if 0 +void s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len) +{ + mp_word w, k = 0; + mp_size ix, jx; + mp_digit *pa, *pt; + + for(ix = 0; ix < len; ++ix, ++b) { + if(*b == 0) + continue; + + pa = a; + for(jx = 0; jx < len; ++jx, ++pa) { + pt = out + ix + jx; + w = *b * *pa + k + *pt; + *pt = ACCUM(w); + k = CARRYOUT(w); + } + + out[ix + jx] = k; + k = 0; + } + +} /* end s_mp_kmul() */ +#endif + +/* }}} */ + +/* {{{ s_mp_sqr(a) */ + +/* + Computes the square of a, in place. This can be done more + efficiently than a general multiplication, because many of the + computation steps are redundant when squaring. The inner product + step is a bit more complicated, but we save a fair number of + iterations of the multiplication loop. + */ +#if MP_SQUARE +mp_err s_mp_sqr(mp_int *a) +{ + mp_word w, k = 0; + mp_int tmp; + mp_err res; + mp_size ix, jx, kx, used = USED(a); + mp_digit *pa1, *pa2, *pt, *pbt; + + if((res = mp_init_size(&tmp, 2 * used)) != MP_OKAY) + return res; + + /* Left-pad with zeroes */ + USED(&tmp) = 2 * used; + + /* We need the base value each time through the loop */ + pbt = DIGITS(&tmp); + + pa1 = DIGITS(a); + for(ix = 0; ix < used; ++ix, ++pa1) { + if(*pa1 == 0) + continue; + + w = DIGIT(&tmp, ix + ix) + (*pa1 * *pa1); + + pbt[ix + ix] = ACCUM(w); + k = CARRYOUT(w); + + /* + The inner product is computed as: + + (C, S) = t[i,j] + 2 a[i] a[j] + C + + This can overflow what can be represented in an mp_word, and + since C arithmetic does not provide any way to check for + overflow, we have to check explicitly for overflow conditions + before they happen. + */ + for(jx = ix + 1, pa2 = DIGITS(a) + jx; jx < used; ++jx, ++pa2) { + mp_word u = 0, v; + + /* Store this in a temporary to avoid indirections later */ + pt = pbt + ix + jx; + + /* Compute the multiplicative step */ + w = *pa1 * *pa2; + + /* If w is more than half MP_WORD_MAX, the doubling will + overflow, and we need to record a carry out into the next + word */ + u = (w >> (MP_WORD_BIT - 1)) & 1; + + /* Double what we've got, overflow will be ignored as defined + for C arithmetic (we've already noted if it is to occur) + */ + w *= 2; + + /* Compute the additive step */ + v = *pt + k; + + /* If we do not already have an overflow carry, check to see + if the addition will cause one, and set the carry out if so + */ + u |= ((MP_WORD_MAX - v) < w); + + /* Add in the rest, again ignoring overflow */ + w += v; + + /* Set the i,j digit of the output */ + *pt = ACCUM(w); + + /* Save carry information for the next iteration of the loop. + This is why k must be an mp_word, instead of an mp_digit */ + k = CARRYOUT(w) | (u << DIGIT_BIT); + + } /* for(jx ...) */ + + /* Set the last digit in the cycle and reset the carry */ + k = DIGIT(&tmp, ix + jx) + k; + pbt[ix + jx] = ACCUM(k); + k = CARRYOUT(k); + + /* If we are carrying out, propagate the carry to the next digit + in the output. This may cascade, so we have to be somewhat + circumspect -- but we will have enough precision in the output + that we won't overflow + */ + kx = 1; + while(k) { + k = pbt[ix + jx + kx] + 1; + pbt[ix + jx + kx] = ACCUM(k); + k = CARRYOUT(k); + ++kx; + } + } /* for(ix ...) */ + + s_mp_clamp(&tmp); + s_mp_exch(&tmp, a); + + mp_clear(&tmp); + + return MP_OKAY; + +} /* end s_mp_sqr() */ +#endif + +/* }}} */ + +/* {{{ s_mp_div(a, b) */ + +/* + s_mp_div(a, b) + + Compute a = a / b and b = a mod b. Assumes b > a. + */ + +mp_err s_mp_div(mp_int *a, mp_int *b) +{ + mp_int quot, rem, t; + mp_word q; + mp_err res; + mp_digit d; + int ix; + + if(mp_cmp_z(b) == 0) + return MP_RANGE; + + /* Shortcut if b is power of two */ + if((ix = s_mp_ispow2(b)) >= 0) { + mp_copy(a, b); /* need this for remainder */ + s_mp_div_2d(a, (mp_digit)ix); + s_mp_mod_2d(b, (mp_digit)ix); + + return MP_OKAY; + } + + /* Allocate space to store the quotient */ + if((res = mp_init_size(", USED(a))) != MP_OKAY) + return res; + + /* A working temporary for division */ + if((res = mp_init_size(&t, USED(a))) != MP_OKAY) + goto T; + + /* Allocate space for the remainder */ + if((res = mp_init_size(&rem, USED(a))) != MP_OKAY) + goto REM; + + /* Normalize to optimize guessing */ + d = s_mp_norm(a, b); + + /* Perform the division itself...woo! */ + ix = USED(a) - 1; + + while(ix >= 0) { + /* Find a partial substring of a which is at least b */ + while(s_mp_cmp(&rem, b) < 0 && ix >= 0) { + if((res = s_mp_lshd(&rem, 1)) != MP_OKAY) + goto CLEANUP; + + if((res = s_mp_lshd(", 1)) != MP_OKAY) + goto CLEANUP; + + DIGIT(&rem, 0) = DIGIT(a, ix); + s_mp_clamp(&rem); + --ix; + } + + /* If we didn't find one, we're finished dividing */ + if(s_mp_cmp(&rem, b) < 0) + break; + + /* Compute a guess for the next quotient digit */ + q = DIGIT(&rem, USED(&rem) - 1); + if(q <= DIGIT(b, USED(b) - 1) && USED(&rem) > 1) + q = (q << DIGIT_BIT) | DIGIT(&rem, USED(&rem) - 2); + + q /= DIGIT(b, USED(b) - 1); + + /* The guess can be as much as RADIX + 1 */ + if(q >= RADIX) + q = RADIX - 1; + + /* See what that multiplies out to */ + mp_copy(b, &t); + if((res = s_mp_mul_d(&t, q)) != MP_OKAY) + goto CLEANUP; + + /* + If it's too big, back it off. We should not have to do this + more than once, or, in rare cases, twice. Knuth describes a + method by which this could be reduced to a maximum of once, but + I didn't implement that here. + */ + while(s_mp_cmp(&t, &rem) > 0) { + --q; + s_mp_sub(&t, b); + } + + /* At this point, q should be the right next digit */ + if((res = s_mp_sub(&rem, &t)) != MP_OKAY) + goto CLEANUP; + + /* + Include the digit in the quotient. We allocated enough memory + for any quotient we could ever possibly get, so we should not + have to check for failures here + */ + DIGIT(", 0) = q; + } + + /* Denormalize remainder */ + if(d != 0) + s_mp_div_2d(&rem, d); + + s_mp_clamp("); + s_mp_clamp(&rem); + + /* Copy quotient back to output */ + s_mp_exch(", a); + + /* Copy remainder back to output */ + s_mp_exch(&rem, b); + +CLEANUP: + mp_clear(&rem); +REM: + mp_clear(&t); +T: + mp_clear("); + + return res; + +} /* end s_mp_div() */ + +/* }}} */ + +/* {{{ s_mp_2expt(a, k) */ + +mp_err s_mp_2expt(mp_int *a, mp_digit k) +{ + mp_err res; + mp_size dig, bit; + + dig = k / DIGIT_BIT; + bit = k % DIGIT_BIT; + + mp_zero(a); + if((res = s_mp_pad(a, dig + 1)) != MP_OKAY) + return res; + + DIGIT(a, dig) |= (1 << bit); + + return MP_OKAY; + +} /* end s_mp_2expt() */ + +/* }}} */ + + +/* }}} */ + +/* }}} */ + +/* {{{ Primitive comparisons */ + +/* {{{ s_mp_cmp(a, b) */ + +/* Compare |a| <=> |b|, return 0 if equal, <0 if a0 if a>b */ +int s_mp_cmp(mp_int *a, mp_int *b) +{ + mp_size ua = USED(a), ub = USED(b); + + if(ua > ub) + return MP_GT; + else if(ua < ub) + return MP_LT; + else { + int ix = ua - 1; + mp_digit *ap = DIGITS(a) + ix, *bp = DIGITS(b) + ix; + + while(ix >= 0) { + if(*ap > *bp) + return MP_GT; + else if(*ap < *bp) + return MP_LT; + + --ap; --bp; --ix; + } + + return MP_EQ; + } + +} /* end s_mp_cmp() */ + +/* }}} */ + +/* {{{ s_mp_cmp_d(a, d) */ + +/* Compare |a| <=> d, return 0 if equal, <0 if a0 if a>d */ +int s_mp_cmp_d(mp_int *a, mp_digit d) +{ + mp_size ua = USED(a); + mp_digit *ap = DIGITS(a); + + if(ua > 1) + return MP_GT; + + if(*ap < d) + return MP_LT; + else if(*ap > d) + return MP_GT; + else + return MP_EQ; + +} /* end s_mp_cmp_d() */ + +/* }}} */ + +/* {{{ s_mp_ispow2(v) */ + +/* + Returns -1 if the value is not a power of two; otherwise, it returns + k such that v = 2^k, i.e. lg(v). + */ +int s_mp_ispow2(mp_int *v) +{ + mp_digit d, *dp; + mp_size uv = USED(v); + int extra = 0, ix; + + d = DIGIT(v, uv - 1); /* most significant digit of v */ + + while(d && ((d & 1) == 0)) { + d >>= 1; + ++extra; + } + + if(d == 1) { + ix = uv - 2; + dp = DIGITS(v) + ix; + + while(ix >= 0) { + if(*dp) + return -1; /* not a power of two */ + + --dp; --ix; + } + + return ((uv - 1) * DIGIT_BIT) + extra; + } + + return -1; + +} /* end s_mp_ispow2() */ + +/* }}} */ + +/* {{{ s_mp_ispow2d(d) */ + +int s_mp_ispow2d(mp_digit d) +{ + int pow = 0; + + while((d & 1) == 0) { + ++pow; d >>= 1; + } + + if(d == 1) + return pow; + + return -1; + +} /* end s_mp_ispow2d() */ + +/* }}} */ + +/* }}} */ + +/* {{{ Primitive I/O helpers */ + +/* {{{ s_mp_tovalue(ch, r) */ + +/* + Convert the given character to its digit value, in the given radix. + If the given character is not understood in the given radix, -1 is + returned. Otherwise the digit's numeric value is returned. + + The results will be odd if you use a radix < 2 or > 62, you are + expected to know what you're up to. + */ +int s_mp_tovalue(char ch, int r) +{ + int val, xch; + + if(r > 36) + xch = ch; + else + xch = toupper(ch); + + if(isdigit(xch)) + val = xch - '0'; + else if(isupper(xch)) + val = xch - 'A' + 10; + else if(islower(xch)) + val = xch - 'a' + 36; + else if(xch == '+') + val = 62; + else if(xch == '/') + val = 63; + else + return -1; + + if(val < 0 || val >= r) + return -1; + + return val; + +} /* end s_mp_tovalue() */ + +/* }}} */ + +/* {{{ s_mp_todigit(val, r, low) */ + +/* + Convert val to a radix-r digit, if possible. If val is out of range + for r, returns zero. Otherwise, returns an ASCII character denoting + the value in the given radix. + + The results may be odd if you use a radix < 2 or > 64, you are + expected to know what you're doing. + */ + +char s_mp_todigit(int val, int r, int low) +{ + char ch; + + if(val < 0 || val >= r) + return 0; + + ch = s_dmap_1[val]; + + if(r <= 36 && low) + ch = tolower(ch); + + return ch; + +} /* end s_mp_todigit() */ + +/* }}} */ + +/* {{{ s_mp_outlen(bits, radix) */ + +/* + Return an estimate for how long a string is needed to hold a radix + r representation of a number with 'bits' significant bits. + + Does not include space for a sign or a NUL terminator. + */ +int s_mp_outlen(int bits, int r) +{ + return (int)((double)bits * LOG_V_2(r)); + +} /* end s_mp_outlen() */ + +/* }}} */ + +/* }}} */ + +/*------------------------------------------------------------------------*/ +/* HERE THERE BE DRAGONS */ +/* crc==4242132123, version==2, Sat Feb 02 06:43:52 2002 */ + +/* $Source: /cvs/libtom/libtommath/mtest/mpi.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/mtest/mpi.h b/lib/hcrypto/libtommath/mtest/mpi.h new file mode 100644 index 000000000..66ae87311 --- /dev/null +++ b/lib/hcrypto/libtommath/mtest/mpi.h @@ -0,0 +1,231 @@ +/* + mpi.h + + by Michael J. Fromberger + Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved + + Arbitrary precision integer arithmetic library + + $Id: mpi.h,v 1.2 2005/05/05 14:38:47 tom Exp $ + */ + +#ifndef _H_MPI_ +#define _H_MPI_ + +#include "mpi-config.h" + +#define MP_LT -1 +#define MP_EQ 0 +#define MP_GT 1 + +#if MP_DEBUG +#undef MP_IOFUNC +#define MP_IOFUNC 1 +#endif + +#if MP_IOFUNC +#include +#include +#endif + +#include + +#define MP_NEG 1 +#define MP_ZPOS 0 + +/* Included for compatibility... */ +#define NEG MP_NEG +#define ZPOS MP_ZPOS + +#define MP_OKAY 0 /* no error, all is well */ +#define MP_YES 0 /* yes (boolean result) */ +#define MP_NO -1 /* no (boolean result) */ +#define MP_MEM -2 /* out of memory */ +#define MP_RANGE -3 /* argument out of range */ +#define MP_BADARG -4 /* invalid parameter */ +#define MP_UNDEF -5 /* answer is undefined */ +#define MP_LAST_CODE MP_UNDEF + +#include "mpi-types.h" + +/* Included for compatibility... */ +#define DIGIT_BIT MP_DIGIT_BIT +#define DIGIT_MAX MP_DIGIT_MAX + +/* Macros for accessing the mp_int internals */ +#define SIGN(MP) ((MP)->sign) +#define USED(MP) ((MP)->used) +#define ALLOC(MP) ((MP)->alloc) +#define DIGITS(MP) ((MP)->dp) +#define DIGIT(MP,N) (MP)->dp[(N)] + +#if MP_ARGCHK == 1 +#define ARGCHK(X,Y) {if(!(X)){return (Y);}} +#elif MP_ARGCHK == 2 +#include +#define ARGCHK(X,Y) assert(X) +#else +#define ARGCHK(X,Y) /* */ +#endif + +/* This defines the maximum I/O base (minimum is 2) */ +#define MAX_RADIX 64 + +typedef struct { + mp_sign sign; /* sign of this quantity */ + mp_size alloc; /* how many digits allocated */ + mp_size used; /* how many digits used */ + mp_digit *dp; /* the digits themselves */ +} mp_int; + +/*------------------------------------------------------------------------*/ +/* Default precision */ + +unsigned int mp_get_prec(void); +void mp_set_prec(unsigned int prec); + +/*------------------------------------------------------------------------*/ +/* Memory management */ + +mp_err mp_init(mp_int *mp); +mp_err mp_init_array(mp_int mp[], int count); +mp_err mp_init_size(mp_int *mp, mp_size prec); +mp_err mp_init_copy(mp_int *mp, mp_int *from); +mp_err mp_copy(mp_int *from, mp_int *to); +void mp_exch(mp_int *mp1, mp_int *mp2); +void mp_clear(mp_int *mp); +void mp_clear_array(mp_int mp[], int count); +void mp_zero(mp_int *mp); +void mp_set(mp_int *mp, mp_digit d); +mp_err mp_set_int(mp_int *mp, long z); +mp_err mp_shrink(mp_int *a); + + +/*------------------------------------------------------------------------*/ +/* Single digit arithmetic */ + +mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b); +mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b); +mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b); +mp_err mp_mul_2(mp_int *a, mp_int *c); +mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r); +mp_err mp_div_2(mp_int *a, mp_int *c); +mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c); + +/*------------------------------------------------------------------------*/ +/* Sign manipulations */ + +mp_err mp_abs(mp_int *a, mp_int *b); +mp_err mp_neg(mp_int *a, mp_int *b); + +/*------------------------------------------------------------------------*/ +/* Full arithmetic */ + +mp_err mp_add(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_mul_2d(mp_int *a, mp_digit d, mp_int *c); +#if MP_SQUARE +mp_err mp_sqr(mp_int *a, mp_int *b); +#else +#define mp_sqr(a, b) mp_mul(a, a, b) +#endif +mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r); +mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r); +mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_2expt(mp_int *a, mp_digit k); +mp_err mp_sqrt(mp_int *a, mp_int *b); + +/*------------------------------------------------------------------------*/ +/* Modular arithmetic */ + +#if MP_MODARITH +mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c); +mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c); +mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c); +mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c); +mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c); +#if MP_SQUARE +mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c); +#else +#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c) +#endif +mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c); +mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c); +#endif /* MP_MODARITH */ + +/*------------------------------------------------------------------------*/ +/* Comparisons */ + +int mp_cmp_z(mp_int *a); +int mp_cmp_d(mp_int *a, mp_digit d); +int mp_cmp(mp_int *a, mp_int *b); +int mp_cmp_mag(mp_int *a, mp_int *b); +int mp_cmp_int(mp_int *a, long z); +int mp_isodd(mp_int *a); +int mp_iseven(mp_int *a); + +/*------------------------------------------------------------------------*/ +/* Number theoretic */ + +#if MP_NUMTH +mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y); +mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c); +#endif /* end MP_NUMTH */ + +/*------------------------------------------------------------------------*/ +/* Input and output */ + +#if MP_IOFUNC +void mp_print(mp_int *mp, FILE *ofp); +#endif /* end MP_IOFUNC */ + +/*------------------------------------------------------------------------*/ +/* Base conversion */ + +#define BITS 1 +#define BYTES CHAR_BIT + +mp_err mp_read_signed_bin(mp_int *mp, unsigned char *str, int len); +int mp_signed_bin_size(mp_int *mp); +mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str); + +mp_err mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len); +int mp_unsigned_bin_size(mp_int *mp); +mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str); + +int mp_count_bits(mp_int *mp); + +#if MP_COMPAT_MACROS +#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) +#define mp_raw_size(mp) mp_signed_bin_size(mp) +#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) +#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) +#define mp_mag_size(mp) mp_unsigned_bin_size(mp) +#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) +#endif + +mp_err mp_read_radix(mp_int *mp, unsigned char *str, int radix); +int mp_radix_size(mp_int *mp, int radix); +int mp_value_radix_size(int num, int qty, int radix); +mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix); + +int mp_char2value(char ch, int r); + +#define mp_tobinary(M, S) mp_toradix((M), (S), 2) +#define mp_tooctal(M, S) mp_toradix((M), (S), 8) +#define mp_todecimal(M, S) mp_toradix((M), (S), 10) +#define mp_tohex(M, S) mp_toradix((M), (S), 16) + +/*------------------------------------------------------------------------*/ +/* Error strings */ + +const char *mp_strerror(mp_err ec); + +#endif /* end _H_MPI_ */ + +/* $Source: /cvs/libtom/libtommath/mtest/mpi.h,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/mtest/mtest.c b/lib/hcrypto/libtommath/mtest/mtest.c new file mode 100644 index 000000000..bdfe6127a --- /dev/null +++ b/lib/hcrypto/libtommath/mtest/mtest.c @@ -0,0 +1,308 @@ +/* makes a bignum test harness with NUM tests per operation + * + * the output is made in the following format [one parameter per line] + +operation +operand1 +operand2 +[... operandN] +result1 +result2 +[... resultN] + +So for example "a * b mod n" would be + +mulmod +a +b +n +a*b mod n + +e.g. if a=3, b=4 n=11 then + +mulmod +3 +4 +11 +1 + + */ + +#ifdef MP_8BIT +#define THE_MASK 127 +#else +#define THE_MASK 32767 +#endif + +#include +#include +#include +#include "mpi.c" + +FILE *rng; + +void rand_num(mp_int *a) +{ + int n, size; + unsigned char buf[2048]; + + size = 1 + ((fgetc(rng)<<8) + fgetc(rng)) % 101; + buf[0] = (fgetc(rng)&1)?1:0; + fread(buf+1, 1, size, rng); + while (buf[1] == 0) buf[1] = fgetc(rng); + mp_read_raw(a, buf, 1+size); +} + +void rand_num2(mp_int *a) +{ + int n, size; + unsigned char buf[2048]; + + size = 10 + ((fgetc(rng)<<8) + fgetc(rng)) % 101; + buf[0] = (fgetc(rng)&1)?1:0; + fread(buf+1, 1, size, rng); + while (buf[1] == 0) buf[1] = fgetc(rng); + mp_read_raw(a, buf, 1+size); +} + +#define mp_to64(a, b) mp_toradix(a, b, 64) + +int main(void) +{ + int n, tmp; + mp_int a, b, c, d, e; + clock_t t1; + char buf[4096]; + + mp_init(&a); + mp_init(&b); + mp_init(&c); + mp_init(&d); + mp_init(&e); + + + /* initial (2^n - 1)^2 testing, makes sure the comba multiplier works [it has the new carry code] */ +/* + mp_set(&a, 1); + for (n = 1; n < 8192; n++) { + mp_mul(&a, &a, &c); + printf("mul\n"); + mp_to64(&a, buf); + printf("%s\n%s\n", buf, buf); + mp_to64(&c, buf); + printf("%s\n", buf); + + mp_add_d(&a, 1, &a); + mp_mul_2(&a, &a); + mp_sub_d(&a, 1, &a); + } +*/ + + rng = fopen("/dev/urandom", "rb"); + if (rng == NULL) { + rng = fopen("/dev/random", "rb"); + if (rng == NULL) { + fprintf(stderr, "\nWarning: stdin used as random source\n\n"); + rng = stdin; + } + } + + t1 = clock(); + for (;;) { +#if 0 + if (clock() - t1 > CLOCKS_PER_SEC) { + sleep(2); + t1 = clock(); + } +#endif + n = fgetc(rng) % 15; + + if (n == 0) { + /* add tests */ + rand_num(&a); + rand_num(&b); + mp_add(&a, &b, &c); + printf("add\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + mp_to64(&c, buf); + printf("%s\n", buf); + } else if (n == 1) { + /* sub tests */ + rand_num(&a); + rand_num(&b); + mp_sub(&a, &b, &c); + printf("sub\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + mp_to64(&c, buf); + printf("%s\n", buf); + } else if (n == 2) { + /* mul tests */ + rand_num(&a); + rand_num(&b); + mp_mul(&a, &b, &c); + printf("mul\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + mp_to64(&c, buf); + printf("%s\n", buf); + } else if (n == 3) { + /* div tests */ + rand_num(&a); + rand_num(&b); + mp_div(&a, &b, &c, &d); + printf("div\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + mp_to64(&c, buf); + printf("%s\n", buf); + mp_to64(&d, buf); + printf("%s\n", buf); + } else if (n == 4) { + /* sqr tests */ + rand_num(&a); + mp_sqr(&a, &b); + printf("sqr\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + } else if (n == 5) { + /* mul_2d test */ + rand_num(&a); + mp_copy(&a, &b); + n = fgetc(rng) & 63; + mp_mul_2d(&b, n, &b); + mp_to64(&a, buf); + printf("mul2d\n"); + printf("%s\n", buf); + printf("%d\n", n); + mp_to64(&b, buf); + printf("%s\n", buf); + } else if (n == 6) { + /* div_2d test */ + rand_num(&a); + mp_copy(&a, &b); + n = fgetc(rng) & 63; + mp_div_2d(&b, n, &b, NULL); + mp_to64(&a, buf); + printf("div2d\n"); + printf("%s\n", buf); + printf("%d\n", n); + mp_to64(&b, buf); + printf("%s\n", buf); + } else if (n == 7) { + /* gcd test */ + rand_num(&a); + rand_num(&b); + a.sign = MP_ZPOS; + b.sign = MP_ZPOS; + mp_gcd(&a, &b, &c); + printf("gcd\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + mp_to64(&c, buf); + printf("%s\n", buf); + } else if (n == 8) { + /* lcm test */ + rand_num(&a); + rand_num(&b); + a.sign = MP_ZPOS; + b.sign = MP_ZPOS; + mp_lcm(&a, &b, &c); + printf("lcm\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + mp_to64(&c, buf); + printf("%s\n", buf); + } else if (n == 9) { + /* exptmod test */ + rand_num2(&a); + rand_num2(&b); + rand_num2(&c); +// if (c.dp[0]&1) mp_add_d(&c, 1, &c); + a.sign = b.sign = c.sign = 0; + mp_exptmod(&a, &b, &c, &d); + printf("expt\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + mp_to64(&c, buf); + printf("%s\n", buf); + mp_to64(&d, buf); + printf("%s\n", buf); + } else if (n == 10) { + /* invmod test */ + rand_num2(&a); + rand_num2(&b); + b.sign = MP_ZPOS; + a.sign = MP_ZPOS; + mp_gcd(&a, &b, &c); + if (mp_cmp_d(&c, 1) != 0) continue; + if (mp_cmp_d(&b, 1) == 0) continue; + mp_invmod(&a, &b, &c); + printf("invmod\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + mp_to64(&c, buf); + printf("%s\n", buf); + } else if (n == 11) { + rand_num(&a); + mp_mul_2(&a, &a); + mp_div_2(&a, &b); + printf("div2\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + } else if (n == 12) { + rand_num2(&a); + mp_mul_2(&a, &b); + printf("mul2\n"); + mp_to64(&a, buf); + printf("%s\n", buf); + mp_to64(&b, buf); + printf("%s\n", buf); + } else if (n == 13) { + rand_num2(&a); + tmp = abs(rand()) & THE_MASK; + mp_add_d(&a, tmp, &b); + printf("add_d\n"); + mp_to64(&a, buf); + printf("%s\n%d\n", buf, tmp); + mp_to64(&b, buf); + printf("%s\n", buf); + } else if (n == 14) { + rand_num2(&a); + tmp = abs(rand()) & THE_MASK; + mp_sub_d(&a, tmp, &b); + printf("sub_d\n"); + mp_to64(&a, buf); + printf("%s\n%d\n", buf, tmp); + mp_to64(&b, buf); + printf("%s\n", buf); + } + } + fclose(rng); + return 0; +} + +/* $Source: /cvs/libtom/libtommath/mtest/mtest.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/pics/design_process.sxd b/lib/hcrypto/libtommath/pics/design_process.sxd new file mode 100644 index 0000000000000000000000000000000000000000..7414dbb27696fe716fe8c73a5c2b21d8c3e0c23c GIT binary patch literal 6950 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 literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/pics/design_process.tif b/lib/hcrypto/libtommath/pics/design_process.tif new file mode 100644 index 0000000000000000000000000000000000000000..4a0c012d565ecd12a43186f132b3bccdefb9a23e GIT binary patch literal 79042 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 z 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 z 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
imTAQ|Ef;H}|GB@4fzaU#!j2;w5>{*Y%#* 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 literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/pics/expt_state.sxd b/lib/hcrypto/libtommath/pics/expt_state.sxd new file mode 100644 index 0000000000000000000000000000000000000000..6518404d5fa6eca01b4457a813f85cda074c0915 GIT binary patch literal 6869 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 SkP=n~Rt6PD28P*^ARYiC`4Gea literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/pics/expt_state.tif b/lib/hcrypto/libtommath/pics/expt_state.tif new file mode 100644 index 0000000000000000000000000000000000000000..cb06e8edf17017dec815be222c845f1b0a938e07 GIT binary patch literal 87542 zcmebD)M7{rVPvS7^L8$KMQG@?w&^A>_m(@oV02oqIECR-^?Tm{N0#FkC0%7p)82@_ zRJgSIOB}Q33jwQ^0H&6EOSPUpk3I8{fBNhewV2esc7{``&)cTX-*9gG{=aLZx98mz zI&8p$f-3lSq|VxrDA9(DKF&$N6x%b*#47Z*|9Jn+{;GNYy(zQJ^G@|jn}4}p^Zfkd zquuKI`+h8{Ge?A!a+!}Xn0ub}@9$4nPZxcA6KPrbX^D(|S-XzT*N>mJI(&VWnD-)SLc8}+20{`&g*(^FHmt&TlD(y81jtUk@9Q|RUT|6UjJ8^>RWMaACQOyMtL{I@n_1>M}gNyUHO zpUC&OgrENS_;^#v%^=%zESy3fS677|y?;MGXqnH?HRWfa$=`$l~O5we&*`Oo2x># zUw*C9KRLzl^5%P6)lYqUdpq?&1EW#;IhjhubKI8}xpKe!8RdU+lIrRBPrIOr=GfsR zXo|6G=aZkL=-hTOl=lYsRWzKjX z4O#2bDS5HGZ8xa-g&lr)xc%vsm%*<*&rUU-o@OR7k6rb_+1ch_Uw@id&9=jI*tt2}zM{i4y-0LsMAIG`)DO=60TGCxz9#ca^+clD2l%rG>TZn(^!Y z2w$G_u}t2o#DgiEWmQ?nve>0wqMDJLmZWxnU;*eW0Im!00xEV!xmcp2wy*=5()L~c%-q?Fo~zIV0% zoaE#Eo)=CjaB^~9{G<5a>tE2uq@(I)>z`=Ov8Z$kTNk6Lcu>)5`@`qY)kU>JCWxH; zUv>QoG+oHC!qSDLS<(z1S)-6^>!bB=7N=alGi91?wAZ_sou!Gamx!K{=j1l5p{*7dyNc%SU1 zii=5S_5EgOEd2H~=khY&H8Zu3$sax&ZT|GwSL^HTKf9XS`A@x@yZb8tzW)d6zIHsG zdQ5rlZR_n%PEL0J^!)t#`{dR=Y`v~)?7sCR{x(oe5<@Avw!D&gm&&H5=n zH$9zX=UkO}ciGl0`PbvR#57mg6_x*=vUsX}Pn=w=<%2xwJz}lcQ+47#+mSbSyN-d%fsJnFufr@rfN$GeK8+vnbvf7&0>fB0^?OZmQ- z_~(EAC7xTq`~0uP1$}Q{ZCzdT=SShq-R0|FJ*atmXJ>GqtnIR5vB=G-qU-0xO)}4q zJ2~Bc{*yB^gTH=s;S|mkJHPnFL&K?4`mMwkSI;k=!*8T_=k4w0J?5{flXky*7bkuB z_2TM!pT|b8?2c@k%YHNcxoQ7rjSm{%4^IA3nF@`A{_f02prClTbB;}AP#d4TR z_A7&y?b5fOd#7JJ{JjkG@A|jfvuDlhb)WTbUgV~&y3?-`nrMuUK>Q-Ba)BUu`z}_D#ILSn>EW*#M12 z3GD$Od+3w0~`W|2A7k+&e`gKEb zZG~;r-q#Y(B>H767d@U=IMLEO&2y&G(%ZG^GRF1`k{^HDCMo|${;`GcEt5%xkKaD_ zpA+$D&xillCuWy@ymWN;e{l>mi z9{;&takX;t?e!1k>JQp25 zDZbwfQgZYxZ-l0snIHU3?B3M>`7FOF+%!o)-|p(nnA%IL0_WNu%&{nQ zitG5?bY(@P^B?WstNCQj{bH_eI2UW7etUcV^aY}ho67IUaq{y|w@s`Lng8Vd#mAq; zPw3yi%~x`sDwgl{-Z%*z1+)ish1e8C|=}-cIVBZFcJ1 zTkF#K7dbAT`TOV3lBCwIN!H)z&RhCo@^8L3lNY=9zxwwf>fZTnKmY71eVz4f+iJ6y zT*%6Spx4>H~bd^e-=wFrKV?O>Wvs;P_ex6F*S@5sv)w>wsqC?wr?=E}H z%sc<_$4}oTDY%W* zc6xZ$^_9A!r^ENCZ=aVtcYi_LbM}&&JNx?1)fL9QP=EFO{qkb-j9oqX|N1_km|<1( zWP^*F+bhEYe*?Ff%}F|&BkiH{YcVlIbXnj zJKbl~wWjZ%tlr(6vNFhP+nbvuHAV6*?>Vnqwx#*bemRHdI`7}O{?FfjT>1UuTj8ej zPaYZMNlJ@qg5nOcSy>23aL*LQuXp^{Ulmaqvkv7N>Mc=ncB3h$Zq+VX!%d` zm1&LqkM4?f2aXHH?tQ%y)}%an_5Qk5*SBBK-kWl`jd#`Lg}2LIU-aF3Wp&v4NgM7a zuBu)5{Gp=jYp3N${o@uov1VS~HC5z9{DXCE?0edHK3upE5V^Uk_f=cQiHh!vCqI6F zq+PrAdG@X2lXEhUtM@$@dvA5??!xBw6xRz}k=sgUW-V%1c4vVjvu5b3DRpXgxqlwj z^mkS5ULSLD&g-kI!@WHUIZH3hW>X+h`Uv30`)mpq&)q9rDEVFE_+}qnj_f~|S(Bix+vg$L>i$y;! z-DI03^E=}A(p$5qqp(_Z5G?-e13Z-~COg-YbKb_obYl_t){isWO%|$Ai!PD0?St^Lfwu+}Yb!bsEd< zoNv~icWq-+-|qbXc4ucL+7zyPVSQ_{JO9dvjf?8UUUU4YHu~Zm*7{<{qd1$gH#4%H z{4lJ$*^jYgTDRIdKI_x`Pq0FmJWv}0}?Dy-g%hydGCA8$tul1Q^()sLa`nf5Q>tgq+ z&EB4KE!)%o-khC9ukJWD|KdGz{kr+JuezYxI#J@7eE;V&Wv|X?t_|Iub92#F)7QL} zY+h5XrrMSN68ShW#k0cmcXwi>h%)7yuN>)2imW`E+Wg9E4jb)`}Ezb|d<=?8HoGujyL4N4-VD|LfoT(84M7>Z8vL1IM&8GZZb0o=kXm zclT<(cE8SNZe|=-Z$3Re9h#gRUHIr2xLI1+{cIKYV#!B;-IhP8DdeeGHB;DP!~ceB zc~2IUzrPr}Ds1Jdx}uV_S9?FyK3ui@G2^q^l+p$5j}!Ic*6et-`rU)A8B^xhew)c7 zV-c{PvzWF1_wD;j+wjS6&Z4DX{%_p>t;F^F+gn>#*Zh1sy}UH!oZ!CaY3_l)7M?a@{49q4!^R`xmq)7 z%Zhu>Z}e~9*-+Sg&N$`73`f2AJv!au`qONyzpc0zyUQo@>c#k~m#SZ9y0=!Fl@zb& zku?r`c7DEo;p3xMEp@(W_Ls~3t={r&qO!Y}heyXV2}A!2YooXCwkw<$IDk8|aCoF8Tx_@7mbiVPB6N5N#~_^P({JxLAO# z!&Z;~UjM$QNCh8W(EPD=dC9pwmPTn`ByMh~Yfdw}vO3=1s{EbK(Jry#^@;a(C|Z}j z3$V@p_2uO%-$@@YEXfqkyt-=YugKW@%V+9duMgi__;=S=qwHrok(FxaeYo)Y*>HqFmpPsu|mQU6wWb;|eYhM4R zhO{sKuC_0v#H~nQ#&)947tP7bPyDI;Z2DO_xveK?uUl#5=J&H-m8b8{*dz0Nie_-i zxi^-tj=KI|^CCQOSLxejzkRMbmpt&6v(8(?BW>nmd}C+bi#;z^^Dpk)tiSyHoNH@x zzl2@m&$+)V_FK#Qi`g^HVx#72pPaA1|A*N3t2|sL5qn-WM!ku zODVSTPx=e?S*)-9{Ux-1Pxdym>+i0-44$R``R?}nFEvT^bh?P$MAYMxc!Wj^iZ1oE( zxWzSf=313bTIM@zmA|!C#@mcTckcJ_-t+gn2SU8r9vY_^b2m zwvc+seC8)lKIGrrUex_jku1Px|}o>sJ}0 z`X@HZ8_xzVcJrKXSNp~IL{g$1@7eipp`$S8*K56;J-!EXI3(-%g6&%3n7)A-~p z)z#6qqPaRLr5!ate@=gO{i&&4YweS(^VY9g=APG{Jx^w<=uNeZZ=2K3OzM?3&)Qeg zJ3Z?~cw-H#it8tl^1o*qmf2)JQu)gNSliY7&+q&H*HzwI7xiUFJ`jC>e|^1X{JuT^=G8v?qZ79) z;_sdxXIK8e;86YT&C0ruGi=soyqay6KdE!F+Nni9yF;>{*FJHvS)ukWWrGfHjFzLL zLtYA{rOpM(&N0T;=_M_Ig5yEYa$mvpIFM=<6Pwa z?lphqZ<+QroD&}&ZhO7MA^54pqRU4t|F6mZ@u*w>3j4h+nZdQOSHAKDDt>SK^HEUQ z?ZmR)*(URsBv0?Vw8_=`Bxs~-)owZGANL9*O$sLX%(V*rYgiE%SO2&)R@`B}$Cl@{ zg1=1`?~R#Rv}$s(tz`B8zvt^yKTbMYCA05njj8q0#OAgtf0w5p9v=QQ|NkF%w|=>` z#aw3!_x^sjdzV@BNB(ROj$jB{i|Cn|K^phTz7ri8_8$O+xX?zJ(j$? zCwY0_rB$igA5T3kEx%LzFKkWB!eSQl{5w-tU0vn%a?(=M|M%}!D2BK8R9(wla5{W# z)Yo%6_Sdd=`+M_1W%A!sZNAba`?9b1#lHHRcVorEw3EgAt!}5kG1`CR{2YG!KLOhh ze_Y(YJ@c+x|9QyZRmHD>*_*GKYFK#emHhqf-Q`*9JSVFKEh~}ys`uf~%P%XG@&)3r zoq1`zRqjai)g6V&Z?#2ZYu{fZ}JA8t&#+wiRC+S^qtCvDx3 z``qm6jk=kiy3;a0?Bl=p-{Ibi&uzb4Vi)E)&XzW*n6R(^`-St6C1txi8T zQ?r?kXVTZ~>#M`u=5fxF+iUyrjoaB(Wk&NZmdKv%lUf) z${u!pt=b<|CGQv7<+?vE|FqTq@B8JyqP`@*GBMina&d>c^jZG9Mz5^wYPM!yUmKeL z>5{5<=zcf-r#1_I7rvV_r}KjD!d3VG8vPW%>cK6hv*KS^*5MgntkrkR*0cW7lCq7` zsr$+v8+^jebF4*B8H2e$2G~OL%~onVvn-xB@05-^zsLVC+t;h@ zZ}a*ZuW#~Qr#Z_a+wP=ra|4;NDPSt9j8I)Bf? z-&<2o3f+|77;pRF#lw_FgZ~cuEFSN=U;WqQ_?*uNEZ$z-Jw0S~kni*QMNa#E{(iq- zKlxbC#jQMNTuW!QoDM{e5|p&(vN^o)GBFW|e%?boQLbA@_g2{cKTkBjD>? zV>OHVUMcfkw}lVvv@3pg=3-?N8?Us-%S%g3ds&Jj*6pqM8g2 zEveQ0oMK)6_KKyYQO}I{N6$r{bM)H3GTr~}wrMTz_pd!KjZL~Y6-_;LX z-=5b34Wk?IJnlalDerOY-j0utOWrEZlYW(O%{yrEPP^=Y^_S#d{eHji`uls8dzMCi zPP??B&N{}U?6bum!_QhO6tn!DB-L(OxPI@iS-%(-eKwkW)HdaXz)X|ONitm) zCF=P*%XC4b>Q}oLzuLQM`ovxtAthmTpAdfCs;J&srXk;5(g+fyf+qWAFsH6DqLf|B>$dycS^6H>Fb`Zw`#fQ-olHA zTyI5-;b94@a?n+Az1r@p!b;*|T#FUP|>&J-$u0YG3lDBa+WwUt52o=dhrxxB*u-xb+_xru$nyLS!eL;Eg zU9FHc3!blx+G;Ij6=j*NI^*@is41={$TMz z$McxV{^k07=i6+GUD&riy^ zua>M_)wyu#B<%}pGL6@2-bs}S*eqjF;ZS_g{l87r=8m7~|C;&j3RZV6?p^rt>|Fcs z(g$Z}n`Nt6)M`eXly-{JUq{>38~Wp0*l+JDh|ZtWrSo@ae(b`=*A zzAoG>HsN0D6YJwk@)wt`i`yMldg%VTzso*LE%llfRQo@%$k$@oV)ec(`+!fD7V=+$ zpGXzQS;Q5ko)A91->1y#t9n#Q$>XQ}O@*${EI;c6*UwxvEB%|y&G$Y1X=kt6pQ(GO zshHk+{o?#~nf^d!_m%wiR=zRD+xX>!_SYmNEI7B?pv}bF<(;itN$fNIX*$u1b`^g( zm2mb{{*@&YOERuI)^Pp2WBz>c=fH{Wsb_W=TK#vd_qgV3aKBm1XTRUR$h^iHBU@S^KRMJpSs* z>m615UhX~}BUxCWg}%Swd?WG=cPH? zpE8#C%ry#4J2ykK`p~xwHj&?6`GK3%ZNJVu39fP&UbZQ zL&ci=Rljww9@)Eh&*IwotJV7M%~dHBs{FpU{OQ&3_`Uk{T-P`%PX2Bku1ah+v6T*w!jYi8UGXaABc6^Gr9hVtwSE? zanE(bX^#?Y+JX?se_)We_OA24 z#&zrN>)N<*d*)d&B@0eIT6^@juYZt9WKr0^Z_niV>*IVDKR9ZfX zIq~*YU#-jOrR?f^RZa$%|H}V2@m}G#{x#Dri=VGJ-m-66#+@JYtxH}kxIVwwi;d^; zoSxEW+pO_V$&2zGTkYNKtk7w(*7Qa?UFZrK4Tjz6cLh#T51s+uor@w_MhU9ibZ7Jan~ zb3V(h|1x1wYq!@WmGA2=7Mv5leqrYSTN~<{t8#Xz&zPNgXUWES#_Q+A8CGRqc>Hn2 z{||@xtLFUq^I+Ham$%)Yx4dZmsc>ED?%ZORX}`KewM*h7&O64(e>%4KboO)GC-(~S zHloJmWH>s9%UrW7``S;h?;C>gMuS*^)E($+0V`K6bef9Gxx=~wqycYd_B&HBL zN>jYx{NsJhzqg1fR?oI9yDzlw(>?oplV_P`ANvtkb3Xgpx``JTyS=_+_seu9f9$T3 zi}$7k8aH2Da-rq9{tSKlZ~p_o?)Q;2Ub(GT-Zp+;O`fU27ju)fiHF-yzL~js>o>*w zbJnnbvELFN-e2)yRf6P)#|)f&Tw#0HAM-YSa#e1<*T$rya@OV%zvJ)Sn_pl5DgW#9 zpxvUHK`wSbzpDrBi~0Hc8RMcNg+~oOvy41zzb5WJWb%2ITzkgLIo&H}S;&R&IrhYA z^6Z}PyDCpVyR^+WS~Fz9h1z1#jJbRG`0Mtte7qvxIBk~A%fD7{9yj!zv`qMap>wA2 z!N=YDf6u%$7BY{EIeSqdcxlGQMXQ`Qy)z756;h>p=jUyC@w3eu_sq?{%(JNdJ#U76yxq?q!e>`H=0E>@bH7#T z>lZVU@)Wat&;L-6pZ#n9|L=cG?JuW$tp6@3RX@ulb5SkZgS{2YPo7Z^&&dA~H`o2q zttpz}Zl7CUWPAFbesQmVx~+vu1RI}3#dnLDx2xW6y>7BxeOa}_tBu9$H@$1HWdBm| zjQ@oB@yG9HnZG+QOYE8EGM|}B_Wge%k1OtcY?^)birn@;Hp=d4|L^_X#n)Q%#U%5x z$Ihas@75%rm=Kf+ zex3yN&5qV|-`#9BA*l1U)BgjE%xoFc%0G#meE(x!zWnydzu!D~l6iT$+M|G$yzPE( zt!^2A?Em6E;r!V;H@VI$f69J^PRbSDX6@6l=@`4en6;^Hw&Y0z#p7)8`zLSzr?SP< zDDJ}J>FZC+kG$gXKH1>h zSw9t@b)C4mf3~l@s`Q-mkLIb0*WA*-9HOpvd2aHQ_#an;4`mzH^J|FwIg{x$3R(fbpE&*xmspY-;7 z#n$#Kbt||1s=V9S=W*7}?#O{gX4Q<;3G>oRj@adY2|Rml>vM&D?Kd~4zkYpknnF0+ z{_5p@bGO`IG`V@rPDS_rRb}0No^>q8z2Z+Uf7t5UpC*6e=)w7`|9WnJAMoGeFVD;T zSxTu~Uq2Y7AE*m_zi6tu_beadO^=WCDi_98e0ja7QfmA8_qV=ghepR49uax^&W-a)4w*)DMo+K(>cQL;_ZGP`6#@q(YXHNVt4+p zFLu1nKlz!f*c!BOEOK*NrknY{cjscQUe~@~r{3^7y?9Q_rDA&-s|t@#&(G^m)egUw zK7Yl`mwD?yw{ja*pUZjqKe_(qzTDk?g`28QP19Wc{`sG!UUR+HE5>V1ULGR*C-Zx) zDWpNQ==qtQ#eM0J6qS@uPrU1cvUjTzA*m z*%f`-$j&df<{sy@f2<+=6a3~{W$N+PC8=}Ii|c;Ty@&0+&8=deTaV-!e;@jp7PBDw z-R=GUpF=+EkhiG`_#_^5n7++yG33u_k|<-9PM zX_`Fko%hi$(WSn(&0aMw>sO1~F!&)=V{NbJ>$%Pl`HSsH)gu%z%8-KU?q zpXe)yYJ~*UTb$Q<_p8$CHRl{lqdK{ouV2G=9TVf-Q@HuqtE1_%9P`gt9=UzKyu3E< zX5Y)l;CWmNi?5dspP1@bD-?WJ__CRN`M!B?gVb$vldRvdr~3bp`{XV+8=3O%-tgQKR(f#7DWLen>j}`vUc>nRyvEa4SqIA>G&G}wgC~L2?%dVJjb@Yah>M#AOxXOKz@M72ZclHJwhn|>aS@&kgIaLGp zpcMs*Yis}h{bO4HC$O~U>Jk0;NoS+YvwdxfZ~54of9YMK_N=O?HtYJT+V3@=)7QLmG_V(7&dli2krd+)6ecHU`>+Y4s_5V9x@$gTPUE|}2 z^L~7}?Em$Kar#M}+*?~O{$!{+f9x4+(pV8(J<})SW^`U#URo*j$Qr|^$zv0WWDpFp_TQBu*a$3wJ^OI3$&&_>b z(f{F4g%ET>dU}JJd)W5{2b)vgzS{ce>C>f^N3IB5TpRv)e&MVBxz^=b^9s83b^!SEnRx!I)*j{MVd9=jy z-IeMqo80?kFV+Z^`1i^C*WND6U3xux@11wt3l?8KJY{R+WOe^*rnPnd>Z<0Qo~|pO zYkP9z;@8D}CyzT{U-IAT-w)87Wt+!($7hlk4tr16)h*4sIx)p_Qe{YgY2W`pt)HV7 zPukw=E|EKjN9vsU^?j+`(?DyluP&8my?SJQ%%wm1vD-hK=7|k%ICjQDJ8aR6XP-09 zU;KYod`H%!E2n$ztDT*-qOTsbN>cFS*RNAUG=q;?DIem?K7T#p9kz!*`)YarbJ!$7bH&_t*CEtk+v>kC(lD zeCji|t!{Iz>#dO~0ObI0;x#gwa;Cr_WFT9Um< z)l%NZm{-!s<=^l7|6lE4ul#q$wqV`OG@r;015s9R8CRxprsm_4;=AaY~S0#0H1!jFbPLs7m^y{={Wd+UAIh zNxyi+q|0s9wr4wUGG193x&8FMhssL9b7tL|Y~Xtbls9aci#*l*=B&7RBgKBP{JxLJ zq=VK*ZOwT8Z0;G>J@dZ2I6S{$`lLCVoMw ziK#~9`7d8mc0Y+*!2Gz~O+7u{c5OdTLEgtdpK2WMdhuCD8l~)ie|xw8D)x};mQ637 zxg|A!?y0XjzD{-*U*fALE34{)mU(F|^`3q$ck;|hn#s#{pO;-X%i_GcY1Xw1G1>Ey zXUHpAv%EFgmM$85UO+}CzV7GJb-@c{)&45oF3-?^dTPq$J0DkL?&O{<{X`QZOP1UB9DHlcg%MyNl;+ z&$~A%>+0&4Rs5SeE6Oh3ne_i|_c^=byC2*2W4DETU+OVY>6bBceZ`gQRu+}dwVT3T z?44m;?RPffk>#YR7_OP?DjqMpDQbTBhj5pxM^`?5q5bap^YZ2Wp66mF?RTjADzxL;{iyN{VMWi+ z?Y6!BvE{-41BZLgw?5~Y$1QjDbkp@`Z@1qM>pyV0<;?E-Kab^u_Eda4UiD6)`t$Al zeOK#(Wth)5+sN8MCTv0#mvkFMM@t?Q7=L4K}{8g#-#E z#VgLOye$0T&(6=Y*#Et&e&6Mt}2}i-{*V}_I}rYW4)wcO5cLj6SrUb z{B_=~*+F^X!YQ^3L>IF@GIxzvemrN-`<*Q3~`Q@&B6;1gwLHXS*+b0d>vnpG@->dbXrXRg7c~Z`|?f?Ew6VV9?0FA4i z=eKb`(kmYRHRadAN9C_B>}(EM72vt|;<|!$5xajK6^~z$Kj$YyRqvy_<(q;_?mc`J zI@2t9mR$OccLrBaM{mhdJR5Cx{rL=S@%0&gJjY+&;g89FHffqpoDyid^{dp6!*^5J zEDhR^6>ENW1WjL@nJvX=`en|BXAN7W>}&ov|5`VrJ|V8RlE3Ke*Sg;7_j^y=Na$tS z>#|c`Sk-UI^O@Dp9Bn+nP0>GF3tw4YD`Q*F6IRc9-t&rzpBbm^*_X;Lb;(P+rf%W8 zB(qK8kJ**HFE?fyrFOk~l<{EA+RIzJ|5yKC?48 zH!GfqIrja*I<+Oo9J!TeGy1PtoLm0tj;HB8+v@Kb^{!vizuetD>)}=HSJDz69y6Sk zO_aZ|@_yxW*|Qw?MRs{!TN9_OIcaIYeAj({eunI~Dfuzs+1j3em0NP|?~C2uF6Q_D z$f;26)#p}LYHa`i`|Yp%sMm`wKW10VZ;jKH;jc@qIr`*)#VpIu41eoi=qDy7?uy+b znXzik$?mFsD;h7>l)t^V^fT}2X?mAGyT|*UoBmCy$MwH!{gLpdWuAVlzdOqAtf@4< zDtz(Bi7zVx7q>mLx9^+xN2g%V?jHVgOLzb4;^!_c`2X*(X?V+L_xjLdl0RRs`>FoU za*@`+4;@1x5}qtKfk=)n&&we4mj?rUlX0m*ICJ^-aIF}^vjRH z*!Kr)9nP6Qo>(J#ZTcJg4e`%cYK5&>@!j-x;`|S*itX9-_^13ReC)lq>Z{3nm0e#2 z8{E$S^?k?v+UZ2msp;zT-$q=UGpmm@O7;CRSQhop@xblB z@9Y0ZpErNbDbE(y-T&`v;Fi71?mS%8$!uEm{oP$tf8$*?7t&iZ!8>L?<~VLXn(x{7 zVZ*}1DWNB{Vw2nc?+Se#X7#>btY=-DSlPQnmRAp4*miwgthV59WanyPeRyU4hb+*Rfz3xQPPyo_QrWuv<(gTG ztIW^EPw=Xn8j@UAwDYG;mF}hV)PH||&Z_je+vXR3aDCIODUz4dul!xApZsK^$Jae_ zJr*ne#ceUY=3G=$@${xz-JK7$4_~EASXZribveak!du^Zdn1K8Uu&rmL<8)EiX3 z>yHlqFZy8DhIfqlw#k!t4zlq|d*rRZ^ZjdF&#KPJ7oFF87+GA{B-#D$SM;vK7c)LC zJ3q%Txc1taw-fRY-(fBGU$a^_Zq1L_|K`ahhmY}ox|u%zRk4%gLLnzGlrdsB1dM`Sk4caI3OcD=N)iURtu-+WqK`W4n9j&)K?8yngSB z;^;fadydBI|6MijtI$y|k6l|{e%bS2X1ZMG9*<2$GuoXd_q~FFdE?toy_;tZ=kuMjEPuYF`<9W^6%Gy3X;{BQX#rvy* z-t7bLkv=b%9xLTho@R&{*etY%)m z?)U3U&nG%Ivzo5%>PM{M40H(THke%C33Y{ z>MN16tB*bI-1j#AXnbk3k=TWni`!0Q-rJHmIqP_e(Sr30{TH7N;y?Cet4;mCJN{`&eVae3Rh8H$TTzN}txv--!Y#m~x* zuv~A?naC-u_M+y{zuMnljW6b9?+x)T4Jf&G{O!+w;Y_}Be$6Un?cx3Pe}UoR{N3}E z-G$%Z+`Rms?9LmvUatt5S$!-x=YnvDk8I5~NA2b(pO&7EI$oSBasQ~dSh&2s)yBz( zo%UZW6h3xx#l*!audl6LH8*(s<~D{}ORGcQT3*U>s5;pI%6E4iZwj$K| zw`|J!S+VcyA?v5gEnYi6KR53+bl;=I_GS9cS4ns^S9iC@8{WM7TxWiy*=;M^Uv9vdOzOXH2=z3{>Pk&(rdOZ z;eY&L;o+<5=hCOHkBBSg_^bWf`_`3r#mnc1Uzl}rmSg(5n5CPl=Dv)5d5-_g&)6*) z6KnpQJU(fELfzHana>|uw$`oZ=gJPNyf)J&b(2o)o{)7h`xZq`{IUHe`?JCeH?~e+ za%bh+ll;rwRc@-iDQ;w9HTmCiN3gu|K3}^sf41Mh4T^_Dgw@$OY^8ibi1^NI$l*2)8n3Yg2!LZv99{?Dd*5Gq4cvK4>z2*Uy#+bs>l|llEuMI}`7k`Je&BudlCV zPm`ZzA(#J2>cYBHd!O zy)AoZdG(?19uGD-to<*UUa|6H`s-V58sC?ETe+uJFYnHtg^xu}*jouzy8Qi;vN~W= zv3_y9;q{|2qQyS%-Z7umu`G2e-nTvX=Cb2wZTP<%zJF}-G1YpPeX)CreBpi@ub1bI z(=R5uZoRLWts8TG;kV4aHJ+ez2&#VU+xz>9bp7jRx?g7$=TF{v#J0nK&Q>Ow$v-!N zJC_~2Z+BMio|dF58<{I@mUH2LaCYG1iPgUR7@Fr(@p9tJEP}8j_2U#`lTQxESL4leBYegezg_<5OVAPRS6^Jy zt1}8~`d8jNxY_R+)B9BGD-+ID%ezc2e-&8bzOT6FkL3I0=$z){uK5c4s?zTstX`RZ zvS)@>>Z-iODJv&k+U_6!wLO5{`tOT_H{GAt*skiI{a0mr&8;n&Mpb7rzFxZAJ$IiC z|7*+oxCd4SVL$wIWiCq;{?d4O`{C9a+gHY2lk4C9SUC5d^Tn4RdlbJ^KetQXv*7Wg z#J)_Q;+Q9A9)C}hKKFdX`*+WZBC-#D`%zugbm8^f>N)$LZ?2qg9CtTY{nbyW`2A&H z5B5#|-1zQXogLR3_d_n6rF{y!=3AbTzPqE&`T181y}Gx1uD`r}YOky*J9Gh-jZ5V*>FOaI{et|uGccm|`I7(f~UGO?C)|Rz`*~z@!E1+P)5}%1dzqvNneMsEvYIsm8 z=-MN+bG)^()T*5M;TJ!9Se`<_g{ucJ;2|eQ$H`(#m4>%zImQt~*+Nsq)^B%9Z<1 zUghB8ob=&C!P>3bQ`Rf&+*`DI|B){RkXq>Qk7UPvOV)n}Eo7an=6C7W94ncA9^25k z+NYs!6@{<P% ziN|x@ca^+VS{uE6+Lp}AcAxD22}1jj$L6zM^Q`-P*4(J_Q_9!mfXkq%q@`X@wW4<0 zX4XorXRoah(~s1-U7mAYC!@-~s=9Kv9C$pkEm6W>@YB0#?0VBdb0w*NG;S)m=mgsE`|BKNbo>3E$FiCe);B!+e3b2H5GJcWHI(Fp&LoqubO=f0o6q$77EEWB2GC9L+> zH^KP$__LaIi{@8;p7!dUqod=k&4T=0^{MqI=W1`i)(J^uZHYFv6>150pEWcxZ`m%8 z?QwDM$J*;_LW6geyi~fnDs1=d*&T7F+1J-!jhgrG?bFlK!tZ~cd@lM(ylvtkmb00a zv!0xt9bT;RQu>#L-ACWqW+yu)DyJO!VI5_5Z+?RmpCAXohSum z_ns-f(&nDWd?c4)^Upj8?$XwjQ(*DBAeiM6f z_48{{?>y7Dfct`p5^aLk%g@i5_Vo1h?D!K4raHblt0o;|ENWdE^w+d>)se8IgQXmivWsq-eSUW4@@L0s7M9cB-r7Dn#Rj;=qW4` z^Z540mA$*Ax%gPmq?wn~y`DVu(2QBKq2$E{$Gw6xjZ^DX=FZ9yx%P9SamCL|sb71R z_)U(2ZvUJn>ZpB1IBsK%t7h1m8Q0pUO;3V)?>t-0!-?)nsUH>`oE0e~DY??Lc2&sA zE82ec?lvc{e0^AbIMww5SEs!FzANiue@~n*`R`TC-m=hVXJ@Ow|6U#cJICm_!!e)Z z=VX^U?qz$mwx4s4tBwD}y-w3Cp3C&wl)t+(tN7-sRBg{`Ix~;ky3d3xi)d4K?ydg# z$n`AGoBR9sv$V6UPK({=RQd8-k$J5AOf%nG?yEMwP!txEQ)@iUoO=A5?5g_ftD?Qn z&9~RTy)EzZubcZP?f)V2>En(+*3e?3LT+cp%SC7A8i(7Sv{9a5+{b=Xd;9cnMMw1g zWaULcJ)ZvdO4Z5zWR0h(o%2l_xJXe+8w%V^C$t@^qt4CRdUwXo!rk; zzQ4O`RR6AKrdjT-yKTwM(G;@8l`Skni{nY#SYK_v)NJyGyO_8yyiTH2h zIY~t*z}BJa+pCrHB&)KI`3uA|tzzv6*VFeDxc|8%(w`x-qWnglq01ugTDJp0>C z`TNI@6PI{SvfEJS>-MulPG9}U9arZ?=F416q@GR(hnLRoMTy> z0xHX@&Svc_`gzXS>E55prIDM{f)wf*Ys*f|R9?R4%O&qgYQD45_nwwJJ9Be-%GFt+ zpYCqIfAZCYtFr z-)7IV%l*ZEZNo{A$c;s?C-US(-S)iO@Jj20&V`)vH#ZjU zRdnx{({)$sU$I^-^U{(@_Vsn3lRln&JExm^ddk$KeMhf2=eh8ok4)M8|H6Ovncq&E zSPB$6{B^6n|3w4h*@{$Y5C7-XI{dCs+{)whaZk5DEEkSFeOe>cj*Pb>1P*t4& z5ok4Q!+UD7_jLV}7Z$|x8~f+W%geI@`~EY=&iVIt zUes<$NYXm?neROJm(rMxNv$=1zh2*zc$n?2V@r5j)V_{@y0ebF*RL3JU~;PRa;-l z-MxMV>OOG06Eqd}&*y@6IH#Zd7PS}S^75b zw3zPE)2F?K_RaVpDeLbl^;6S0{oIx3dyn-> zdrwyLRVjaW=T`m8Rtx%t#@_tJnL$|RUs>td}oVyAW9%)Xt=o4U9;HFs#Q&}nLVarwP@`#GDXjUG((_w@VKmp?i8 z|KHPluWSF;fB(I^?CmX6#smImY_7)at@^rqzAC7yw<>+LqU`OhZ`T=CO+P(dKl}c^ zTC0Kw4P9Mb6*7x&8Lba~mR?Y>VbS8nq5=W|H``el7#e~^#Km8~*tmGszk4NTXPf&U z@0Sk`37Iml?px+v@#6VRf0%Rf9d6Fp&mX_1BCz`Vo2!Rhxwn?S4%=D1L;Kl2iKAaS z13y1I`}E<)=K?oU%I&4SbY<_G5Gt*gCTR9HB1`}XZ``44_=e){@x^v!mz2WqM5>Dr2lj@j4N zY~;Oo`t<5e{G1x%pLdl!I>Pz$_wUzFr^knZmf-)Mz`(!|z_!eAP2A?F&1q+Yf|4e& z@yadnoUFFext*_Q<>R26?cr}{gv^;gfBoOz-?D$&PuDio47|7RUe@((bN^az>hJH* zebmk`f9<+v{OeoW?W4BlEtUKJZA0uG`vdpa)vkG!@ra>L>)FevmzH{;vYNm2%a;;R z%Re(S^VGfxx!1dP@7i_i`Kb>d3btll^~#Of9vBcX;m(~qTE8zaPPzE=^K;YWV?4iq z^!4_JMnpuU$_oYPv9hv8?J8OM_s(JK_j{7#r-OX(HFjr_Yv%nWFaN%LpZz=h_SYYe z`?D`BaLkgpwP6$g+9=~#8&lm-&)t)!lv(&b-+WH{f6~6J+TVxo-i^(Bm$ynj=zd&v z#=SK=K}Xuj=g-gjd^2&DMZ5)XwJRv4 zI?Bzhjf)?Z?N*Z_{5kygIQb?d%-O zVC}Fq3p$w@7($en*~{1$#(Xq>oO`%7?^SWu^>uS?Y;CoFUsz>Y9CvojnKQ*Rt!kfb z*>okgxBJDf`Rx=rGg9h8eM1|M+#)_fS*_oC3>wUrkDN^x zIh$O0sD(4@;v!dY@Gk4D|8S5!YFmz^uM7jj0x84XhY6<~bz`@M91ZXKdZlIgl?9H? zSy$6nubQ;?;X0A{i&r15F1xoN@!Z;(;(2LHW{AaIO>d9q_my#QHJ)#8Kc&h;J8a#B zQ=;0TArVVv%#h%fv~nrGSGhb^Id7i**)y7-tENtxw1~A^?8RI2``d~`-0Y2_`1>j@ z#ATbDU(2vcZ+dm%; zOIZ{wcy)F4@p%#sqHe}LO;dB^6CNx=mNQ@(5+^YCw) zhx-?IGOzI1S-CR`v^M74jFr98X1BK9QPzkXG&ztpSO4au_YY#LWklv>^ z^XKEVf756F-kN@1&NTPhm35-^Z#EvkvdQ)I?HYfEDWbkIevZQI3=Avc&g8sSmUQ2e z_t)y_)2Eu7vX}g=sVbe5+k3lTjcxo>`OB7a5YZ`MD?t-ohM>gnk(&%89wy1Hws zob2ZnZgwU?y0f-FDCJ$z1P{}z6XPeW4_@wnbK8W;bCatb5&{++I&?@xMkYu4NMkem zmcq+!bFC`9oZERqQ?`5T+-c}8ljTX<4DUt%gQbG;^+UWxSKa`e!G>ElCor8N43*N=A_X5b$^5M7cW@g zFu&$k=cC7uw`M+8tE{S8Rs8&1RoW|KDGBR|+e&fu{heGg1Y{%74D@-?uI| zdYh)Y`tg6&mswt2TfMrWfuXXh^49rf<^8Ynu6MMzx1YXycJHKqnX8<>G6&WgecpR! zpBQLEvbO&Ir1&c{ z@o@2<6~9-+?k?++m011n@9)*Qv$vJ`$`%-BJStGSoN-o%|MQ$kv1gT6-@MF_dh_*~ z;_UX$ooltj*VSx4f4JT#{_(3E1`@aoFSs;R#%7(;Ak!Ad048Ot`OpO^ca{LcQ%QSo?8Q+ zred1iw4Jq||CjEbk(_^L$HrUR^Xt8@hnzLkkKGqyoPK7@Z`;|QWhEq5B=YlJUg9~q zB>eX7Cr?AGPV4Ra_1@O#--mX4jYPjDTRY?8rT#whw%=|fckMI3_3tOc3M)irN~rQK z^V=4*&+pi>-zcyyBwu{e(>;}XB4?MdfT-2>X+AZ&t8|c zEepB4%y)C`-9MHy*zT>(Ht(%3+LM%={PvCkLnu2un^^fA*4z=Y;Pdly+UDlhx5;g0 zyLkNi@iNBC$v)Rts#aN?YFFc1ZkRpgtW}|LbMoQ+W*LXucyH~lUcX5{<#y=_RiEtM z7a|M){r$DNc=@@q-W@k5AGBFt_g`x9Ox~hjUow|2S)!3yJ}GQ%)Y2_iOiXich1gbo zyKpzKe6@2sU)kJ>%5M!Ox+hIkFCRTy{P%6rw}Ub!858E!|Et{Xw{MSL?5-s*FE4++ zxBUL)>+Sot^9 zk&CU#Cq-6PR@5}ia7D(X&|>1>Ilg(@`j*IFJjN?+n*Ywmx?9WI`uFb2ySz@)FB%j1 zGtMkdzGAp&@!YqGRo{B;ij$*u-@Klf|0!o&a)(vU4YQin_?8>--v08mr-$e4 zY!N3LrY%>qTe>oMxz>)j zf|>cRfBW7sc>R5Te(ZAbsq)3U{#%%-`0H#awf+U$0JJ~+RP@7vhvfnk72+0-hTa&+@F1e`Ebthz4v0?uD-rb z>wVI^*yMesuftqR`!C%MEWf?=*> zx0vl6gXiBsXRY6>dae8P$&-)_;qubb(9h4#npS>F>6J7-cCHaUwihomxc_R|U7hHC zKJWMbo+l(M{5GbLpP#?9_suH9TW3=B5hInKG@5v;`pPKJxs4Bwg=Y6jN-|9yXJ z%15EO7KKh*v#w9tKYu?PzucPn|NlJi>gbrz-F><|K3PsFGBR?Oef_>~Z*DGLKEE>R z?X7LQAKv-+$w2qd-SYceV>PX^#_tpx|2s{8)_`EzA!cDU`&CzHE+dqW)@ z9Cr2#I~-lyc~~>!5d#B*!&ygRci*IIis@;oSx-+*EnE9zUF`0VkdTzy+0)m>n*2NY zu`1yN^S0;HO!6;RPyVKo`S@Ays=sgh1^N2|Djt8}vemnM1a$t*?Wt$pOuW5xN$36_ zkGjkDU;JeB`i{7MTu$_%TU)bph0U`MyZ6d1)eK&?!u7LQQMq=l?5@m5v$y43ivRyB zTsLxuOX;gCfz52ZSLz+=t<6=9jDqa$**&%MV-W3E<692yuQ8ai`^uR1=HBu2oMl_R zEo@ChVtVZiJvk|e+w)rrrJasb25;$H~XvRz39-oGbDmeq;93 zv%d>2KmY#jZg&6sGQ+bs_dM_K>zmf^|1)~?%iCuU_xEwF6VHja?vt}$RayM}=Kp^uUbu&>&$HdRYe(3(yDNfxnEn5%g@PJ@ z^7a4SZ=d+f{KvH5frD>FR@1JscUtlB_k;46KL~1kc5eRaneu0@Oqbrb<#+bI((AFa zEK(QAN&ISPdd>EK|4uUoEqPe!;1?1Qu;B0S@2?LuGMB~1xSnfd)tdctUf!)OEAO_S zEBQDZlsr;qy*=2>Zd&}zM>l52g>|ClYxmUs{Uv3T(;-*?rqH#lJLKckq}-ePTyJm7 z+x$65PUhbNo4q!n-h0~qsDCy|iaON9%KhbZ{J%@<)|$WG`F`K?JX^u*@1rm!+MZb@KA%&71hSR|ur_y}!9R{p#j)|J%KP{{GE>^*Zy>ij`*`r~Ul&^w*2U z{ab2(mpy&@^yc+8wQ`e-#^>!8gZheZtG~^;`KjQ0!1s4|MK3BgnLaX4nAd%6ef;{& z^*+I$?xk2WFU#G%P3rfJh~AovB~q=XT3^l1=zN_XUwJcbxrhCnyyv@S*P5P3)H z&3tubWz^=X-lC%7E6aSPdu6S!z01zB<37BTeU%)nDx0%xN$2eSx0fti_NsjU@42=4 zycUg>{J);t|G#PtvzVH6) zVu|k@gTUx*ITPELw^x0AwX}1xn%1v-89#six_hjedBGZ31GqqHmc^VNHNGkHEC27# zzi(Ij=i~9HJrx`0YUic(va_(Pa6K&sYW_Uen|pP2y8hM-zvr60mgOrmSAHvwOw;py zcGKssbnW_ib3QCdsyeQrq4A>ax~N`C{Do<2qrbfV|8HwhP|%y7=GkZD<$i9+%{k-C zxJnHkFl}ml>We#>pQg*1FMF;NxyxnqqjXI}!;AaW&F)@1^UVD9(fD8Yr-K@1HMKR` zzYA8gUfveIHZC>&QqJv7zP-}s*E%LDgZeLJb*Fl7l|@C(N;`7?!g9{}w{AW${C+&+ z&W^%YmsXzkeLtDu!MBC5G9)wOQGwAci-K&QdQ)8+Ma6^bMD5Go%$VCNd&?lCxsB%% z_y505v&=G2Sv@r}G7h-3&-3!1^UtzBE;@SZ)R~~~E8a=j=j~avXwj3mZ~rzI&zwDb zHRz)NQ@IYma7U^H0}{z4Xp@_uKcTzgcH*eR8;s|MG)_%~y8>ChvZ( z*|4e`R>Ch|*m?M5#-jskjdRPwAL$)Eemwi)BG*$V&u!%W?qC0J@+^})r|Ek=pZz@X zCOm7`j+=+Cya|5w?%_H+!`ds`^W*Q{{N-2ecYdz@@*}aGQG2tt3QZPz`u6EsMd!8^ z{`2j!Zf;uo>dMN)`<6L~!rHP8moFT7m|{}6AZd7{ja=RMQZx?VoY-XF2LS(61(1t<1+Y#gS!c72Eah zipa{Y-LS!6oioE#7I?YkEZjc%;*rL##AgZbZ*MC$C4E8p(Cx%1nes>AD-xBf-^IqpYJ)~)1u>15 z<7yA$e_3Dm*Z$SDwX+{RdL$ww6m+va^zF>gRZmZe?*3+HZ-4*a<(PVdGdUugkr$W2lNv>V- zE|80dBW0Qe!;~hBM4+jscWvew<6Aol7f+fz`R$o0d~dC9SYBsnkjIF9Ko@%>wo&o`B5e4WrIW4CC}9h;rI zcWbMdxIBFLkc*2e$j`6uo7(%U@9ypvjWLhd$edJqT(*3Jn+(IL4s_3cooV_2v=n1b z|8tE(_eJOCTC3~p>ziiZ^LhI&Yx#x^2C-*$ulUka@_PqpfrXW8$)x@J?X!rLvh^ht7`x1FI{>7y8Y@df5G{$@&`Un&s>wL zcGgWPda~O#Va=$=R#v}~|E0T3x3|=3IT0CT7^|u!Ds+1Oi(UUV>@v!Voi39pa;kOq z|B3d-)9j^x-hExW{P)Z4f4}{G{`qg+y?On+=N@`iJNNDHdz-&M|GKZ@<0Dr_28Iug zfq@f2OZET#`Rp%gQ?WrsO^vPEv%&x0uh;sO-|v<`{e0ej`u6*E(Rq8nUQ5vDWMDX; zKkE;lyj{*WGwbqqQ!+0v^Q@_<*)W}zrKOJl*Qe9^r|;MQ*98qI#nk`(8n^eqD`<57 zgP^a>HgNm@_Jt#f#vmaMu~`;5;PLcr3p)>|fkwLpbW93wfTt*OoQ2!Zg8DWJ5gCs* zfIHPU+SK@FUp&Id;IQGskwk8g5gT}YWy}_LGBY$JEbKfi1~MW+dX`0w8)%gNpp$UB zF35-jW+sI@jF6Q#A1e|G(dt zZrKvDDs;8j8&yWT%lprp-z}NkBVp(i6cp67SLVP}G|xR;a(TJ`=}%8j`wIK}`c7?W zVKFXeDp(9!q;#;E{prf(^Cnfl+o^uzG$R&gz8AOu^T9cCXVKD>w6s%m%kODkk16)u zFrD>>in)3Cr%#_!E-Y{~DLmkg7RUvcma6?bDjq*$^VahFwdTGu>%QJhpFi{4#~+XT zFCSr)zla*zhdoUSZ?vfK{pd#zs70NJ)l3Qx)T5g(>p!%ZeRS;>1Fb7K`#i|W$!Y0(VKFha(A8n4`3@_PQ_mb1;dbAQM+cs6 zX_dDs@z|DsU+?JAqd_;t9P9TkS>p2P^XI2ePENkG(3yQ@^!B`^^?oHKTTHUA`8;~` z$VZ;ti4inz4oy!FRc2Y_I0>`sg-1ncNt@+Nm@`M_=gZ~ueV(t&nZ4k5fADg@nevMl zEwZWd_3-kVRQULqXI9p#miBh`te*|>$mvV{;*mt*Sr!GBw(9GCcj@o{69ihS#LCJV z6c#4-!Cu|cGIG=A%}bMy_klL#Hq_S~5JyU}h|t(I|H9@+yW->aR&AYQU9R__p3PTg zVFxJvLUTm{G(ex;-ch(1bT`kYtgEZEFC7UE3OZ9aN3Acw36%b!xyqtbjc@jaBaNTl z-q`3YrW28{@80{nyRV-K;cQtIy4ouzXHChgE1qq<(rUU!+GL(PfyPjz1UqdcIs@uQ^aj6qu2_v*=gpp-J8?T&)U1w%)$Tu z^Ai)5pGjUgbjS&Gwy8n% zd)}|>`1U?(YnJErb+M}2+NbCEFYHvF0?PUh8kf_}x98kcx?lf)uZ(TgmBl~XX8rjh zd7-I^NmEN}(v~eIo7LC*+}%~Gs;qqYj4g{3Xx(1v^6@A;Cd3l*p{l6MdAD@)-eG^=TVe!A>#?Q~sL8;d$|DMfE%i?7>^M5F7X?e+2 zzcG|FOlr9q{rOg7fHNqD7y9g;f6npekH`I~-`?E(bUS~4>_&TSOUs*E=BxS6x^P5r zQ^q4$TA4cAIK6MCcHN5$iu>*Q&M9A!v&*`o(b?V2ec@HZfrX$lG+=pg04V3I-G0yL ze9^QiQ-0V!-e6-=xP#GG#t#|*Mcrb$lis|^DfZv1Zp?jp@%i*uK8F$yx1ALBw^1y8 zb%pbT7UO?V{5!0;oNoF3?QQj)J9nndU-$W_x3@R*uXGm|7mwH1*3O*UG{GI=b>zNdD+s=*rkzdvCUsbh>N5bI1p1c<_&I(sR5!WF7BIiTt>uV=huivM2zvgrA z&+iVq9`{+F*%$ksaaHW@G6#Dz0S}WxSb{(Ga_8i!+To{ue0;og!-fm5zh5s_{rdX) zbkE6Zp6lcGp4m5Rvl@phC)G85<;IZ*0+as2(w&C7je8oB1}erwkM z?lB9f?ttd-2aXjcYq7x{RZh5e?<1i2hV>R zvoWc4=F&xTZ32vpj8blG$-J~8Q2E>@g(Vk{z=|H5#n1iK{N`jlTk)dq_UyIJ6%{)& zyCWkbFD>;Jf3{2^1r(kQ(l6p-o-Y*<5jg=`tMLs~-qqE|yuH6G{Qd3i>u>Hh&$(g1 zu$pz93_Mdbr1QzyXn+QYpUuvnrME6U*k)<@)z^Dx-Q87c{QPL;S%(#iKr1NBZ*EL( zKQqhJdzyZ{-tm6<@4p|%R=?f)>BC|E(+3)v&wf8{nstTafL5b+yBZ%X2xfAN>z!B^ zyZg-bT3h3HXYYQ?y|rcH^th^%HGPKt0t>;_?H!lrQm8xAO(6uddcby)!*|ZEsK^|>c8_9zJ7jfcwFVtErkkG zz@aev&&T8PpH8aJKe5QQJLU8=-Maf*C1quGlaKeAp07A|?3j_ajAB2+nUZ(4Ui=ZU zeZO|T`LFZ4-mmak8@2VxL3a5moWg1zpP!wTjnI5x4a%(r!nMC-N5tjj^PhEme|I-p$}~&m>Z(xg4_=K2 z7I(sG)QaafHYOX@{wgWn|M%tP<=TJ$zI^#It=}oSMH-v|Zol|fbFhiksQg{b&CTik zbL{KyE$_d)CerxisZ*2mVt09@q@*;2bH+#_-1z=Q?Kk7JGX}nYj&ur(&U3!_T<2>J zs8CFOb!FwG88cpd@M3%q4%ypNrc61ptMqls$45s&`wlO2*v>5caer0VS}jdYO{2m` zE|m`&*)tv$@FEgedCB>|FPG0hRsDXi`s?fK%|C~n5*8Fx^z`(+v_9VcbJ+I0*!FO) zihfYJe#b3(!MntgZ4b}PG)}#}EjMnyXn%M2WWTvqGk2RtZ_ClVx;lKn(`r_xZbaO)6;Z~&xgI5YxlIXw|8pbVz-ko zE-tS8CbSORAkF*w^?Lm5;z##uzt64Qc6s)d>C>jEO;+}>0@HwNd+ z!`$98Tw<%cU;F*!j>5-Fd}o`T@oijYO<;#@jy}Xk?!Lx9aV!txJoa zpED|W;IQ-iy=qk(8ygR8);-|LAaCjOkT2_eZQrl`{_oH4J6@Gr+SS$7Pb>G^D7}37 zvgq?!^ULKAw2)H9OK?<7nm<4Po9t|}++A<3KYsl9>}%)wcC{*MYRBf-Gu~+cM_kVJ zb+MZg4l@0GvABQ9h7B7o?R<3c;>AmQtIJQGIWr~g?5vsA4L5cl_C-`S`=WQ3t?iLC zb~DSlQE>CTx|-Uo&zgIyzo+GK#eggMJ3i?$ukK8F^CoBW{EPMf>$k|KrKHT*wz#_D zKrWIom(z`o_si?s|M_s(K0TmhT18OMB%9A?j4!Q?HlJkyGwO3(Vd2J`-TJY+uH4xg zDQL?dx7<(m<@NRRE!F2unDF3%SL1;N@I3b8-G_&V)8_3kbD2AT(R$XZeM{>9|9d9s z^EW+C{(%}es>;;;=b8A{oSdXu^yV)3{N$9KD4>v8h) z^M4a!Tn{#rcT4m6na0QGh_BCBR`K`O*VGde6rcJ2ws_!%i0At+zdihZzuvrBVD7?2 zn~&Vyp06*g<}*P|H|oPJhU=h;pCS6pT-eX`l#%>OS-50^5}%Q@Ha{q61WM~@yg zZEylL=%JM=iA$CQP|{6713`+dFSV?7h)Y^y+poIp6|4|rWv@!&=Fg`c0FpWWNN zV^@ao^O?O-Xa3T&<6geJw6wOMpdiSS zu&Ai4fBPf8zq`9Me0|)(xW4n?Zim|bf4^4q$lKky^MCR4@Gm_Tr>E(jJzx6jif7jK zb!WflqWH(R=JYgOqwH%spT91s{r&BkUNJ*>`{U#Nr@KV8&sZ)wbLLEf{_%8h7zy89 z{PfwgQ?J+W*PCsYYm^>-YiqW8WMt%|S+k_xJY}qdS6Ffqw~l<}6VLVRl{TNo$jnv{ zCb6UI&HerH%lzhQfjR|(%5E(1P{~lgQhV#dLg&=0t3riDMN^+Gv-$hw^0KE4dGMB? zje(x&$Df~{dtYAWd$!(xmPNtW8{6~e`^>Y6jM|#z3Q8OtitYUJ(;S=GJmcc#nPgr% zGAI7k&CSbKzi(jFTL{bLauOzm4_>)})%&`-x`OIdV`tadJI?uL-rHkYo_&bxpV`O% z4Ek-Ek1FQ8naesS^y;_c(_1_^J<7qL!(%0f-EZ64^DeboT?#^%6z|?uy(@e8!d=zg zKhJkRtABQur@T#a$DNrwH`moYQ|9@8r}&&*_501=%h&&n?w7NzQc(+*_*@^7+d(~1;PwRbgx^q+2j}Hsq z+}j)7#wV*)`RU2UPc<)>PFMQ1$wzH+J9xqI`TBp#N4rEPZ@*Wiy-5H0%A*p`zu&LF z{{2w?{=aILMNc|jcpJ_1QJZ`+rAqDY?sETYYopZ{yY)`8E`R6o{@z~I;%8?BYa`Vr zN0ocx?be>o**2QVkJR!f z85Vv&F=NL`k-e!tcT$XI`Yb!K)HM6riS_&ctuj0Wx)kuznbTk1ERuUL`_LZUxIGnN z@{2aEUskQ*0m2L*uIPZHP zPM~`VRQ#sg_>@1>M=e+c?8YZv$Bs0gnz2LE1|tbAZkwTfXIHIv4gc>`ABB&DHjWg% zdZM|r;^CryGwV;!)?aUue=+9MlXJ=&laFqz0C~7;5h%ILj5#@@B0y5uycOgrlz^?c za$)c9?@!L$G~SePQR(K^;^{HFDm;H$_{^!Uw|saSv^o0at*xt{oSl9B5hx97a)BeG zNHzJ9W2(;`5l|#oq6U{Uznskk?d$6_`0XnnEtz9e8uY&O{k*+JudnHzoM_y>CF`o! zt!BPFv2L|KMcN^K-Hj#a-gMK2JK*DSZ6VdEYq2SKt5s{=T)&ci+Ylyu7^p^qR=cCT+W7einW5TVJk{dTNSbZD!upo14>9 zZ+*!G-7>hd_V>1sl`*cCUZ7*Qe_irf2+Gwd_@c|3=Wpll7|=ngKQ6XEsy-1Ow8TSE zH+pM`{zsjen|GWQPJDiDE~ven+Q$FCPQzEqe4@YIPnS!}e5IE?uH1iTN1^k&`#bbD zCLf;`K55UQdAw@DDHHnp`*|ddT$cIFT=dUbR6A^nUF|QAT_rE~Wc_^x>Y-&^P)OC- z@c-4-)!EkP=31A##Lvz6$xd^u0c~j0@P%uqFR~+|1HdQ&!$7 zTesM~|5VRR&`&&F7v@g+%=BD&KAIZ|Jqx@O!?xvT~`*N1;hd zm0a6n=b!wdV^#ZW%el@M#wLDyVk}?Y+grWkyQ53lLFpatw~PuOP1O#c2D%Oebo>-? zfm+d-e`iY|+kd-=XXoa~!BJ$rC=p6%`<{o?kE^v{ZPfs5U6BQ?2@V@G@+g33|zlQVWy zr}*4S>AGj6CbzZZ`@7hgw${IX@~+-J ze?FZSJhgMjzUuGqP9F6ZPyM{?tWoAAm9wl-OT9$bM&I0=y1j7u$rPhjM{q5xEh)^e zmHcSg2T;mKsWJPllJ;#VzaJ-QRx^X=g}uWg^$vYet*{B_)|XFvb#;|{#Qn8}EBNJK z7$4|P`uyxHs8$7?39aHW!y#%*h9amrW|DcyqeuMCrSQ^#* zD41!TzHW)n)S$}Z-P_(WJ#+Elog?pZXUD%IAAV0%KR&_wIP3rV1K(M?ov+{c@cX+- z-Q4n%hgi8&e|~ye^yGtJr=W6MpXu$b*~=^cPEzw-weLw{XDWZ4eB*lNk9QZ=_RDqO z{I&T1U)vwHJFMD2zptr}IQ`7?y3nQC*5^BS{Nj7oe?I!o?A4n%x|yc0{apUs`fya- zoyDuupT9Cr{F@hkUG&!X_U}8h&sIN)|K4QtTHsY^#&_AM-`s!pzT0vB!E>JeL)G;Q zx4yry&d};4s4m7=p14SQ_FYLCNgyibpc$4^mq??3S_cK6Zi z*TeH-_AgA{6S6Wm^M2f(h(gbaO0B00=N}ILS$E^x&f@1!K0Q5M^!AnM+|@C=N<536 zo?QC)n90gZ8rPrAh%V1NIZ@d?xru_eQe>b0ZlwTYC<<((zt!uiPg^yI;R29_beMH%d97Q2F`!)H#;Lr?fre zCPoU(QmZn~E|(zAk2Bx42%GZI`(HyeS%yPM`|EQ%IGo^!|aZ+1FD(PdmHo zzC!A$DX$J5j%z;f$TDDF#a9*Yi9W}he|~xry#LLC>ra0C3NZh$Yk3~amHhqo>1XBy zo|>YqEO|Ng$}eBb&EFfX3LidV)h)IwfBH#uZ~u*rN!}kH9bM{hkV(iq?@mK;VEDOt z_S)=xaub@_`Ci?+@b>n0)zDKRK}#|OHG`IPsQ6E_ak=;V!~6Cs|JT>nPOh!~{&MGz zvQKOQ@fqHn!m3k*kNdqS|6IF;`FY)3vx1+i>aCy6S|7iE-S?Bm9`hCVPSFhyGg@+f z!FPcjYc!AZzBbQ@=Fm?%uzh9L)>T1^t9k<@ZJ!oDe#UEA`D@9KUq4QLOg_FfC;#4_ zmB$0m?>K*`l`H$cy6JN+_v`PAhHng8$l zIo%}hQiN668;wY#bk2lFGUac67)EYSoBQL(j}wmbn>S@Y*Za%&N;`E_Gsa@D&ZoR7U1wRBFgw6FOPa9-NHE=DtY z*_tU@fnJuHI)ZGwlYjHY3OBs|Sp4-?Xli5l`k1McRJ~8lw!If(SAXL9gq&M@Jh$cC zRH`n2AF9XR?LSLrW!<{CyH%jw$a~wJ+xbpjO7(vF<>lp5!4LPGa$g@4D0X90s&^`A z(3HP4hWC5)rj$+|DI1S|{jfzdj{Tgj5$5#hc)$Fzssq-)9~^A{^tj*t)RU8w=dUwr zbX;=N_ zMd03blhysS^4oL|G(X&V_x=mLokh48S(sh^<=kB@J){ZM=5FK8hD>gw>V@)e)YnwR=26~r!;<(D$?Smrx-*+2J0SDrh}_a|$Y z>;1jQ_tv^aBHRCN!rbih_iSesJ3K!1_uu1R6?$Lf*951Wn&YVzzEbDvs*uYyoc>YS zpTY<>i8^X#?Q^er`uV)w^ho10&1Aj!eS5B~iuHbXZ?|^#^>tS(TmQU$ztL%rd40R) z;nN-5Z~vv0Kh@R@Uc&Q8p2@r|Suc8Sm%d-N@9BoU2adBH zNsHgPNQb}8`HxWzpVe|b0X0~!tPEByUw7wI*75MAK}WqleP6sk_540tqvTsWz2~3GCCn;t zSZA1csO8dzMCX?mHZ~vQS|72`$)0`vl06Sf)BS!MfBEt8k@o5O?{~{h#U%3V5)Lq= zJ~RKnYo(1)+)3LYv(ndBr}D{Kd2|Y?s>I!y@Kg5sA)9UG@9#y$`PGHYuzF*w^C<4Y zoKs!Xbt-4A645(Y6UqHBvc>g^WzlM(~6LyUQrLx7MyODDCVl)$D8Q0`vZTcmAL58oT7|0o}OwpLShY8yx=l-rT>u=Sqvt z7e7Bc)sdO~M#y4f5fm3OrtCmp?|cX_G*@;kdzK2D07x8+ zXDjkSOQeoHxWGHx+2Qm z&L1oSo*5R{M`*kkdNd=x>-VIPRWY8=vqQB)3ngE_Jo4eu#|C!G_oa`r9`6xxk2EQK z%gQYh(#K_f_;uq>h55ff_jbR3 z`8jp(v8&|)?R77|cmI0!Iks2YyzJzW#B-C?{DbTsRG$bx-mL82cV$!Qki#GtFHdKTlwkf#PImq&?vL~mFF9OoxR2W&+HC!ZvR%PYl$7q%YCFwauyig zs;D`zXnW3WrEW2uOYcw5v|cWv8x@jtv_ti9JKyzROv2}8nXcZFanos*dA^?Irso0k z-gKDlNP5a8X;v~rCvH!~ZMXB~Rj*1@J*GQ;cNEy~yE~L6zJLj6wf*K3{-^Lxe|5u*(-&Fs;?(ALZ8{w)u zWa`dK1%47aSsL3=Dtpa>>3w-Y5$~M+1#x>5BDO2=?Q#0ab<6yMn6R41irk6+(!ajC zYGwcQ=H_J=SA}Z7ytuf1T6D=2&=?Tj@s))7+TY)-T(Jwye#JV)(WY8<^#&X7w zQ#yrJuT>sB8LU2at?yj3P_z6yYk0WB+P5EMe_t=~=tuu~!PA`KF}u^&?&Fs-&tCI! zRV$ZBkt93s_omdx#dcLsGE(ovcz1{W`)U9A=~?lX|CUW}-&t?)e_Vd@tf!6PKF$xD zjFz6xkTH$B?H6NtS?R1^7Y*MY?+D&??Fcye)+p|{juMl<|)71 z?XgiQ%B*6IxNcC$Ppx|*AM9(?#B^d7eD*ojot)6yGyUVQhP$7vf5`oj`!98kC-43) z-O5kTE>^sMc6L^~)%0e?yxaSH-FoFzy~T7Via*|?ad%hQrvlDN{~%D=zAwS#rT z_RRQm>ASe+Je!@Tvk&cWJ0G||@j`jt{fiRm*Hk||@)WRloM0;duJIR-bG!c`g$~vF zw_mT9{CEDe#2)9a+%&)zz<{Qtj@nHIUTvKRH=-jLbcBWoU3`|aV9Dco`<2X7lc z-BWcot9NGn&YGqF_ExQZb!lsMxMuJsABXCNdp>F_xm90X6OEzOO6TMqZeaT4rMUmw$VIzmh)pebe%X@8<3f+UVr^Rp$H*&EyGR z1+M8_TN9~lTm9|I@AjL*m(N*qzMt_zgU~oto#CD1&C_p0J<{D7p0xb+m6giAQsxtb zmU?Si^U3_?O+M_N_^0KgQR*cT%fde`-`*Ce)i}f$X0hy6j+1(~C;hzKSFgrk!P{Q* z4m{YW9wTkI^~gz~>9)nke9pe-JYTo^c=V}a3%w6p70yj#=fo$fPVvAvc*`<~Ca z#fD2VFP-u(Y^u^LUI$u^HQ%oG%46&5ZEvE|JJnUUT@|e9-O5~{^0WNbSE=l;;^r`63bmn#4Mt66nFTZ#A%gW28xeYTCpQWF%ocmoVM{s_pVe;`6{YP&a zr(bPvdVRoN)nwaRIm79CTJkdXb$kBF)_45+`ilKw=RK90+JtoluR4X*vSjQx{(S%E zv25>Q|7j+X6KrPNSYI>z#s6ac#-~3f2v^Gp3A@{9zhaqZdnR|r?x08O^!$nM-~A&6 z{O>KQ!JM* zju(i9`^>4guX(beD)jN|(>ARCzCUc2_j(((HTKv12akE(k6%wc^TKdb;bFJb>sOY8 z7OrMpU8Tw?q{30ubBt-erSO58gflNMFP(lZH%j~Wk>7KE7fx-SFyr>W{olgHdgTr8 z2_E@wWw^Yi?RBH&W7fv|EPr%s+r9+t_RBph+I8Rc(e&o30}rm(J^3Lh`R%vCUj9Fa zI+wO)3NiPUa|h{F{#o(I@E^aVVNT1lIG^cybGOa)n`_1TBVzZYb@F%iXx6X$8C+{2 zr0%)K?xriZ_}5!DO-HyNyM8{czyF05_xZW$7e8+8yR@uywnC-Z%KA5r3diQp$gJ_w zSbt%LMJcCW_jJBJdmWqEPIbVTg%)s*r4}X09u;$^bA2T-G3tHo0nEG+e<_%(?L8Pz$=iBG+``0H?wx@1~UDAH$ z^}+{_ShDlXwwqZParTy}Y2Dtct*>_3xkNsC44T&N_07MwXXdez-Ceom*JgKEx4Q>F zdv*D9)^UZ`tW!AeJ$eC$FuIF4gz?Ds{E=FQ5Ii3x7I515{_=Chymg;0&hqicmv$cIq@S6kSX=)}d%54dNhOk(JV9eNYt8Rpl1L4YJAZ0} z-kiyj#_1;(FgB;$-&cD|=Hp-0d!`n`?b{E^Ka41lXn!2KHZ1hsi+^pK%)@2wc7BvG ztC_LM?Nf-F@3as}zKz>|>|&{3KH>l59~bYp|5<0a#^8Jv@2i#V9P@+}pRP=~)qLHu zlA%*xFMi>kW6#+7CYOFpXBXnu zFQqH4A9H2T^ew!PI_6dvJi4v!Ge?1$okt`-KHhV#+SWQYwRw8EyN>U>eeo~*_pN&$ zUUa&5V$xDCueGzbPFdUb?7mD;WJQwHi>zFwJ%_TJ4cQET*tOSOxxOT_JMB|ed-&9Y zLG?SQYhV9UJb#mTQ^l{N-D26b{JouzThG>U*i={WReVi3HRI${V+FR_-+gaE$DN)% z+Vz}2?nCVElBr%(wOA9kdaQqWN;Gm)PUo+h^*@VypS7(C+}!r-?ql=5?_BpRkFwf=0h+3EMr_0v}dFI%PW`LpY(soS2U zpIxuwA9%g0t^K&i=wsu4z7Vx@G3!cKU;7o?Z&7e96xyyt&3`N8-16{Z5mc{e}%p%uD1gGX}? z@AiIAD}ENq>=F0l zP+l9pecrRAB{hev&R^TpTKE0j<|b47{DU@$Hxw)1wzz%>d-nctJO6c4fmb^nD9`%WT+r#?#iZlm*Rnn@TdscsXGE*;V zlZRWM#LAeTPhIr0*KB>Z^33G-8#nTQ{v5pA|K--t#V4Lmcyexb^mp|=lb(oH{&=wP z$+@}F*K0Gh{cN90&b6p?`mOvYDZ*UQZ+1kdf*4(^nz zu&$P#WtOQGX_Ovl$Fscseem>HLsN^-cPfjw?g?KTp~@NWC$WJoP$9mtz}9;&$vae>J+t} zR>f8G?PmHZE$1%%W7e!@rnSFHByBP_Y|^yjmwtD5_jd35PZl5V)8bEG$C|8CANSpS zxA)&&Uro1J{jiyk$x-}o>FH@+`|JLi9Gm{#y>pW4lV0ZvPeLMRAjeipm#!RPw!VmUlulYJCWP+{$b6J`N7jax+>|ss?!I?-R60vqWG7aay`AX1ul>sAPTPc0xE_1OP5S@pJ|B~sXnW8>-8BdGwSa}omq~F zpUJK~_eXNwXPu9AYVRi-emtRl>&@2J*RR;`INx7e(l=MrTkYkYm7Dkcez$w!uZcqS zwJ$y>_NL33r_BK!6Kc!(U|WSNi`@T<;SWwSv@hmKKRah>vD2e%Cnra4OmhAI!%uwU z`GRAGkB_fp{|P!5O7xMSqm1=Gp~lZCLWg;!C4Ss?kTfrwQ?;VN_lM_%@(+==LJ1Qq zIv=05Df;12FaPw*%c-u1o_sLnT)C%1F>YJY%uRbjPltQH5l{AhysX!Bo7nj$2cEVb z=kbx^&;B95??LY@lS`Xa%hUf3sO_kkGPRw++)%kF#&amvqujF4v zI}Ec0)|A`iZ_T*qbg%w@ZR$pU?N>st)eH)27Dq-e%-bmDWMiPy^tH)y^YazU&FgL# ze2LpzrTLxz+>yEE(#Lh;H^%72?o+wC`q$==@O{>PIkt6jHu37$)#ummettV>u^X@F zm!d_-U$Nyf=_?j(-E{Bp{$Rc*O{sgA6fHe9$v*$z@kf{P|CBnf|NXe%ZW`$Jr@vwA zq9W~neNcXzzEXbOmk;mTZ?Sz`b-et^lg`P%_I%`5G}{~dyDVs5Oy%Bd6CR0ZdRv@3 z(8yex+ffy}z=84QS3mug@%#TJ-+Qds`LFrM2h;3p8FO3Pr)$Ui*(N!CGA^`9?l>xM zQ?TL9osGedUt~(lNNcC*+`WIG>h{FL?qBX6zQ_43dBXOFO=sq+Z~ye|!9Amkfya(4 zUKWwB{QvmDzwD{6zpdT1&aI9sUFY2HDK%$~9Z_zt(0h_&S^TYMj$LWg_1Ar}mdlbw zubD-h-cj>&)4H3FCmyplTvRM0fjPtZZf;TqLw(Y{^M5AqRIg@u$oVJYetuDkkIkp9 zol-LSXLcAGW&P0DS@5wbWNln%-1{%POtLTOgrvFXsLj((KGqj_?ZlpSmEF&*mN!3T zP0KptoN)4k>z*yw*Tya{-e*<%>V@^ffQ3$uj}l}rob8=Kt<6*PB7Yg~ zJGD7tU(L>Azl+Zs=>0MN;Lo}5+y|AF=B@X)7X9m$HgDTM;gIH^Td%LKUcTm6=Fz|F z<2Fal{IO@}=PhxU?|*r5(fPH64%2^On>*gqwbqt4R=N6lg!{}Xm!2QHwQ8zeeg(tF z)9bz&DIDM4HX}vi@uZ{PQ_epMzq>U$9CSpr_kEFw-+x#?f3-Z^`jbaaQ`KwgglA`G zX$8{+uXSpWr5%{#PTH@O>-Pv2#bQr3y zo3e|=eA(J9nU~#mmUv{}KC(&Jx?lg_qSo#$Haq-39hoG3CG=h6gP`*@`>ojck0-b7 zsJnJF!+S&5glp?GjElZp>igiU7_Vjc|HrfR^Ydbpj&v=wV*yS5uz#0-@k>(f!x#M@ zOCKL~vKPL%k7c4OD6J(t`oXjDpYwkfdG)wE2g|NhCqJ6#{$_QeJkMXzpPDCb?n!#d z_4fG3RgY_rZcdID%>Mi3pkn2e}J-6Qb*cZuWnbULnB}$HU zOkVCYE!n+4Q^$DY)hD0MOwpWt`lHhE-23}t?S4KHewzNrw*KIsOWS;-zY3`@Gb^Y~ z@6CI&W202CA5Z3@Bb_E~(*Eq>a;G1P{+0Ww{jvAPhPvju`pap)OKW$33)&IzP#{w7 zdhLS;jH&a3m-z)w>$5+y-~R9RDLRp#49};XD!X|p_0#PG_rL7Z^!`-4?fr$gzmX4? z`2GCEGc)_J#e3Tw%O8t=ix=kpy``4X@cfy_o#FNO7X44E`=#@lHEH_xoZE}$sRpb2 zUp3N9K6jB8Gx54NeDJH2~$ng1N~`$zu{&w?nCi$fB zuaeVjGe4-f{(p0htP*(dAg66%`ML7jfy0tYx489Jbw8Yb z_)w>6;{M(1`_~_P68y}-^ai7h%zL&QoG~nV6Ld0-I)4Y<@i6{xt|nJ`RHk=^caq)5 zgah7xCfC<1y}i9X{Qu(#E$qxS68#*XGUr)UdL_^K(AltDaK22$lj(PMm9FNIvha9z ze*XI6N{RgE>*g-4x%p|5N}eWT*|)>>bsD`=W|wNJ&TAbvPP%l&Q>xl$_v?$B+pnyQJ#K%^y5&dAEyM2z z{|e9cwsZOB{gSzNSF=v>Y3lz<{l)%h()Txa z7eCHRDx0icZFaxJUz5na8S=;k&YQ@)mUHZ(m)%$Q^_Vtx(>#UBL70*3*n>AVM+SGr)@77NZ z-y`wd)wZqTOHylhYvy^|xBWjpth~G|D|T7#A+CgzN8Vii_j3Kt=La4cSBQWAy)@oo zo}Wd<`uZ=EqD-?_me*#SpOjsmq!#)5q2<9tk>ZEG|Mx6*JC*bG)m6}q5L&^{V??z= zFQm8MxBl)YfAB~1*Tm(27VUQT@-R}9D}DOq{1c8JJKvxG^!U4d)^CSnN0g^`h%eZ` z^nbUs{`8MP zo-9n_T@m=$?Uf_nZ63Mm?)ua1^0h1C?i{gL?mgen?(du6%z*WcOS}ZD{=Audr1rx5 z!09L3PsoHN@BRNd|7@q|q;_Ma=c*rH|F9L1<~jfW#pC`ZE+2(%wKW@C&#>4hdu996 z)6=wHYs4+u@yqu5y2$8Scgz2+-r^}QFD-rLetAJ4GiY_%F=KagwiSgx?AWJt_RCpD z?bKeg?Y8vYE%je4Uo5tn6H#ZOpZdJ3^YDa@{$)Pjf4{lDm-WexmalDFj(O}ou(|#F z;|50Nl#hpw{`&1TRXcNz)jaJlM-R^DjG6WC@7(fx7j34laet@?+Ar#L*Q(U?*v+Zy zVs`r!}baChxxRO748>-L}%G<(coNYK2}h6PZFw!suid!3CRlY_RQa_haX)0|LiB9c0$c@ev64l={~W0qe{PCP~9(GSS)y!t*6u7@8HK3 z=^vg+UQW-jUHER#&ugwWX?zWnJ+X{tBIk z+YQpbNPI0!vv)o{O?PSR?Xq3d9(S1^+W(-3nVoma(QdKT{!Y(yW-iUWz3mjQaoUL= zHw>SwKGZ+CP~)}Nk>vVc^Zl1P{@q|$sBZT6-QL~*?j3Hd(LOP;HNNEi`s&m3SO1@q za&mH}&o}n>^$Y66*Uh+hzyII0ZQefGrRh(*roPI*v&%R8<&A}lk8Rv7bbVjuXSLKl zN3XQ-246hG+`%uum9cor{?S|PPuX- z@YPLb?{(q(=YjTTe|moU|BYL`Uwe|%&dt)?yZ_bN_aWCTBh+8rS-N?h_D(7F!rbWX zxuN@O9z9G?(d^POMDi-m#Vqhd6{qH`2+cXUxnV>P}qF!`hNL;x>L2n zCK;uk*5EJyTDj*2=r)E*hsf8dHIDNg{&P2{*Lqz)G0P-qzuJt7jMo*j*uVa>%{{&) z)K1zu>x-J|1<3 z2m1SdIr06JxwPZbBh~KLG5h`2TAi{9d?0ZHba=z=_xo1ow!ik7tk%2d_rKk*Z0Bhv zFAF%`{O|3jtEXQDAK83tH`9NKckS=n6aD5}#)~i@z9s)Z+1lht9j&3~Fu^Sk}MWv#+`6*(uG^SJx))Dt+yB@DFSAp6N`+ zg>~_Z(|9v4ZRxbDJ~iP-YSP)nJiXUVe7QvKsmNqDOaykMO^0Wpch;Wt+U~%j?_z-;F=)ThP1r`@QN(hRGL7 z)g?@yr`f)_bkw_Q{@UByrm6A%-TQa$HlZi8{@1Or)c=^S_+R(?saugNFD+%VX^6S| z{9p6$tM(nc?*IIH?$_TK{lZ62#2-Z6U=G+^=3BY;a`vohvHJz#PoEil6JGB3qGF1j zcKWwDlTAk-f76XW}4xTA0Ho2eXNxH=)Br3uAisH z^rBYO3AWerd#^HCIYo8za=Y-pm|6Bc3nh2HK52VGuB2#*p!f4Nz8CgML|@8*n{T7{`T5!K{}Wz^uh0JH zSj3rS+x@x1Hu)T1_0Mo!)|XwF)2-M!Bm3I4 zZSQZa+qmY(f(NV5823pZzu(`u^WlU0?5o3n9{nu7wC3oiPse8GXY6^c-5FmwhxOOi z=by#Tz23$6n!RG;W5c_vO11wdPue4-)Zg6s{?=aa`Mk9UcW!=u<$BxBqR-RLe!aKc zXXc{642FNdzPfff;`xhH-z(Gu^*b-O-3*Gmvi#A}?$@`t>)s!+XRmW>oN4iOTgJyl zvu2C@pV-98<#jR1HFjI`gG2r;?|=MUK7Z=NApX@MtCiN5)m*hNvvSjkUENT4r041W z=?%LM?(2-N`{{bzy&$8)=C}NZ?82vqA3ury_wcxU%8d(&yVRM^>%<<h7BPd(?lt+qL!es`E7uelPSre6izhTjTrN+x;y~-!6TA+qU^gr}pvx|7(T% zj@#Cm{J30j)-b+fWvRgiey-yW-aG9+)c@>ZbNj35P1gn9UJI>#TJ_<+dYjz4v%A-1 zK3?|g&kyrolh*J57xj655$~Sx4DlnYH}j~ZKK{DIrAMya-s|q{WIA^`j^oo$ zp~L_FmfwH8ygpIa+~pC+uPe;A|CDh`EV~&y|iuFmL5rCx3af4mX^+|y1vv~ zyjQeuzQVp=2?Fdsk{9~k-PyPJ@6Gwy|E7GEzP`GhbhjC@*(RAvQ&)#vGxfYxw{g+YC2n7(PT4Nn%+B)l@ujEUr@kj#K2zUWsMfYK z^mN#(jdC@6)eMB6N2Z*a5}0*m#lnqufA|I7^MADT6=%`gRqK+!{av}fDC*g*io(rh zj`e4%RO2)ZSbwFmxc|>RkpJm!`Tdu>*!HRA@B6sy*|wI}9j{hfKKpX>@~5}v_fH-9 zD7@8PsqEM0^Y)i3a$h+&RdANPW!Lllo#31KeBIn%a+x<5EloK+N%us#_3Ide!cWPM zOXu%*s7rlR@g=~2?)kr^zx8A9|NOOjz3Fi?pV@yEpPXEJcjAA`@N+Rii&8khetjnK zspzq^OOE-*-yaH|wM_~1_$nIzdGGIUS-ThReY7xsRfVRm^|8qxzQ(iv(c*rlKcQP( zZ&iQ5R;jBcf2YT+xbwSvWBe7nmg?kquHUy#6rQ#+t`5#r*x!m)Q?z{s(E>6=3beg2&>N6EkfpH~GxA z@_qj2kKDB8=|!8x&MqlEeeGW*Px5{V#qVi8HlI4pc4wYedwGBT{!d!Z;td3g>{3ro zQa!+Yuv7VHIYWQzSLth~S5000B9fLWU_x2J^j0P z(%-(P`?kHiq2g=c~dwdwO<+>`>UaKlAdEtJ?~Gzso&q*cE>9o$T(b;N(XtBgB%-C)t;8{rK1oB0L( zeb1O@Ydk$Q{d509{%4wx4L+8>zQ(#naZ_60>NMThdd|~-T=#zJm!0extafsR;NmOV z^Q~?!s^r!TUf1(0`eOO!dsA$qzcp+;zft)3lKlJoj28TFXn1~V>x0>cX7y?xyl0+& zca5C-lbH+lJxuoRJ7=MP^rBhgf6I+8_h?^R6S>&3;Nh1VzW;)^9QXYA$W(K5tdveArZzeVAvmUYh$z51y3$ogf!#$`$4^cS}bb5B=Z zpQ;-kW*@(#K+yA-S5WMGtMZ3)K2=|1jrg8Cccz*1Y~FXu!m{{F&YsTQ;b&6$e#!;4 zv0ZOFAF?{iH~B%+b60Miq=z$v1z&gU|9xtz_Se`Rp?z}#ey@9XcX#%?BNO&?&)?qD z>24=jysP?r-qR~TV)hF>W?dPvanY8{+it%zXXqPFF))@8`FGR0?2W*DXS+`?-n)Y? z3`;#;ko79mW8<_nH`he(_jBWsUs!3Bc=U*Ou>MKj8Cs=Uf9v~lET`Wx13WCKh9`S zEY7bm5jgKV$9&^EQLV5GwUQN)7H|6=KkTiDebCsn-SWQsJ^LGpCoie0mae+;Y9kZ- zo%)3RMW1=4%}(t6{QSy!#`$a!F}uFJJalCJ&ibUL^t1Dp{(Jf(RQVV456wN|@kKY{ zJa|lZajMx>eaU#s9`E;M)29LnW1kbDd$u1wax%5+y+yW+?`)IMva_>1BObLUp7?ML zbj#zMo5d#Ib82iA58CK7yQ~`_5}SwUY0*ZNi(Sr>BI)E3a#< z_LZ<-xJ~=h<3kt1_2O6lmRWIm-6yskK?n9txNhaOe%{`u58T(DYZTx5e#f%dluv%+ zbS?jVHj|9q{r1MMo4Hlz&xy-Rd>0o7)qTiXzCU5TdkJWvfPV6$z~Ey?Y_-vLF~6H@ zr1mb(((>zxna3k`6fHgF_=w9{*m>*WcK+sgj>$r>+hQTQ*J8S?#Sp)A7Df_Y~L__prq)JTsJWmsPqZ ze7?h}l{@o{<;QuA{ZBXl@Him*{LHMyZyEDHMsLs8Jik2lz{iiXpVe(jJFAs?YT87t zsjF8Ucl%(|cx3IP{{|H&5+Zk{tc=-F;Q07ar*EsGQ1v{;TDDGk^L=;zyk7RHcz(0p ztL=wm#P{bXy_(tFdUdzNw)H$$*01CJle^%}y{*yxs&e}ro7qlTNAw%W{j<0H_xa4@ zkGacxIwbj4_9Q%dzwi6HstecGMMu|WetLd#{du!BMK$-`d!!UUKR*{P|M`jLB<=EL z{OWFVtsLGRKTuk7AfGwq#)iaSF~%up6xNs5#m+L%mdnbEz83!M%D;Jxoo!h z`O2WkzeoDmM`qLM)@W1`5xcB<}u4R=BBL=?VYUW8J4zvVtprk|Et$j?UzwP@3nskM10=&_xBgMlhy^# zzDRyG;Oy6E4odaPd>3F7!*sl4wf@Dar=^Vje<$4S{>WkHGiP?W+UtXF_#0P0e(t1W zZRdP&zH`a-&uNc(oagK{wvoT4zGC*5^{W@e|2bdIxg(r?VngsdUVp_p_n8LM9@oyWEKbwCZ&&-v##s3I z+`|&=VyCS6&MO}Kb}mZnug3SIe>e6$uUNYCcJ+yq;_p3KUfyX}ubtA*Qj+V_8rJ<04L=fT&Om-~g6`(>>8aptA**Q$=cDZT9blYYp@ z9j|bku-JG%OKvuxs8wdk5dT znT2ot?f|26%T z`tI}2dEe%!uUWJF1@|4_gECU!GT`zEP+y)x!q$)CD5<;8}DuOef& zMunc7tGwN4{s)6#^?CDu`R+^pv-T$UfhhiBg&RhtT0b_c^S?OM%6+wc_E*`WE0@%q zPQR>tyk7cOpMqcY@oloVt_Fz ztD0~4=dbUI^=lLjza2JK-DA=CNh^BcnrAz8gFbvL<$cQTpXO5vwZR>l%_`B>!BN|Fm)-iuO|NYW7Oa0ug=M${c^J14L)ZUbRd#dvKBm1Kf zr-L~r)%8_Bh&?NFEV#A>YiA79r0BUkquOwPavke?4*vH^_Ljv?-!7b+XKAfa2b%DC zlIwFvu(b7;GmrV#{z}cyMMrFAY+GYkP*=?HDxl(6sgLrHyd4~dO=s5r7#cZB)+*BkK&-Dm&vJN9gA=iFqy zqc_C@Uu(KRnwzQ>lktkE~zbmZz~v$?;Q*s|@j62-tQ25*J;=Ed(r;Ft$Arxc0O~ej#_Ew2=D)% zdwbiK=2$bkP}lE| z$uxVu_H>?0yF#<;-|wmWJFlxV_}rV-Nim0avEKLH-TBkW=dazrxu(TMJ1&<8EPK

d^=EX9QQQh`P7roEvL;1K67+l>VK8% ziyyyZ|M&P^L*d3B{R=Io7u%H^2&JD-drQQzK00ay+T8xvQ(EntWM96`os=%CBp>GJ5}Op6 zJo$^oPo5t<@^bfywO(Tz_G zf6Zg;YxgaduekO&^vLJab5u9Kdzidm)if8GYGdpJf{d+{At-ag&{`m?~y`ooNG-W?;(w|)y_TBJT>|$a2 z!=@`3#Mb1qcy7TOdu zL`cWXuPCi~op7utTe5y)epAGcDAVkhdz6>dD)(&sn6RktkKsH1o7>Ch_nrLct~lSQ za_Y=}6|Wf{GcESa+wnDYb=b@Fxi_lVZ`*cuS{uHs_&V{h)V*GP@xuF4471r9pIb}q zulv;U%hq?EP2~GP+ap|0F8{9HdU$ozzw<`Zp8lRueP)hj@N=elJ;Ld7M}M&zs?4j} zFNHDE9qbeHSm)2NuAZfxw-bCyU!BpEm41JJcYLK{vU3unMDnY7zqrLs_9dUbrfX$p zv*CS%QNppc70hBfF#+>yR|@^xx8U4A_iwL1{gpXgG0$-Sd&T&>`abiYS4cd{jM|lw zc~{-b$1~!Ywbj2p<>B97$Xir6e0z6$^?&=C7aQi-l}5eiuRC2SVZ79Ldf4~BqIw|_ zw&ID8D^|3bPZy}(Bsn=a>`0cu{Dp5cl#@y;(#|~Q64%wax;pIorX#|oe|~)QKYQfn z<6Z9$*vS?jd|)YFz4@nYazVPjN#%@BPfjbha*0l2`pNA9+ST&ux6SG+>R0pcEh*OD z|G6sYih51DWWW9D4&mi8`~NycZ0 ze(v9=753j>+;sl@Z=?FZ%AUfP{x83WuZvsxUO9=yTSQ+mGkE#dIkVJ)MMSdy$=Cf@ zcv?#^_#u5)n?9@m^!5lXzOK{@B^L1KHv0Gw-{+;mB#ck@hWK&brX&U(Da- zXJ%Xb|I~jhtj-qwxIDgV@%uA}T)9^BD}EGy^6g>W3Fpl@KaFOZCQp;GDKI#&+U!BZ z{z6f?tv^3MpWfCh?REB*>D0$|o#__$b|3GPzx?szBiHVy5B@cuvc77qlBQFyFS>uf z^=IC*JB5{(9qTaGUlF=}+7yi_r%OwH#h*#IJ=*kL{?7W(%Ae9@EsI=^FVjC(8MywY zrG7TwpP5BVd_PnkJJwg895K@()#J_iYj2~s%2ej9SE+RU%h(}U^i9(Ec*5PrjplM) zJ#RrvQ0B4jEPnd!`zzjqzfIOWvYWa5-=ELtt-gI;qOl${&EYjg#a-PEGV=&Bd+|aHpl0Vh$!p(1@HKNlr}swSnRJAu%V&m*L(k|!7S&U zU+`U=FYJA4_sb(Mg{3A(?8zwfoT_!T*mC~Kl&XJ8K3Dfvmp|?Av6R>?pnNW3Vxd&_ z<6bG#Px;U5l5LL_|FOwmzvKDQBeI3-ecR zTW)_`aJ50o3xSztrL&CEe%YO!KTB<^(N~+w&lz_-A2zj`rX4+Lc>2ertw$m^r>}f2 z`ny^pI{4g^v}5*5Q%_IROBS?ve==BoY5o3xQue&!XQo&if==Wf7h9o3iMqpyw(}yg_jMPV9yfZYAG&NxpRe|m^$QG@6nn*Y+V$DLC=S?P zf3eBc>YtB*edDn?!rhKMyk{i-ab8Y;uVQ%jc)x7;{evo=lQSeAPd@lZE&N=}sV&Zr zH2mHiZ{w9tId(=8bdK)b-6v+uouMkBmTYqDe>(4YwMz; zXPM=$GSvO}*lxDF+4uARF5A`qdNJqF!W;5Q@@b!+on7jASr zUgI_MQfkS5zYm3awJ-Z(txIf7s;<0f_-K>OH`l84lA%_rTuhH|`uUl<%5D7@B8um^ z_C}e4HY)83SKsn?`YiRo&v+xZ<;*N9JhuHq?mWfE*Ti(AJZ4|ZEy;Iy5K)*EB=J~i z^WL17Mz!aT96J1Pb;!C!^NbXqcBqPR^iRLv{-f7B?JTE6cl)s;C#BE+>6mlzOydXT z_n>9mF$+HlKQ8-Fl=AL~@y!i&&GkBa;w25;pT+c;_I9@WVkJhJezzv) z#tz5g#}7LZvB`4&il?b%k-1mv)^*szkb_IXQNH7e>B*5 zR`F-JL7RG5^|dvTudbK>dXnimS8FS1in8{fMDTKtX-@kmTZ$$J&#*r;!$RuM-y8KO zD|Q7ubUM}Z`r69X&-pWD&Py@Gy;|(vKkZ|E&-BIaeXssqiYm?WoO`QOC4b(YSJ6&y z`W}lnAJ_f7Vr%xbRq;Ge-|>jfJ96Zw%smZ*|DD2WuYNgi7CURgCjU~j3@gsmdqURMQeVScu6-LtfZf=|1i+kCXP@qSeP z;pGy(73ItBTg;ZY+%d_pFgQdwx9j`iHI|!Go}8GtDetUR@At*}@BdV#Keagj>8_t0 z_Y(t_q<>=ik!#+2e>)Wpnq~N)bn5eo6r-K)>t<9W7`7GuVm#*8GxcS%#CyT%jy#q= zrxN!YgqDB!*pc*TkM;ek-@2I>_qcZ0UFq5Q(dN&)-S4MlTQ_BwS8Q$GbM2*RuYS4d zzNPiH^$+(Pv-50BprSDXF zrA#L2%-m$N@yyQnYsMdQ1NZC3$N#l838vxBsDRf6X)=*f}RZx}FykEdTBQzwi5ZEuU6? zOFX_#@#Uo@)sOy8R4@HH>#EU${|vp3Nq3v94)305+yBPXL`}{NqdR+IvZa}$g~tv(R`0oP^Q}Tc>6yxr z*H2GObw1v(Av&qL^RVx9tGPzpHXp+N?~FPwaHd*s&i)0D?;i0K%Dz{5?BS8WJ3e)% z+*f@rWn9+NBW3GVmUn-p&ThxUY*l-Ietueh()EK;V!ftiW{0<8+MH_Dyk-kw8=mZ| ztCkk`J*YLj-X{NWi{#}gKMl;%_8r|ZccJ- zxxIe=m%mHbpP6av{_ft+)&Cq~cb86`r0SLBQ}1#vxTkaWqFEWiYm7h6S?)7$QT6T3 zspr-1?kb=B?Ch-9Q7-Ls=|y|vBXOo>Vt!@`RH)$jK%fBy7eOy|ByA9bs( zZ?1ma@jFfC;0!AjePNd#4xTr+^Y`-#3#+>|8~&LdU$gRY{V5UqL;e51Zk(bU95zYC zOK6$VvlwnMy$N-Hf1TX5^>xXe1LcCN56xH;x3@~F{qWyHzhiIX>%VS&7rrEK!tst> zLHpxsdmH)R&XGzl`nu`Qm&^X2{+8cw@9cd1m!n?(*YAMd?1g%Q#q!h2dF`~HTy0o6 z`SFRBr)8`wJ|tw`-L=(wf63*?M(7jHfi4Dx$6BMe=Y^*2DtmjYp-}qc4$w(DtFEqk zHN&R%)|XkrZ5G1E*EiQpo4nlTnnk}eJO9hCkDX8KFskl*^QyIppG(Hv^N|YU@lTe= z-hUQ5GdWP%{p7FG*UWuKH@6zb-^zy6Utjp~G zMZ$e9pJac(LHdu>$3>|=Ugze#y1LqXciG#L^XVTxUy9#cKdE@r^~pb(KWe_O{W0&# z+Su^N+nVQJ?#xZ`u>p;ZtglS?-)K;|JYd_AGX*@A9YSheE6&V|D4S86@lS8VV$R8G z8sCqvXWRH+r2bf0?rqm>vzKd34YvQ?`To4s^kn|B(_y-$bxtz1F2~o)f8v6gw?{9%K}zWHAdbWT<~wMumLmfTI-W@-6q z?JW5?Y2WmSJ}FZAMaO53T~ld&`kgcPY#$Zg)ITmWdq?IkUUf5tf-^rS zr}+G-w<`M5;WO7P^mF5(F3oN(QLPi#@7L+Fa*Irv{%Fsa8OzH(zWd1g*PQNoY5e5P z%+0@iK#S~OuRJp6LAJ*}t|Io0;+a1#Jls_NJ#O#wO;1mq`Ypd_{YI0Xzw^KFHLU*r zb7TLs!iX6^uH{Cj9yuYnYyXt&!^v|k^D_1s^zBIdHvN(Q$^WuG9+3~fep+)+v+=us zWt9K!bzin%O&<3ukK8eQr}}=6F?->+>`CwKQoE+;6`REED~kLa{b=j)y2`%PHIvL@ zqcU%-SXiYXwEeA?IPb>iKh6uu8x{XL(~!J5^|V_4{=eJ$iaS1X>U`a6QR>CUE4iey zs87aDNzynqWZp^s!jyHxD?3lH6~FMR)F?E$ywtvO2zpEvGrx4iX5 z^0Mi@*?(8A;k}Sv|Lte`D??|U8jnRibN)`Q2sbu!Q#34GC-|;E-}0$f?E(I_88i3n z{M0s!drC6s`on#bYU^KVTbIAN@;muo_}-|}%I|y2mzKP|q$v0P?V{R`f7<#b^o-Nb zgxGr*O)!#A>R-3ImUG@T!@}T{>Ff0G?bd#NZr-ZRYMI?)T?^MBiRSSo0l*UG

%N3(dw zXXV*G%TBCMPkeOn=#Hs%?d8_VR!MpZPc|f}_w#;~Pn=mVE&P8zXm{hra|Jn{*fy$l zZkOGs7Ly~sGhlp=F3?#hIkBh1|Yoz{I^y?!5;uyFj|s;$4)JidH%pZ7D9n9G~boZgW) zkNbIT)Vej6Q~w-`=n>zk?%!3t{A_@|ji_^y&z;Sn#Z>Th@rzF!Ia0a&@$B|+v)ak4 zH{Ra+`+Lgsb8|mkogSb0PqO{{A>9|(Kcu&1w?C<`cyU4T=fmIfCinLi>)6aHXX^0~12nb*;K4`yGV zv@Uj+R(_!kkEHqf`y1kZeSf{a@a2#B2G8qY*c@+Cbjd&T4CjLcUmHTUw9_fcm2Suuh}UN8X7lMKhOJXH&4FU z@fqWpr;8TPv1IuiHIMb@&y3`?x3^52bv1j{@no0d9m>g%mYvZ1^^RLy|3uSIZqVsT zuUx(LxMnccn&k5S*OKr#)+4!fee&B0HT$2`D%i)&IQRH^xo+&X5KEDLaX*3|o(|ns z6R8=wX34wy%6sqKC!c&0xpQ(SyI69>FO_?)M@%DFEX{K3WD*EHTN4OKbkicpp+mxb-Sj^WzrVlZKe4@YeZ}!US>~FfJKa7N8^wWEe?|H6zq7ya zXQ6!EmxWWbgY}MBb}9c5EZ%c3{(D&eOm)M;Q;hHI>mF6iG%Dga+{Djd-oJ*Kl7XyHQ5ZKG7m|9 zJ?!T! zdh^0?Z(hwc(9vZlCuw@mh@mH-~oNexJZ2w+)F>$f!v8lF_)@Q_PxjycAO7jtN$F)9 zS1I39JYx&mGI(=GVKRg8asF0Ij{B!g&(1dYujKs9_U^i{PtCJ4Gk@8fNIddf+AL2) z{_kgH&9EI29XsFIDxUiDXobM{oBlexoyEyTfr#j=Xbwl-JZX^u*p|mJ(AtH>39ABG*g%>+9#r8^pi9w6weA z^|iMfW9B>*{O&GuW%HZTCo?yuPyI9h%t9N@b+gkyE!j~Mz9>&OdZW*4$vFNajiv7{ zMQVkv_~J9K@4U0Y$A0^N5tCHCmz5f>;)*-=p3t^J5PcRxnIb+&0BBk0mH-d zCJ2kK+gbeQpO1{=F5^X2v@&*|B3a;Cemuq6Fa&+m_ZPws38{1jXF@v3;xmJk2; zupd@>CIdQwa_`a}ahdlb&nDgBzo%K#W_ir|{hr0iDo19R9q`}da?)V!WIJu)^!QiO z`Fj<6rA@BcEE3dQ*Iqe6{Wiy^IyTwkK$JZ{l z)9HEpf#XTt$%W2$I8zztt4$Y3ZJurcx)u4@fi_e1ZY?@*IR9BYHDn%@?J4jN35LwP%vkjY5zfIw$q~9HuLhc-#JDzeU_J=Tkjh1Ju3pVr@ZC1!SwUD%rltF*fRhrcgP`q?!}Cv%fQe`vGu$A� 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 literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/pics/makefile b/lib/hcrypto/libtommath/pics/makefile new file mode 100644 index 000000000..3ecb02ff7 --- /dev/null +++ b/lib/hcrypto/libtommath/pics/makefile @@ -0,0 +1,35 @@ +# makes the images... yeah + +default: pses + +design_process.ps: design_process.tif + tiff2ps -s -e design_process.tif > design_process.ps + +sliding_window.ps: sliding_window.tif + tiff2ps -s -e sliding_window.tif > sliding_window.ps + +expt_state.ps: expt_state.tif + tiff2ps -s -e expt_state.tif > expt_state.ps + +primality.ps: primality.tif + tiff2ps -s -e primality.tif > primality.ps + +design_process.pdf: design_process.ps + epstopdf design_process.ps + +sliding_window.pdf: sliding_window.ps + epstopdf sliding_window.ps + +expt_state.pdf: expt_state.ps + epstopdf expt_state.ps + +primality.pdf: primality.ps + epstopdf primality.ps + + +pses: sliding_window.ps expt_state.ps primality.ps design_process.ps +pdfes: sliding_window.pdf expt_state.pdf primality.pdf design_process.pdf + +clean: + rm -rf *.ps *.pdf .xvpics + \ No newline at end of file diff --git a/lib/hcrypto/libtommath/pics/primality.tif b/lib/hcrypto/libtommath/pics/primality.tif new file mode 100644 index 0000000000000000000000000000000000000000..76d6be3fac2cc8b07a401e008fbe45f02758cef7 GIT binary patch literal 85514 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 literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/pics/radix.sxd b/lib/hcrypto/libtommath/pics/radix.sxd new file mode 100644 index 0000000000000000000000000000000000000000..b9eb9a032d0b5229d4828911466490a95c126a2b GIT binary patch literal 6181 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 SNC_JQ8$%Q$1H)D^5Dx&ugP|V) literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/pics/sliding_window.sxd b/lib/hcrypto/libtommath/pics/sliding_window.sxd new file mode 100644 index 0000000000000000000000000000000000000000..91e7c0d9f43b612ff0a59d86a71c8928fbd695f3 GIT binary patch literal 6787 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 literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/pics/sliding_window.tif b/lib/hcrypto/libtommath/pics/sliding_window.tif new file mode 100644 index 0000000000000000000000000000000000000000..bb4cb96ebff4e06478672dd3583bd26a51d85b5d GIT binary patch literal 53880 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 literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/poster.out b/lib/hcrypto/libtommath/poster.out new file mode 100644 index 000000000..e69de29bb diff --git a/lib/hcrypto/libtommath/poster.pdf b/lib/hcrypto/libtommath/poster.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f3768d76904d62226e238a46fb69406e0c481a6d GIT binary patch literal 37821 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 +#ifdef BN_ERROR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +static const struct { + int code; + char *msg; +} msgs[] = { + { MP_OKAY, "Successful" }, + { MP_MEM, "Out of heap" }, + { MP_VAL, "Value out of range" } +}; + +/* return a char * string for a given code */ +char *mp_error_to_string(int code) +{ + int x; + + /* scan the lookup table for the given message */ + for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) { + if (msgs[x].code == code) { + return msgs[x].msg; + } + } + + /* generic reply for invalid code */ + return "Invalid error code"; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_error.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_error.c */ + +/* Start: bn_fast_mp_invmod.c */ +#include +#ifdef BN_FAST_MP_INVMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes the modular inverse via binary extended euclidean algorithm, + * that is c = 1/a mod b + * + * Based on slow invmod except this is optimized for the case where b is + * odd as per HAC Note 14.64 on pp. 610 + */ +int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x, y, u, v, B, D; + int res, neg; + + /* 2. [modified] b must be odd */ + if (mp_iseven (b) == 1) { + return MP_VAL; + } + + /* init all our temps */ + if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { + return res; + } + + /* x == modulus, y == value to invert */ + if ((res = mp_copy (b, &x)) != MP_OKAY) { + goto LBL_ERR; + } + + /* we need y = |a| */ + if ((res = mp_mod (a, b, &y)) != MP_OKAY) { + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = mp_copy (&x, &u)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_copy (&y, &v)) != MP_OKAY) { + goto LBL_ERR; + } + mp_set (&D, 1); + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto LBL_ERR; + } + /* 4.2 if B is odd then */ + if (mp_isodd (&B) == 1) { + if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* B = B/2 */ + if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 5. while v is even do */ + while (mp_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto LBL_ERR; + } + /* 5.2 if D is odd then */ + if (mp_isodd (&D) == 1) { + /* D = (D-x)/2 */ + if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* D = D/2 */ + if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 6. if u >= v then */ + if (mp_cmp (&u, &v) != MP_LT) { + /* u = u - v, B = B - D */ + if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + /* v - v - u, D = D - B */ + if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* if not zero goto step 4 */ + if (mp_iszero (&u) == 0) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d (&v, 1) != MP_EQ) { + res = MP_VAL; + goto LBL_ERR; + } + + /* b is now the inverse */ + neg = a->sign; + while (D.sign == MP_NEG) { + if ((res = mp_add (&D, b, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + mp_exch (&D, c); + c->sign = neg; + res = MP_OKAY; + +LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_fast_mp_invmod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_fast_mp_invmod.c */ + +/* Start: bn_fast_mp_montgomery_reduce.c */ +#include +#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes xR**-1 == x (mod N) via Montgomery Reduction + * + * This is an optimized implementation of montgomery_reduce + * which uses the comba method to quickly calculate the columns of the + * reduction. + * + * Based on Algorithm 14.32 on pp.601 of HAC. +*/ +int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +{ + int ix, res, olduse; + mp_word W[MP_WARRAY]; + + /* get old used count */ + olduse = x->used; + + /* grow a as required */ + if (x->alloc < n->used + 1) { + if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { + return res; + } + } + + /* first we have to get the digits of the input into + * an array of double precision words W[...] + */ + { + register mp_word *_W; + register mp_digit *tmpx; + + /* alias for the W[] array */ + _W = W; + + /* alias for the digits of x*/ + tmpx = x->dp; + + /* copy the digits of a into W[0..a->used-1] */ + for (ix = 0; ix < x->used; ix++) { + *_W++ = *tmpx++; + } + + /* zero the high words of W[a->used..m->used*2] */ + for (; ix < n->used * 2 + 1; ix++) { + *_W++ = 0; + } + } + + /* now we proceed to zero successive digits + * from the least significant upwards + */ + for (ix = 0; ix < n->used; ix++) { + /* mu = ai * m' mod b + * + * We avoid a double precision multiplication (which isn't required) + * by casting the value down to a mp_digit. Note this requires + * that W[ix-1] have the carry cleared (see after the inner loop) + */ + register mp_digit mu; + mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); + + /* a = a + mu * m * b**i + * + * This is computed in place and on the fly. The multiplication + * by b**i is handled by offseting which columns the results + * are added to. + * + * Note the comba method normally doesn't handle carries in the + * inner loop In this case we fix the carry from the previous + * column since the Montgomery reduction requires digits of the + * result (so far) [see above] to work. This is + * handled by fixing up one carry after the inner loop. The + * carry fixups are done in order so after these loops the + * first m->used words of W[] have the carries fixed + */ + { + register int iy; + register mp_digit *tmpn; + register mp_word *_W; + + /* alias for the digits of the modulus */ + tmpn = n->dp; + + /* Alias for the columns set by an offset of ix */ + _W = W + ix; + + /* inner loop */ + for (iy = 0; iy < n->used; iy++) { + *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++); + } + } + + /* now fix carry for next digit, W[ix+1] */ + W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); + } + + /* now we have to propagate the carries and + * shift the words downward [all those least + * significant digits we zeroed]. + */ + { + register mp_digit *tmpx; + register mp_word *_W, *_W1; + + /* nox fix rest of carries */ + + /* alias for current word */ + _W1 = W + ix; + + /* alias for next word, where the carry goes */ + _W = W + ++ix; + + for (; ix <= n->used * 2 + 1; ix++) { + *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); + } + + /* copy out, A = A/b**n + * + * The result is A/b**n but instead of converting from an + * array of mp_word to mp_digit than calling mp_rshd + * we just copy them in the right order + */ + + /* alias for destination word */ + tmpx = x->dp; + + /* alias for shifted double precision result */ + _W = W + n->used; + + for (ix = 0; ix < n->used + 1; ix++) { + *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); + } + + /* zero oldused digits, if the input a was larger than + * m->used+1 we'll have to clear the digits + */ + for (; ix < olduse; ix++) { + *tmpx++ = 0; + } + } + + /* set the max used and clamp */ + x->used = n->used + 1; + mp_clamp (x); + + /* if A >= m then A = A - m */ + if (mp_cmp_mag (x, n) != MP_LT) { + return s_mp_sub (x, n, x); + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_fast_mp_montgomery_reduce.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_fast_mp_montgomery_reduce.c */ + +/* Start: bn_fast_s_mp_mul_digs.c */ +#include +#ifdef BN_FAST_S_MP_MUL_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Fast (comba) multiplier + * + * This is the fast column-array [comba] multiplier. It is + * designed to compute the columns of the product first + * then handle the carries afterwards. This has the effect + * of making the nested loops that compute the columns very + * simple and schedulable on super-scalar processors. + * + * This has been modified to produce a variable number of + * digits of output so if say only a half-product is required + * you don't have to compute the upper half (a feature + * required for fast Barrett reduction). + * + * Based on Algorithm 14.12 on pp.595 of HAC. + * + */ +int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + int olduse, res, pa, ix, iz; + mp_digit W[MP_WARRAY]; + register mp_word _W; + + /* grow the destination as required */ + if (c->alloc < digs) { + if ((res = mp_grow (c, digs)) != MP_OKAY) { + return res; + } + } + + /* number of output digits to produce */ + pa = MIN(digs, a->used + b->used); + + /* clear the carry */ + _W = 0; + for (ix = 0; ix < pa; ix++) { + int tx, ty; + int iy; + mp_digit *tmpx, *tmpy; + + /* get offsets into the two bignums */ + ty = MIN(b->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = b->dp + ty; + + /* this is the number of times the loop will iterrate, essentially + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; ++iz) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + + } + + /* store term */ + W[ix] = ((mp_digit)_W) & MP_MASK; + + /* make next carry */ + _W = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + register mp_digit *tmpc; + tmpc = c->dp; + for (ix = 0; ix < pa+1; ix++) { + /* now extract the previous digit [below the carry] */ + *tmpc++ = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpc++ = 0; + } + } + mp_clamp (c); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_digs.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_fast_s_mp_mul_digs.c */ + +/* Start: bn_fast_s_mp_mul_high_digs.c */ +#include +#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* this is a modified version of fast_s_mul_digs that only produces + * output digits *above* digs. See the comments for fast_s_mul_digs + * to see how it works. + * + * This is used in the Barrett reduction since for one of the multiplications + * only the higher digits were needed. This essentially halves the work. + * + * Based on Algorithm 14.12 on pp.595 of HAC. + */ +int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + int olduse, res, pa, ix, iz; + mp_digit W[MP_WARRAY]; + mp_word _W; + + /* grow the destination as required */ + pa = a->used + b->used; + if (c->alloc < pa) { + if ((res = mp_grow (c, pa)) != MP_OKAY) { + return res; + } + } + + /* number of output digits to produce */ + pa = a->used + b->used; + _W = 0; + for (ix = digs; ix < pa; ix++) { + int tx, ty, iy; + mp_digit *tmpx, *tmpy; + + /* get offsets into the two bignums */ + ty = MIN(b->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = b->dp + ty; + + /* this is the number of times the loop will iterrate, essentially its + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + } + + /* store term */ + W[ix] = ((mp_digit)_W) & MP_MASK; + + /* make next carry */ + _W = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + register mp_digit *tmpc; + + tmpc = c->dp + digs; + for (ix = digs; ix < pa; ix++) { + /* now extract the previous digit [below the carry] */ + *tmpc++ = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpc++ = 0; + } + } + mp_clamp (c); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_mul_high_digs.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_fast_s_mp_mul_high_digs.c */ + +/* Start: bn_fast_s_mp_sqr.c */ +#include +#ifdef BN_FAST_S_MP_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* the jist of squaring... + * you do like mult except the offset of the tmpx [one that + * starts closer to zero] can't equal the offset of tmpy. + * So basically you set up iy like before then you min it with + * (ty-tx) so that it never happens. You double all those + * you add in the inner loop + +After that loop you do the squares and add them in. +*/ + +int fast_s_mp_sqr (mp_int * a, mp_int * b) +{ + int olduse, res, pa, ix, iz; + mp_digit W[MP_WARRAY], *tmpx; + mp_word W1; + + /* grow the destination as required */ + pa = a->used + a->used; + if (b->alloc < pa) { + if ((res = mp_grow (b, pa)) != MP_OKAY) { + return res; + } + } + + /* number of output digits to produce */ + W1 = 0; + for (ix = 0; ix < pa; ix++) { + int tx, ty, iy; + mp_word _W; + mp_digit *tmpy; + + /* clear counter */ + _W = 0; + + /* get offsets into the two bignums */ + ty = MIN(a->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = a->dp + ty; + + /* this is the number of times the loop will iterrate, essentially + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* now for squaring tx can never equal ty + * we halve the distance since they approach at a rate of 2x + * and we have to round because odd cases need to be executed + */ + iy = MIN(iy, (ty-tx+1)>>1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + } + + /* double the inner product and add carry */ + _W = _W + _W + W1; + + /* even columns have the square term in them */ + if ((ix&1) == 0) { + _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]); + } + + /* store it */ + W[ix] = (mp_digit)(_W & MP_MASK); + + /* make next carry */ + W1 = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = b->used; + b->used = a->used+a->used; + + { + mp_digit *tmpb; + tmpb = b->dp; + for (ix = 0; ix < pa; ix++) { + *tmpb++ = W[ix] & MP_MASK; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpb++ = 0; + } + } + mp_clamp (b); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_fast_s_mp_sqr.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_fast_s_mp_sqr.c */ + +/* Start: bn_mp_2expt.c */ +#include +#ifdef BN_MP_2EXPT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes a = 2**b + * + * Simple algorithm which zeroes the int, grows it then just sets one bit + * as required. + */ +int +mp_2expt (mp_int * a, int b) +{ + int res; + + /* zero a as per default */ + mp_zero (a); + + /* grow a to accomodate the single bit */ + if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { + return res; + } + + /* set the used count of where the bit will go */ + a->used = b / DIGIT_BIT + 1; + + /* put the single bit in its place */ + a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT); + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_2expt.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_2expt.c */ + +/* Start: bn_mp_abs.c */ +#include +#ifdef BN_MP_ABS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* b = |a| + * + * Simple function copies the input and fixes the sign to positive + */ +int +mp_abs (mp_int * a, mp_int * b) +{ + int res; + + /* copy a to b */ + if (a != b) { + if ((res = mp_copy (a, b)) != MP_OKAY) { + return res; + } + } + + /* force the sign of b to positive */ + b->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_abs.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_abs.c */ + +/* Start: bn_mp_add.c */ +#include +#ifdef BN_MP_ADD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* high level addition (handles signs) */ +int mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + int sa, sb, res; + + /* get sign of both inputs */ + sa = a->sign; + sb = b->sign; + + /* handle two cases, not four */ + if (sa == sb) { + /* both positive or both negative */ + /* add their magnitudes, copy the sign */ + c->sign = sa; + res = s_mp_add (a, b, c); + } else { + /* one positive, the other negative */ + /* subtract the one with the greater magnitude from */ + /* the one of the lesser magnitude. The result gets */ + /* the sign of the one with the greater magnitude. */ + if (mp_cmp_mag (a, b) == MP_LT) { + c->sign = sb; + res = s_mp_sub (b, a, c); + } else { + c->sign = sa; + res = s_mp_sub (a, b, c); + } + } + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_add.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_add.c */ + +/* Start: bn_mp_add_d.c */ +#include +#ifdef BN_MP_ADD_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* single digit addition */ +int +mp_add_d (mp_int * a, mp_digit b, mp_int * c) +{ + int res, ix, oldused; + mp_digit *tmpa, *tmpc, mu; + + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* if a is negative and |a| >= b, call c = |a| - b */ + if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) { + /* temporarily fix sign of a */ + a->sign = MP_ZPOS; + + /* c = |a| - b */ + res = mp_sub_d(a, b, c); + + /* fix sign */ + a->sign = c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return res; + } + + /* old number of used digits in c */ + oldused = c->used; + + /* sign always positive */ + c->sign = MP_ZPOS; + + /* source alias */ + tmpa = a->dp; + + /* destination alias */ + tmpc = c->dp; + + /* if a is positive */ + if (a->sign == MP_ZPOS) { + /* add digit, after this we're propagating + * the carry. + */ + *tmpc = *tmpa++ + b; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + + /* now handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ + mu; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + } + /* set final carry */ + ix++; + *tmpc++ = mu; + + /* setup size */ + c->used = a->used + 1; + } else { + /* a was negative and |a| < b */ + c->used = 1; + + /* the result is a single digit */ + if (a->used == 1) { + *tmpc++ = b - a->dp[0]; + } else { + *tmpc++ = b; + } + + /* setup count so the clearing of oldused + * can fall through correctly + */ + ix = 1; + } + + /* now zero to oldused */ + while (ix++ < oldused) { + *tmpc++ = 0; + } + mp_clamp(c); + + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_add_d.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_add_d.c */ + +/* Start: bn_mp_addmod.c */ +#include +#ifdef BN_MP_ADDMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* d = a + b (mod c) */ +int +mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_add (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, c, d); + mp_clear (&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_addmod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_addmod.c */ + +/* Start: bn_mp_and.c */ +#include +#ifdef BN_MP_AND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* AND two ints together */ +int +mp_and (mp_int * a, mp_int * b, mp_int * c) +{ + int res, ix, px; + mp_int t, *x; + + if (a->used > b->used) { + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + px = b->used; + x = b; + } else { + if ((res = mp_init_copy (&t, b)) != MP_OKAY) { + return res; + } + px = a->used; + x = a; + } + + for (ix = 0; ix < px; ix++) { + t.dp[ix] &= x->dp[ix]; + } + + /* zero digits above the last from the smallest mp_int */ + for (; ix < t.used; ix++) { + t.dp[ix] = 0; + } + + mp_clamp (&t); + mp_exch (c, &t); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_and.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_and.c */ + +/* Start: bn_mp_clamp.c */ +#include +#ifdef BN_MP_CLAMP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* trim unused digits + * + * This is used to ensure that leading zero digits are + * trimed and the leading "used" digit will be non-zero + * Typically very fast. Also fixes the sign if there + * are no more leading digits + */ +void +mp_clamp (mp_int * a) +{ + /* decrease used while the most significant digit is + * zero. + */ + while (a->used > 0 && a->dp[a->used - 1] == 0) { + --(a->used); + } + + /* reset the sign flag if used == 0 */ + if (a->used == 0) { + a->sign = MP_ZPOS; + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_clamp.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_clamp.c */ + +/* Start: bn_mp_clear.c */ +#include +#ifdef BN_MP_CLEAR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* clear one (frees) */ +void +mp_clear (mp_int * a) +{ + int i; + + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* first zero the digits */ + for (i = 0; i < a->used; i++) { + a->dp[i] = 0; + } + + /* free ram */ + XFREE(a->dp); + + /* reset members to make debugging easier */ + a->dp = NULL; + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_clear.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_clear.c */ + +/* Start: bn_mp_clear_multi.c */ +#include +#ifdef BN_MP_CLEAR_MULTI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include + +void mp_clear_multi(mp_int *mp, ...) +{ + mp_int* next_mp = mp; + va_list args; + va_start(args, mp); + while (next_mp != NULL) { + mp_clear(next_mp); + next_mp = va_arg(args, mp_int*); + } + va_end(args); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_clear_multi.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_clear_multi.c */ + +/* Start: bn_mp_cmp.c */ +#include +#ifdef BN_MP_CMP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* compare two ints (signed)*/ +int +mp_cmp (mp_int * a, mp_int * b) +{ + /* compare based on sign */ + if (a->sign != b->sign) { + if (a->sign == MP_NEG) { + return MP_LT; + } else { + return MP_GT; + } + } + + /* compare digits */ + if (a->sign == MP_NEG) { + /* if negative compare opposite direction */ + return mp_cmp_mag(b, a); + } else { + return mp_cmp_mag(a, b); + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_cmp.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_cmp.c */ + +/* Start: bn_mp_cmp_d.c */ +#include +#ifdef BN_MP_CMP_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* compare a digit */ +int mp_cmp_d(mp_int * a, mp_digit b) +{ + /* compare based on sign */ + if (a->sign == MP_NEG) { + return MP_LT; + } + + /* compare based on magnitude */ + if (a->used > 1) { + return MP_GT; + } + + /* compare the only digit of a to b */ + if (a->dp[0] > b) { + return MP_GT; + } else if (a->dp[0] < b) { + return MP_LT; + } else { + return MP_EQ; + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_cmp_d.c */ + +/* Start: bn_mp_cmp_mag.c */ +#include +#ifdef BN_MP_CMP_MAG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* compare maginitude of two ints (unsigned) */ +int mp_cmp_mag (mp_int * a, mp_int * b) +{ + int n; + mp_digit *tmpa, *tmpb; + + /* compare based on # of non-zero digits */ + if (a->used > b->used) { + return MP_GT; + } + + if (a->used < b->used) { + return MP_LT; + } + + /* alias for a */ + tmpa = a->dp + (a->used - 1); + + /* alias for b */ + tmpb = b->dp + (a->used - 1); + + /* compare based on digits */ + for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { + if (*tmpa > *tmpb) { + return MP_GT; + } + + if (*tmpa < *tmpb) { + return MP_LT; + } + } + return MP_EQ; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_mag.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_cmp_mag.c */ + +/* Start: bn_mp_cnt_lsb.c */ +#include +#ifdef BN_MP_CNT_LSB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +static const int lnz[16] = { + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(mp_int *a) +{ + int x; + mp_digit q, qq; + + /* easy out */ + if (mp_iszero(a) == 1) { + return 0; + } + + /* scan lower digits until non-zero */ + for (x = 0; x < a->used && a->dp[x] == 0; x++); + q = a->dp[x]; + x *= DIGIT_BIT; + + /* now scan this digit until a 1 is found */ + if ((q & 1) == 0) { + do { + qq = q & 15; + x += lnz[qq]; + q >>= 4; + } while (qq == 0); + } + return x; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_cnt_lsb.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_cnt_lsb.c */ + +/* Start: bn_mp_copy.c */ +#include +#ifdef BN_MP_COPY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* copy, b = a */ +int +mp_copy (mp_int * a, mp_int * b) +{ + int res, n; + + /* if dst == src do nothing */ + if (a == b) { + return MP_OKAY; + } + + /* grow dest */ + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + } + + /* zero b and copy the parameters over */ + { + register mp_digit *tmpa, *tmpb; + + /* pointer aliases */ + + /* source */ + tmpa = a->dp; + + /* destination */ + tmpb = b->dp; + + /* copy all the digits */ + for (n = 0; n < a->used; n++) { + *tmpb++ = *tmpa++; + } + + /* clear high digits */ + for (; n < b->used; n++) { + *tmpb++ = 0; + } + } + + /* copy used count and sign */ + b->used = a->used; + b->sign = a->sign; + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_copy.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_copy.c */ + +/* Start: bn_mp_count_bits.c */ +#include +#ifdef BN_MP_COUNT_BITS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* returns the number of bits in an int */ +int +mp_count_bits (mp_int * a) +{ + int r; + mp_digit q; + + /* shortcut */ + if (a->used == 0) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > ((mp_digit) 0)) { + ++r; + q >>= ((mp_digit) 1); + } + return r; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_count_bits.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_count_bits.c */ + +/* Start: bn_mp_div.c */ +#include +#ifdef BN_MP_DIV_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +#ifdef BN_MP_DIV_SMALL + +/* slower bit-bang division... also smaller */ +int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + mp_int ta, tb, tq, q; + int res, n, n2; + + /* is divisor zero ? */ + if (mp_iszero (b) == 1) { + return MP_VAL; + } + + /* if a < b then q=0, r = a */ + if (mp_cmp_mag (a, b) == MP_LT) { + if (d != NULL) { + res = mp_copy (a, d); + } else { + res = MP_OKAY; + } + if (c != NULL) { + mp_zero (c); + } + return res; + } + + /* init our temps */ + if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) { + return res; + } + + + mp_set(&tq, 1); + n = mp_count_bits(a) - mp_count_bits(b); + if (((res = mp_abs(a, &ta)) != MP_OKAY) || + ((res = mp_abs(b, &tb)) != MP_OKAY) || + ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) || + ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) { + goto LBL_ERR; + } + + while (n-- >= 0) { + if (mp_cmp(&tb, &ta) != MP_GT) { + if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) || + ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) { + goto LBL_ERR; + } + } + if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) || + ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) { + goto LBL_ERR; + } + } + + /* now q == quotient and ta == remainder */ + n = a->sign; + n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG); + if (c != NULL) { + mp_exch(c, &q); + c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2; + } + if (d != NULL) { + mp_exch(d, &ta); + d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n; + } +LBL_ERR: + mp_clear_multi(&ta, &tb, &tq, &q, NULL); + return res; +} + +#else + +/* integer signed division. + * c*b + d == a [e.g. a/b, c=quotient, d=remainder] + * HAC pp.598 Algorithm 14.20 + * + * Note that the description in HAC is horribly + * incomplete. For example, it doesn't consider + * the case where digits are removed from 'x' in + * the inner loop. It also doesn't consider the + * case that y has fewer than three digits, etc.. + * + * The overall algorithm is as described as + * 14.20 from HAC but fixed to treat these cases. +*/ +int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + mp_int q, x, y, t1, t2; + int res, n, t, i, norm, neg; + + /* is divisor zero ? */ + if (mp_iszero (b) == 1) { + return MP_VAL; + } + + /* if a < b then q=0, r = a */ + if (mp_cmp_mag (a, b) == MP_LT) { + if (d != NULL) { + res = mp_copy (a, d); + } else { + res = MP_OKAY; + } + if (c != NULL) { + mp_zero (c); + } + return res; + } + + if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { + return res; + } + q.used = a->used + 2; + + if ((res = mp_init (&t1)) != MP_OKAY) { + goto LBL_Q; + } + + if ((res = mp_init (&t2)) != MP_OKAY) { + goto LBL_T1; + } + + if ((res = mp_init_copy (&x, a)) != MP_OKAY) { + goto LBL_T2; + } + + if ((res = mp_init_copy (&y, b)) != MP_OKAY) { + goto LBL_X; + } + + /* fix the sign */ + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + x.sign = y.sign = MP_ZPOS; + + /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ + norm = mp_count_bits(&y) % DIGIT_BIT; + if (norm < (int)(DIGIT_BIT-1)) { + norm = (DIGIT_BIT-1) - norm; + if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { + goto LBL_Y; + } + if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { + goto LBL_Y; + } + } else { + norm = 0; + } + + /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ + n = x.used - 1; + t = y.used - 1; + + /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ + if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */ + goto LBL_Y; + } + + while (mp_cmp (&x, &y) != MP_LT) { + ++(q.dp[n - t]); + if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { + goto LBL_Y; + } + } + + /* reset y by shifting it back down */ + mp_rshd (&y, n - t); + + /* step 3. for i from n down to (t + 1) */ + for (i = n; i >= (t + 1); i--) { + if (i > x.used) { + continue; + } + + /* step 3.1 if xi == yt then set q{i-t-1} to b-1, + * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ + if (x.dp[i] == y.dp[t]) { + q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); + } else { + mp_word tmp; + tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); + tmp |= ((mp_word) x.dp[i - 1]); + tmp /= ((mp_word) y.dp[t]); + if (tmp > (mp_word) MP_MASK) + tmp = MP_MASK; + q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); + } + + /* while (q{i-t-1} * (yt * b + y{t-1})) > + xi * b**2 + xi-1 * b + xi-2 + + do q{i-t-1} -= 1; + */ + q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; + do { + q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; + + /* find left hand */ + mp_zero (&t1); + t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; + t1.dp[1] = y.dp[t]; + t1.used = 2; + if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { + goto LBL_Y; + } + + /* find right hand */ + t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; + t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; + t2.dp[2] = x.dp[i]; + t2.used = 3; + } while (mp_cmp_mag(&t1, &t2) == MP_GT); + + /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ + if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { + goto LBL_Y; + } + + if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { + goto LBL_Y; + } + + if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { + goto LBL_Y; + } + + /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ + if (x.sign == MP_NEG) { + if ((res = mp_copy (&y, &t1)) != MP_OKAY) { + goto LBL_Y; + } + if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { + goto LBL_Y; + } + if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { + goto LBL_Y; + } + + q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; + } + } + + /* now q is the quotient and x is the remainder + * [which we have to normalize] + */ + + /* get sign before writing to c */ + x.sign = x.used == 0 ? MP_ZPOS : a->sign; + + if (c != NULL) { + mp_clamp (&q); + mp_exch (&q, c); + c->sign = neg; + } + + if (d != NULL) { + mp_div_2d (&x, norm, &x, NULL); + mp_exch (&x, d); + } + + res = MP_OKAY; + +LBL_Y:mp_clear (&y); +LBL_X:mp_clear (&x); +LBL_T2:mp_clear (&t2); +LBL_T1:mp_clear (&t1); +LBL_Q:mp_clear (&q); + return res; +} + +#endif + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_div.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_div.c */ + +/* Start: bn_mp_div_2.c */ +#include +#ifdef BN_MP_DIV_2_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* b = a/2 */ +int mp_div_2(mp_int * a, mp_int * b) +{ + int x, res, oldused; + + /* copy */ + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + } + + oldused = b->used; + b->used = a->used; + { + register mp_digit r, rr, *tmpa, *tmpb; + + /* source alias */ + tmpa = a->dp + b->used - 1; + + /* dest alias */ + tmpb = b->dp + b->used - 1; + + /* carry */ + r = 0; + for (x = b->used - 1; x >= 0; x--) { + /* get the carry for the next iteration */ + rr = *tmpa & 1; + + /* shift the current digit, add in carry and store */ + *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero excess digits */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + mp_clamp (b); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_div_2.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_div_2.c */ + +/* Start: bn_mp_div_2d.c */ +#include +#ifdef BN_MP_DIV_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ +int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) +{ + mp_digit D, r, rr; + int x, res; + mp_int t; + + + /* if the shift count is <= 0 then we do no work */ + if (b <= 0) { + res = mp_copy (a, c); + if (d != NULL) { + mp_zero (d); + } + return res; + } + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + /* get the remainder */ + if (d != NULL) { + if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + } + + /* copy */ + if ((res = mp_copy (a, c)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + mp_rshd (c, b / DIGIT_BIT); + } + + /* shift any bit count < DIGIT_BIT */ + D = (mp_digit) (b % DIGIT_BIT); + if (D != 0) { + register mp_digit *tmpc, mask, shift; + + /* mask */ + mask = (((mp_digit)1) << D) - 1; + + /* shift for lsb */ + shift = DIGIT_BIT - D; + + /* alias */ + tmpc = c->dp + (c->used - 1); + + /* carry */ + r = 0; + for (x = c->used - 1; x >= 0; x--) { + /* get the lower bits of this word in a temp */ + rr = *tmpc & mask; + + /* shift the current word and mix in the carry bits from the previous word */ + *tmpc = (*tmpc >> D) | (r << shift); + --tmpc; + + /* set the carry to the carry bits of the current word found above */ + r = rr; + } + } + mp_clamp (c); + if (d != NULL) { + mp_exch (&t, d); + } + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_div_2d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_div_2d.c */ + +/* Start: bn_mp_div_3.c */ +#include +#ifdef BN_MP_DIV_3_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* divide by three (based on routine from MPI and the GMP manual) */ +int +mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) +{ + mp_int q; + mp_word w, t; + mp_digit b; + int res, ix; + + /* b = 2**DIGIT_BIT / 3 */ + b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3); + + if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { + return res; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); + + if (w >= 3) { + /* multiply w by [1/3] */ + t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); + + /* now subtract 3 * [w/3] from w, to get the remainder */ + w -= t+t+t; + + /* fixup the remainder as required since + * the optimization is not exact. + */ + while (w >= 3) { + t += 1; + w -= 3; + } + } else { + t = 0; + } + q.dp[ix] = (mp_digit)t; + } + + /* [optional] store the remainder */ + if (d != NULL) { + *d = (mp_digit)w; + } + + /* [optional] store the quotient */ + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_div_3.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_div_3.c */ + +/* Start: bn_mp_div_d.c */ +#include +#ifdef BN_MP_DIV_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +static int s_is_power_of_two(mp_digit b, int *p) +{ + int x; + + /* fast return if no power of two */ + if ((b==0) || (b & (b-1))) { + return 0; + } + + for (x = 0; x < DIGIT_BIT; x++) { + if (b == (((mp_digit)1)<dp[0] & ((((mp_digit)1)<used)) != MP_OKAY) { + return res; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); + + if (w >= b) { + t = (mp_digit)(w / b); + w -= ((mp_word)t) * ((mp_word)b); + } else { + t = 0; + } + q.dp[ix] = (mp_digit)t; + } + + if (d != NULL) { + *d = (mp_digit)w; + } + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_div_d.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2007/01/09 04:44:32 $ */ + +/* End: bn_mp_div_d.c */ + +/* Start: bn_mp_dr_is_modulus.c */ +#include +#ifdef BN_MP_DR_IS_MODULUS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines if a number is a valid DR modulus */ +int mp_dr_is_modulus(mp_int *a) +{ + int ix; + + /* must be at least two digits */ + if (a->used < 2) { + return 0; + } + + /* must be of the form b**k - a [a <= b] so all + * but the first digit must be equal to -1 (mod b). + */ + for (ix = 1; ix < a->used; ix++) { + if (a->dp[ix] != MP_MASK) { + return 0; + } + } + return 1; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_dr_is_modulus.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_dr_is_modulus.c */ + +/* Start: bn_mp_dr_reduce.c */ +#include +#ifdef BN_MP_DR_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reduce "x" in place modulo "n" using the Diminished Radix algorithm. + * + * Based on algorithm from the paper + * + * "Generating Efficient Primes for Discrete Log Cryptosystems" + * Chae Hoon Lim, Pil Joong Lee, + * POSTECH Information Research Laboratories + * + * The modulus must be of a special format [see manual] + * + * Has been modified to use algorithm 7.10 from the LTM book instead + * + * Input x must be in the range 0 <= x <= (n-1)**2 + */ +int +mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k) +{ + int err, i, m; + mp_word r; + mp_digit mu, *tmpx1, *tmpx2; + + /* m = digits in modulus */ + m = n->used; + + /* ensure that "x" has at least 2m digits */ + if (x->alloc < m + m) { + if ((err = mp_grow (x, m + m)) != MP_OKAY) { + return err; + } + } + +/* top of loop, this is where the code resumes if + * another reduction pass is required. + */ +top: + /* aliases for digits */ + /* alias for lower half of x */ + tmpx1 = x->dp; + + /* alias for upper half of x, or x/B**m */ + tmpx2 = x->dp + m; + + /* set carry to zero */ + mu = 0; + + /* compute (x mod B**m) + k * [x/B**m] inline and inplace */ + for (i = 0; i < m; i++) { + r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu; + *tmpx1++ = (mp_digit)(r & MP_MASK); + mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT)); + } + + /* set final carry */ + *tmpx1++ = mu; + + /* zero words above m */ + for (i = m + 1; i < x->used; i++) { + *tmpx1++ = 0; + } + + /* clamp, sub and return */ + mp_clamp (x); + + /* if x >= n then subtract and reduce again + * Each successive "recursion" makes the input smaller and smaller. + */ + if (mp_cmp_mag (x, n) != MP_LT) { + s_mp_sub(x, n, x); + goto top; + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_dr_reduce.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_dr_reduce.c */ + +/* Start: bn_mp_dr_setup.c */ +#include +#ifdef BN_MP_DR_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines the setup value */ +void mp_dr_setup(mp_int *a, mp_digit *d) +{ + /* the casts are required if DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. DIGIT_BIT==31] + */ + *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - + ((mp_word)a->dp[0])); +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_dr_setup.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_dr_setup.c */ + +/* Start: bn_mp_exch.c */ +#include +#ifdef BN_MP_EXCH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* swap the elements of two integers, for cases where you can't simply swap the + * mp_int pointers around + */ +void +mp_exch (mp_int * a, mp_int * b) +{ + mp_int t; + + t = *a; + *a = *b; + *b = t; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_exch.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_exch.c */ + +/* Start: bn_mp_expt_d.c */ +#include +#ifdef BN_MP_EXPT_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* calculate c = a**b using a square-multiply algorithm */ +int mp_expt_d (mp_int * a, mp_digit b, mp_int * c) +{ + int res, x; + mp_int g; + + if ((res = mp_init_copy (&g, a)) != MP_OKAY) { + return res; + } + + /* set initial result */ + mp_set (c, 1); + + for (x = 0; x < (int) DIGIT_BIT; x++) { + /* square */ + if ((res = mp_sqr (c, c)) != MP_OKAY) { + mp_clear (&g); + return res; + } + + /* if the bit is set multiply */ + if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) { + if ((res = mp_mul (c, &g, c)) != MP_OKAY) { + mp_clear (&g); + return res; + } + } + + /* shift to next bit */ + b <<= 1; + } + + mp_clear (&g); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_expt_d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_expt_d.c */ + +/* Start: bn_mp_exptmod.c */ +#include +#ifdef BN_MP_EXPTMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + + +/* this is a shell function that calls either the normal or Montgomery + * exptmod functions. Originally the call to the montgomery code was + * embedded in the normal function but that wasted alot of stack space + * for nothing (since 99% of the time the Montgomery code would be called) + */ +int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + int dr; + + /* modulus P must be positive */ + if (P->sign == MP_NEG) { + return MP_VAL; + } + + /* if exponent X is negative we have to recurse */ + if (X->sign == MP_NEG) { +#ifdef BN_MP_INVMOD_C + mp_int tmpG, tmpX; + int err; + + /* first compute 1/G mod P */ + if ((err = mp_init(&tmpG)) != MP_OKAY) { + return err; + } + if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { + mp_clear(&tmpG); + return err; + } + + /* now get |X| */ + if ((err = mp_init(&tmpX)) != MP_OKAY) { + mp_clear(&tmpG); + return err; + } + if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; + } + + /* and now compute (1/G)**|X| instead of G**X [X < 0] */ + err = mp_exptmod(&tmpG, &tmpX, P, Y); + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; +#else + /* no invmod */ + return MP_VAL; +#endif + } + +/* modified diminished radix reduction */ +#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C) + if (mp_reduce_is_2k_l(P) == MP_YES) { + return s_mp_exptmod(G, X, P, Y, 1); + } +#endif + +#ifdef BN_MP_DR_IS_MODULUS_C + /* is it a DR modulus? */ + dr = mp_dr_is_modulus(P); +#else + /* default to no */ + dr = 0; +#endif + +#ifdef BN_MP_REDUCE_IS_2K_C + /* if not, is it a unrestricted DR modulus? */ + if (dr == 0) { + dr = mp_reduce_is_2k(P) << 1; + } +#endif + + /* if the modulus is odd or dr != 0 use the montgomery method */ +#ifdef BN_MP_EXPTMOD_FAST_C + if (mp_isodd (P) == 1 || dr != 0) { + return mp_exptmod_fast (G, X, P, Y, dr); + } else { +#endif +#ifdef BN_S_MP_EXPTMOD_C + /* otherwise use the generic Barrett reduction technique */ + return s_mp_exptmod (G, X, P, Y, 0); +#else + /* no exptmod for evens */ + return MP_VAL; +#endif +#ifdef BN_MP_EXPTMOD_FAST_C + } +#endif +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_exptmod.c */ + +/* Start: bn_mp_exptmod_fast.c */ +#include +#ifdef BN_MP_EXPTMOD_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 + * + * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. + * The value of k changes based on the size of the exponent. + * + * Uses Montgomery or Diminished Radix reduction [whichever appropriate] + */ + +#ifdef MP_LOW_MEM + #define TAB_SIZE 32 +#else + #define TAB_SIZE 256 +#endif + +int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) +{ + mp_int M[TAB_SIZE], res; + mp_digit buf, mp; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + + /* use a pointer to the reduction algorithm. This allows us to use + * one of many reduction algorithms without modding the guts of + * the code with if statements everywhere. + */ + int (*redux)(mp_int*,mp_int*,mp_digit); + + /* find window size */ + x = mp_count_bits (X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + +#ifdef MP_LOW_MEM + if (winsize > 5) { + winsize = 5; + } +#endif + + /* init M array */ + /* init first cell */ + if ((err = mp_init(&M[1])) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init(&M[x])) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear (&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* determine and setup reduction code */ + if (redmode == 0) { +#ifdef BN_MP_MONTGOMERY_SETUP_C + /* now setup montgomery */ + if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { + goto LBL_M; + } +#else + err = MP_VAL; + goto LBL_M; +#endif + + /* automatically pick the comba one if available (saves quite a few calls/ifs) */ +#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C + if (((P->used * 2 + 1) < MP_WARRAY) && + P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + redux = fast_mp_montgomery_reduce; + } else +#endif + { +#ifdef BN_MP_MONTGOMERY_REDUCE_C + /* use slower baseline Montgomery method */ + redux = mp_montgomery_reduce; +#else + err = MP_VAL; + goto LBL_M; +#endif + } + } else if (redmode == 1) { +#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C) + /* setup DR reduction for moduli of the form B**k - b */ + mp_dr_setup(P, &mp); + redux = mp_dr_reduce; +#else + err = MP_VAL; + goto LBL_M; +#endif + } else { +#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) + /* setup DR reduction for moduli of the form 2**k - b */ + if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { + goto LBL_M; + } + redux = mp_reduce_2k; +#else + err = MP_VAL; + goto LBL_M; +#endif + } + + /* setup result */ + if ((err = mp_init (&res)) != MP_OKAY) { + goto LBL_M; + } + + /* create M table + * + + * + * The first half of the table is not computed though accept for M[0] and M[1] + */ + + if (redmode == 0) { +#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { + goto LBL_RES; + } +#else + err = MP_VAL; + goto LBL_RES; +#endif + + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { + goto LBL_RES; + } + } else { + mp_set(&res, 1); + if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { + goto LBL_RES; + } + } + + /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ + if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto LBL_RES; + } + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&M[x], P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* then multiply */ + if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + + /* get next bit of the window */ + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + } + } + + if (redmode == 0) { + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ + if ((err = redux(&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* swap res with Y */ + mp_exch (&res, Y); + err = MP_OKAY; +LBL_RES:mp_clear (&res); +LBL_M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear (&M[x]); + } + return err; +} +#endif + + +/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod_fast.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_exptmod_fast.c */ + +/* Start: bn_mp_exteuclid.c */ +#include +#ifdef BN_MP_EXTEUCLID_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Extended euclidean algorithm of (a, b) produces + a*u1 + b*u2 = u3 + */ +int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) +{ + mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp; + int err; + + if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { + return err; + } + + /* initialize, (u1,u2,u3) = (1,0,a) */ + mp_set(&u1, 1); + if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; } + + /* initialize, (v1,v2,v3) = (0,1,b) */ + mp_set(&v2, 1); + if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; } + + /* loop while v3 != 0 */ + while (mp_iszero(&v3) == MP_NO) { + /* q = u3/v3 */ + if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; } + + /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ + if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; } + if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; } + if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; } + if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; } + if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; } + if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; } + + /* (u1,u2,u3) = (v1,v2,v3) */ + if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; } + + /* (v1,v2,v3) = (t1,t2,t3) */ + if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; } + if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; } + } + + /* make sure U3 >= 0 */ + if (u3.sign == MP_NEG) { + mp_neg(&u1, &u1); + mp_neg(&u2, &u2); + mp_neg(&u3, &u3); + } + + /* copy result out */ + if (U1 != NULL) { mp_exch(U1, &u1); } + if (U2 != NULL) { mp_exch(U2, &u2); } + if (U3 != NULL) { mp_exch(U3, &u3); } + + err = MP_OKAY; +_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_exteuclid.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_exteuclid.c */ + +/* Start: bn_mp_fread.c */ +#include +#ifdef BN_MP_FREAD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* read a bigint from a file stream in ASCII */ +int mp_fread(mp_int *a, int radix, FILE *stream) +{ + int err, ch, neg, y; + + /* clear a */ + mp_zero(a); + + /* if first digit is - then set negative */ + ch = fgetc(stream); + if (ch == '-') { + neg = MP_NEG; + ch = fgetc(stream); + } else { + neg = MP_ZPOS; + } + + for (;;) { + /* find y in the radix map */ + for (y = 0; y < radix; y++) { + if (mp_s_rmap[y] == ch) { + break; + } + } + if (y == radix) { + break; + } + + /* shift up and add */ + if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, y, a)) != MP_OKAY) { + return err; + } + + ch = fgetc(stream); + } + if (mp_cmp_d(a, 0) != MP_EQ) { + a->sign = neg; + } + + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_fread.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_fread.c */ + +/* Start: bn_mp_fwrite.c */ +#include +#ifdef BN_MP_FWRITE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +int mp_fwrite(mp_int *a, int radix, FILE *stream) +{ + char *buf; + int err, len, x; + + if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) { + return err; + } + + buf = OPT_CAST(char) XMALLOC (len); + if (buf == NULL) { + return MP_MEM; + } + + if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) { + XFREE (buf); + return err; + } + + for (x = 0; x < len; x++) { + if (fputc(buf[x], stream) == EOF) { + XFREE (buf); + return MP_VAL; + } + } + + XFREE (buf); + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_fwrite.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_fwrite.c */ + +/* Start: bn_mp_gcd.c */ +#include +#ifdef BN_MP_GCD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Greatest Common Divisor using the binary method */ +int mp_gcd (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int u, v; + int k, u_lsb, v_lsb, res; + + /* either zero than gcd is the largest */ + if (mp_iszero (a) == MP_YES) { + return mp_abs (b, c); + } + if (mp_iszero (b) == MP_YES) { + return mp_abs (a, c); + } + + /* get copies of a and b we can modify */ + if ((res = mp_init_copy (&u, a)) != MP_OKAY) { + return res; + } + + if ((res = mp_init_copy (&v, b)) != MP_OKAY) { + goto LBL_U; + } + + /* must be positive for the remainder of the algorithm */ + u.sign = v.sign = MP_ZPOS; + + /* B1. Find the common power of two for u and v */ + u_lsb = mp_cnt_lsb(&u); + v_lsb = mp_cnt_lsb(&v); + k = MIN(u_lsb, v_lsb); + + if (k > 0) { + /* divide the power of two out */ + if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + + if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* divide any remaining factors of two out */ + if (u_lsb != k) { + if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + if (v_lsb != k) { + if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + while (mp_iszero(&v) == 0) { + /* make sure v is the largest */ + if (mp_cmp_mag(&u, &v) == MP_GT) { + /* swap u and v to make sure v is >= u */ + mp_exch(&u, &v); + } + + /* subtract smallest from largest */ + if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) { + goto LBL_V; + } + + /* Divide out all factors of two */ + if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* multiply by 2**k which we divided out at the beginning */ + if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) { + goto LBL_V; + } + c->sign = MP_ZPOS; + res = MP_OKAY; +LBL_V:mp_clear (&u); +LBL_U:mp_clear (&v); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_gcd.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_gcd.c */ + +/* Start: bn_mp_get_int.c */ +#include +#ifdef BN_MP_GET_INT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* get the lower 32-bits of an mp_int */ +unsigned long mp_get_int(mp_int * a) +{ + int i; + unsigned long res; + + if (a->used == 0) { + return 0; + } + + /* get number of digits of the lsb we have to read */ + i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1; + + /* get most significant digit of result */ + res = DIGIT(a,i); + + while (--i >= 0) { + res = (res << DIGIT_BIT) | DIGIT(a,i); + } + + /* force result to 32-bits always so it is consistent on non 32-bit platforms */ + return res & 0xFFFFFFFFUL; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_get_int.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_get_int.c */ + +/* Start: bn_mp_grow.c */ +#include +#ifdef BN_MP_GROW_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* grow as required */ +int mp_grow (mp_int * a, int size) +{ + int i; + mp_digit *tmp; + + /* if the alloc size is smaller alloc more ram */ + if (a->alloc < size) { + /* ensure there are always at least MP_PREC digits extra on top */ + size += (MP_PREC * 2) - (size % MP_PREC); + + /* reallocate the array a->dp + * + * We store the return in a temporary variable + * in case the operation failed we don't want + * to overwrite the dp member of a. + */ + tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size); + if (tmp == NULL) { + /* reallocation failed but "a" is still valid [can be freed] */ + return MP_MEM; + } + + /* reallocation succeeded so set a->dp */ + a->dp = tmp; + + /* zero excess digits */ + i = a->alloc; + a->alloc = size; + for (; i < a->alloc; i++) { + a->dp[i] = 0; + } + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_grow.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_grow.c */ + +/* Start: bn_mp_init.c */ +#include +#ifdef BN_MP_INIT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* init a new mp_int */ +int mp_init (mp_int * a) +{ + int i; + + /* allocate memory required and clear it */ + a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the digits to zero */ + for (i = 0; i < MP_PREC; i++) { + a->dp[i] = 0; + } + + /* set the used to zero, allocated digits to the default precision + * and sign to positive */ + a->used = 0; + a->alloc = MP_PREC; + a->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_init.c */ + +/* Start: bn_mp_init_copy.c */ +#include +#ifdef BN_MP_INIT_COPY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* creates "a" then copies b into it */ +int mp_init_copy (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_init (a)) != MP_OKAY) { + return res; + } + return mp_copy (b, a); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init_copy.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_init_copy.c */ + +/* Start: bn_mp_init_multi.c */ +#include +#ifdef BN_MP_INIT_MULTI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include + +int mp_init_multi(mp_int *mp, ...) +{ + mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ + int n = 0; /* Number of ok inits */ + mp_int* cur_arg = mp; + va_list args; + + va_start(args, mp); /* init args to next argument from caller */ + while (cur_arg != NULL) { + if (mp_init(cur_arg) != MP_OKAY) { + /* Oops - error! Back-track and mp_clear what we already + succeeded in init-ing, then return error. + */ + va_list clean_args; + + /* end the current list */ + va_end(args); + + /* now start cleaning up */ + cur_arg = mp; + va_start(clean_args, mp); + while (n--) { + mp_clear(cur_arg); + cur_arg = va_arg(clean_args, mp_int*); + } + va_end(clean_args); + res = MP_MEM; + break; + } + n++; + cur_arg = va_arg(args, mp_int*); + } + va_end(args); + return res; /* Assumed ok, if error flagged above. */ +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init_multi.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_init_multi.c */ + +/* Start: bn_mp_init_set.c */ +#include +#ifdef BN_MP_INIT_SET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* initialize and set a digit */ +int mp_init_set (mp_int * a, mp_digit b) +{ + int err; + if ((err = mp_init(a)) != MP_OKAY) { + return err; + } + mp_set(a, b); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init_set.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_init_set.c */ + +/* Start: bn_mp_init_set_int.c */ +#include +#ifdef BN_MP_INIT_SET_INT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* initialize and set a digit */ +int mp_init_set_int (mp_int * a, unsigned long b) +{ + int err; + if ((err = mp_init(a)) != MP_OKAY) { + return err; + } + return mp_set_int(a, b); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init_set_int.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_init_set_int.c */ + +/* Start: bn_mp_init_size.c */ +#include +#ifdef BN_MP_INIT_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* init an mp_init for a given size */ +int mp_init_size (mp_int * a, int size) +{ + int x; + + /* pad size so there are always extra digits */ + size += (MP_PREC * 2) - (size % MP_PREC); + + /* alloc mem */ + a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the members */ + a->used = 0; + a->alloc = size; + a->sign = MP_ZPOS; + + /* zero the digits */ + for (x = 0; x < size; x++) { + a->dp[x] = 0; + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_init_size.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_init_size.c */ + +/* Start: bn_mp_invmod.c */ +#include +#ifdef BN_MP_INVMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* hac 14.61, pp608 */ +int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + /* b cannot be negative */ + if (b->sign == MP_NEG || mp_iszero(b) == 1) { + return MP_VAL; + } + +#ifdef BN_FAST_MP_INVMOD_C + /* if the modulus is odd we can use a faster routine instead */ + if (mp_isodd (b) == 1) { + return fast_mp_invmod (a, b, c); + } +#endif + +#ifdef BN_MP_INVMOD_SLOW_C + return mp_invmod_slow(a, b, c); +#endif + + return MP_VAL; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_invmod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_invmod.c */ + +/* Start: bn_mp_invmod_slow.c */ +#include +#ifdef BN_MP_INVMOD_SLOW_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* hac 14.61, pp608 */ +int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x, y, u, v, A, B, C, D; + int res; + + /* b cannot be negative */ + if (b->sign == MP_NEG || mp_iszero(b) == 1) { + return MP_VAL; + } + + /* init temps */ + if ((res = mp_init_multi(&x, &y, &u, &v, + &A, &B, &C, &D, NULL)) != MP_OKAY) { + return res; + } + + /* x = a, y = b */ + if ((res = mp_mod(a, b, &x)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_copy (b, &y)) != MP_OKAY) { + goto LBL_ERR; + } + + /* 2. [modified] if x,y are both even then return an error! */ + if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { + res = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = mp_copy (&x, &u)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_copy (&y, &v)) != MP_OKAY) { + goto LBL_ERR; + } + mp_set (&A, 1); + mp_set (&D, 1); + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto LBL_ERR; + } + /* 4.2 if A or B is odd then */ + if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* A = A/2, B = B/2 */ + if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 5. while v is even do */ + while (mp_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto LBL_ERR; + } + /* 5.2 if C or D is odd then */ + if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* C = C/2, D = D/2 */ + if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 6. if u >= v then */ + if (mp_cmp (&u, &v) != MP_LT) { + /* u = u - v, A = A - C, B = B - D */ + if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* if not zero goto step 4 */ + if (mp_iszero (&u) == 0) + goto top; + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d (&v, 1) != MP_EQ) { + res = MP_VAL; + goto LBL_ERR; + } + + /* if its too low */ + while (mp_cmp_d(&C, 0) == MP_LT) { + if ((res = mp_add(&C, b, &C)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* too big */ + while (mp_cmp_mag(&C, b) != MP_LT) { + if ((res = mp_sub(&C, b, &C)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* C is now the inverse */ + mp_exch (&C, c); + res = MP_OKAY; +LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_invmod_slow.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_invmod_slow.c */ + +/* Start: bn_mp_is_square.c */ +#include +#ifdef BN_MP_IS_SQUARE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Check if remainders are possible squares - fast exclude non-squares */ +static const char rem_128[128] = { + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 +}; + +static const char rem_105[105] = { + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 +}; + +/* Store non-zero to ret if arg is square, and zero if not */ +int mp_is_square(mp_int *arg,int *ret) +{ + int res; + mp_digit c; + mp_int t; + unsigned long r; + + /* Default to Non-square :) */ + *ret = MP_NO; + + if (arg->sign == MP_NEG) { + return MP_VAL; + } + + /* digits used? (TSD) */ + if (arg->used == 0) { + return MP_OKAY; + } + + /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */ + if (rem_128[127 & DIGIT(arg,0)] == 1) { + return MP_OKAY; + } + + /* Next check mod 105 (3*5*7) */ + if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) { + return res; + } + if (rem_105[c] == 1) { + return MP_OKAY; + } + + + if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) { + return res; + } + if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) { + goto ERR; + } + r = mp_get_int(&t); + /* Check for other prime modules, note it's not an ERROR but we must + * free "t" so the easiest way is to goto ERR. We know that res + * is already equal to MP_OKAY from the mp_mod call + */ + if ( (1L<<(r%11)) & 0x5C4L ) goto ERR; + if ( (1L<<(r%13)) & 0x9E4L ) goto ERR; + if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR; + if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR; + if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR; + if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR; + if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR; + + /* Final check - is sqr(sqrt(arg)) == arg ? */ + if ((res = mp_sqrt(arg,&t)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sqr(&t,&t)) != MP_OKAY) { + goto ERR; + } + + *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO; +ERR:mp_clear(&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_is_square.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_is_square.c */ + +/* Start: bn_mp_jacobi.c */ +#include +#ifdef BN_MP_JACOBI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes the jacobi c = (a | n) (or Legendre if n is prime) + * HAC pp. 73 Algorithm 2.149 + */ +int mp_jacobi (mp_int * a, mp_int * p, int *c) +{ + mp_int a1, p1; + int k, s, r, res; + mp_digit residue; + + /* if p <= 0 return MP_VAL */ + if (mp_cmp_d(p, 0) != MP_GT) { + return MP_VAL; + } + + /* step 1. if a == 0, return 0 */ + if (mp_iszero (a) == 1) { + *c = 0; + return MP_OKAY; + } + + /* step 2. if a == 1, return 1 */ + if (mp_cmp_d (a, 1) == MP_EQ) { + *c = 1; + return MP_OKAY; + } + + /* default */ + s = 0; + + /* step 3. write a = a1 * 2**k */ + if ((res = mp_init_copy (&a1, a)) != MP_OKAY) { + return res; + } + + if ((res = mp_init (&p1)) != MP_OKAY) { + goto LBL_A1; + } + + /* divide out larger power of two */ + k = mp_cnt_lsb(&a1); + if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) { + goto LBL_P1; + } + + /* step 4. if e is even set s=1 */ + if ((k & 1) == 0) { + s = 1; + } else { + /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */ + residue = p->dp[0] & 7; + + if (residue == 1 || residue == 7) { + s = 1; + } else if (residue == 3 || residue == 5) { + s = -1; + } + } + + /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */ + if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) { + s = -s; + } + + /* if a1 == 1 we're done */ + if (mp_cmp_d (&a1, 1) == MP_EQ) { + *c = s; + } else { + /* n1 = n mod a1 */ + if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) { + goto LBL_P1; + } + if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) { + goto LBL_P1; + } + *c = s * r; + } + + /* done */ + res = MP_OKAY; +LBL_P1:mp_clear (&p1); +LBL_A1:mp_clear (&a1); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_jacobi.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_jacobi.c */ + +/* Start: bn_mp_karatsuba_mul.c */ +#include +#ifdef BN_MP_KARATSUBA_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* c = |a| * |b| using Karatsuba Multiplication using + * three half size multiplications + * + * Let B represent the radix [e.g. 2**DIGIT_BIT] and + * let n represent half of the number of digits in + * the min(a,b) + * + * a = a1 * B**n + a0 + * b = b1 * B**n + b0 + * + * Then, a * b => + a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0 + * + * Note that a1b1 and a0b0 are used twice and only need to be + * computed once. So in total three half size (half # of + * digit) multiplications are performed, a0b0, a1b1 and + * (a1+b1)(a0+b0) + * + * Note that a multiplication of half the digits requires + * 1/4th the number of single precision multiplications so in + * total after one call 25% of the single precision multiplications + * are saved. Note also that the call to mp_mul can end up back + * in this function if the a0, a1, b0, or b1 are above the threshold. + * This is known as divide-and-conquer and leads to the famous + * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than + * the standard O(N**2) that the baseline/comba methods use. + * Generally though the overhead of this method doesn't pay off + * until a certain size (N ~ 80) is reached. + */ +int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x0, x1, y0, y1, t1, x0y0, x1y1; + int B, err; + + /* default the return code to an error */ + err = MP_MEM; + + /* min # of digits */ + B = MIN (a->used, b->used); + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if (mp_init_size (&x0, B) != MP_OKAY) + goto ERR; + if (mp_init_size (&x1, a->used - B) != MP_OKAY) + goto X0; + if (mp_init_size (&y0, B) != MP_OKAY) + goto X1; + if (mp_init_size (&y1, b->used - B) != MP_OKAY) + goto Y0; + + /* init temps */ + if (mp_init_size (&t1, B * 2) != MP_OKAY) + goto Y1; + if (mp_init_size (&x0y0, B * 2) != MP_OKAY) + goto T1; + if (mp_init_size (&x1y1, B * 2) != MP_OKAY) + goto X0Y0; + + /* now shift the digits */ + x0.used = y0.used = B; + x1.used = a->used - B; + y1.used = b->used - B; + + { + register int x; + register mp_digit *tmpa, *tmpb, *tmpx, *tmpy; + + /* we copy the digits directly instead of using higher level functions + * since we also need to shift the digits + */ + tmpa = a->dp; + tmpb = b->dp; + + tmpx = x0.dp; + tmpy = y0.dp; + for (x = 0; x < B; x++) { + *tmpx++ = *tmpa++; + *tmpy++ = *tmpb++; + } + + tmpx = x1.dp; + for (x = B; x < a->used; x++) { + *tmpx++ = *tmpa++; + } + + tmpy = y1.dp; + for (x = B; x < b->used; x++) { + *tmpy++ = *tmpb++; + } + } + + /* only need to clamp the lower words since by definition the + * upper words x1/y1 must have a known number of digits + */ + mp_clamp (&x0); + mp_clamp (&y0); + + /* now calc the products x0y0 and x1y1 */ + /* after this x0 is no longer required, free temp [x0==t2]! */ + if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY) + goto X1Y1; /* x0y0 = x0*y0 */ + if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY) + goto X1Y1; /* x1y1 = x1*y1 */ + + /* now calc x1+x0 and y1+y0 */ + if (s_mp_add (&x1, &x0, &t1) != MP_OKAY) + goto X1Y1; /* t1 = x1 - x0 */ + if (s_mp_add (&y1, &y0, &x0) != MP_OKAY) + goto X1Y1; /* t2 = y1 - y0 */ + if (mp_mul (&t1, &x0, &t1) != MP_OKAY) + goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */ + + /* add x0y0 */ + if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY) + goto X1Y1; /* t2 = x0y0 + x1y1 */ + if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY) + goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */ + + /* shift by B */ + if (mp_lshd (&t1, B) != MP_OKAY) + goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))< +#ifdef BN_MP_KARATSUBA_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Karatsuba squaring, computes b = a*a using three + * half size squarings + * + * See comments of karatsuba_mul for details. It + * is essentially the same algorithm but merely + * tuned to perform recursive squarings. + */ +int mp_karatsuba_sqr (mp_int * a, mp_int * b) +{ + mp_int x0, x1, t1, t2, x0x0, x1x1; + int B, err; + + err = MP_MEM; + + /* min # of digits */ + B = a->used; + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if (mp_init_size (&x0, B) != MP_OKAY) + goto ERR; + if (mp_init_size (&x1, a->used - B) != MP_OKAY) + goto X0; + + /* init temps */ + if (mp_init_size (&t1, a->used * 2) != MP_OKAY) + goto X1; + if (mp_init_size (&t2, a->used * 2) != MP_OKAY) + goto T1; + if (mp_init_size (&x0x0, B * 2) != MP_OKAY) + goto T2; + if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY) + goto X0X0; + + { + register int x; + register mp_digit *dst, *src; + + src = a->dp; + + /* now shift the digits */ + dst = x0.dp; + for (x = 0; x < B; x++) { + *dst++ = *src++; + } + + dst = x1.dp; + for (x = B; x < a->used; x++) { + *dst++ = *src++; + } + } + + x0.used = B; + x1.used = a->used - B; + + mp_clamp (&x0); + + /* now calc the products x0*x0 and x1*x1 */ + if (mp_sqr (&x0, &x0x0) != MP_OKAY) + goto X1X1; /* x0x0 = x0*x0 */ + if (mp_sqr (&x1, &x1x1) != MP_OKAY) + goto X1X1; /* x1x1 = x1*x1 */ + + /* now calc (x1+x0)**2 */ + if (s_mp_add (&x1, &x0, &t1) != MP_OKAY) + goto X1X1; /* t1 = x1 - x0 */ + if (mp_sqr (&t1, &t1) != MP_OKAY) + goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */ + + /* add x0y0 */ + if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY) + goto X1X1; /* t2 = x0x0 + x1x1 */ + if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY) + goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */ + + /* shift by B */ + if (mp_lshd (&t1, B) != MP_OKAY) + goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))< +#ifdef BN_MP_LCM_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes least common multiple as |a*b|/(a, b) */ +int mp_lcm (mp_int * a, mp_int * b, mp_int * c) +{ + int res; + mp_int t1, t2; + + + if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) { + return res; + } + + /* t1 = get the GCD of the two inputs */ + if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) { + goto LBL_T; + } + + /* divide the smallest by the GCD */ + if (mp_cmp_mag(a, b) == MP_LT) { + /* store quotient in t2 such that t2 * b is the LCM */ + if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + res = mp_mul(b, &t2, c); + } else { + /* store quotient in t2 such that t2 * a is the LCM */ + if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + res = mp_mul(a, &t2, c); + } + + /* fix the sign to positive */ + c->sign = MP_ZPOS; + +LBL_T: + mp_clear_multi (&t1, &t2, NULL); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_lcm.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_lcm.c */ + +/* Start: bn_mp_lshd.c */ +#include +#ifdef BN_MP_LSHD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* shift left a certain amount of digits */ +int mp_lshd (mp_int * a, int b) +{ + int x, res; + + /* if its less than zero return */ + if (b <= 0) { + return MP_OKAY; + } + + /* grow to fit the new digits */ + if (a->alloc < a->used + b) { + if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { + return res; + } + } + + { + register mp_digit *top, *bottom; + + /* increment the used by the shift amount then copy upwards */ + a->used += b; + + /* top */ + top = a->dp + a->used - 1; + + /* base */ + bottom = a->dp + a->used - 1 - b; + + /* much like mp_rshd this is implemented using a sliding window + * except the window goes the otherway around. Copying from + * the bottom to the top. see bn_mp_rshd.c for more info. + */ + for (x = a->used - 1; x >= b; x--) { + *top-- = *bottom--; + } + + /* zero the lower digits */ + top = a->dp; + for (x = 0; x < b; x++) { + *top++ = 0; + } + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_lshd.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_lshd.c */ + +/* Start: bn_mp_mod.c */ +#include +#ifdef BN_MP_MOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* c = a mod b, 0 <= c < b */ +int +mp_mod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int t; + int res; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + if (t.sign != b->sign) { + res = mp_add (b, &t, c); + } else { + res = MP_OKAY; + mp_exch (&t, c); + } + + mp_clear (&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_mod.c */ + +/* Start: bn_mp_mod_2d.c */ +#include +#ifdef BN_MP_MOD_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* calc a value mod 2**b */ +int +mp_mod_2d (mp_int * a, int b, mp_int * c) +{ + int x, res; + + /* if b is <= 0 then zero the int */ + if (b <= 0) { + mp_zero (c); + return MP_OKAY; + } + + /* if the modulus is larger than the value than return */ + if (b >= (int) (a->used * DIGIT_BIT)) { + res = mp_copy (a, c); + return res; + } + + /* copy */ + if ((res = mp_copy (a, c)) != MP_OKAY) { + return res; + } + + /* zero digits above the last digit of the modulus */ + for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { + c->dp[x] = 0; + } + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / DIGIT_BIT] &= + (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); + mp_clamp (c); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mod_2d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_mod_2d.c */ + +/* Start: bn_mp_mod_d.c */ +#include +#ifdef BN_MP_MOD_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +int +mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) +{ + return mp_div_d(a, b, NULL, c); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mod_d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_mod_d.c */ + +/* Start: bn_mp_montgomery_calc_normalization.c */ +#include +#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* + * shifts with subtractions when the result is greater than b. + * + * The method is slightly modified to shift B unconditionally upto just under + * the leading bit of b. This saves alot of multiple precision shifting. + */ +int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) +{ + int x, bits, res; + + /* how many bits of last digit does b use */ + bits = mp_count_bits (b) % DIGIT_BIT; + + if (b->used > 1) { + if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { + return res; + } + } else { + mp_set(a, 1); + bits = 1; + } + + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int)DIGIT_BIT; x++) { + if ((res = mp_mul_2 (a, a)) != MP_OKAY) { + return res; + } + if (mp_cmp_mag (a, b) != MP_LT) { + if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { + return res; + } + } + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_calc_normalization.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_montgomery_calc_normalization.c */ + +/* Start: bn_mp_montgomery_reduce.c */ +#include +#ifdef BN_MP_MONTGOMERY_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes xR**-1 == x (mod N) via Montgomery Reduction */ +int +mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +{ + int ix, res, digs; + mp_digit mu; + + /* can the fast reduction [comba] method be used? + * + * Note that unlike in mul you're safely allowed *less* + * than the available columns [255 per default] since carries + * are fixed up in the inner loop. + */ + digs = n->used * 2 + 1; + if ((digs < MP_WARRAY) && + n->used < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_mp_montgomery_reduce (x, n, rho); + } + + /* grow the input as required */ + if (x->alloc < digs) { + if ((res = mp_grow (x, digs)) != MP_OKAY) { + return res; + } + } + x->used = digs; + + for (ix = 0; ix < n->used; ix++) { + /* mu = ai * rho mod b + * + * The value of rho must be precalculated via + * montgomery_setup() such that + * it equals -1/n0 mod b this allows the + * following inner loop to reduce the + * input one digit at a time + */ + mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK); + + /* a = a + mu * m * b**i */ + { + register int iy; + register mp_digit *tmpn, *tmpx, u; + register mp_word r; + + /* alias for digits of the modulus */ + tmpn = n->dp; + + /* alias for the digits of x [the input] */ + tmpx = x->dp + ix; + + /* set the carry to zero */ + u = 0; + + /* Multiply and add in place */ + for (iy = 0; iy < n->used; iy++) { + /* compute product and sum */ + r = ((mp_word)mu) * ((mp_word)*tmpn++) + + ((mp_word) u) + ((mp_word) * tmpx); + + /* get carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + + /* fix digit */ + *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK)); + } + /* At this point the ix'th digit of x should be zero */ + + + /* propagate carries upwards as required*/ + while (u) { + *tmpx += u; + u = *tmpx >> DIGIT_BIT; + *tmpx++ &= MP_MASK; + } + } + } + + /* at this point the n.used'th least + * significant digits of x are all zero + * which means we can shift x to the + * right by n.used digits and the + * residue is unchanged. + */ + + /* x = x/b**n.used */ + mp_clamp(x); + mp_rshd (x, n->used); + + /* if x >= n then x = x - n */ + if (mp_cmp_mag (x, n) != MP_LT) { + return s_mp_sub (x, n, x); + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_reduce.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_montgomery_reduce.c */ + +/* Start: bn_mp_montgomery_setup.c */ +#include +#ifdef BN_MP_MONTGOMERY_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* setups the montgomery reduction stuff */ +int +mp_montgomery_setup (mp_int * n, mp_digit * rho) +{ + mp_digit x, b; + +/* fast inversion mod 2**k + * + * Based on the fact that + * + * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) + * => 2*X*A - X*X*A*A = 1 + * => 2*(1) - (1) = 1 + */ + b = n->dp[0]; + + if ((b & 1) == 0) { + return MP_VAL; + } + + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ +#if !defined(MP_8BIT) + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ +#endif +#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT)) + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ +#endif +#ifdef MP_64BIT + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ +#endif + + /* rho = -1/m mod b */ + *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK; + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_setup.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_montgomery_setup.c */ + +/* Start: bn_mp_mul.c */ +#include +#ifdef BN_MP_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* high level multiplication (handles sign) */ +int mp_mul (mp_int * a, mp_int * b, mp_int * c) +{ + int res, neg; + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + + /* use Toom-Cook? */ +#ifdef BN_MP_TOOM_MUL_C + if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { + res = mp_toom_mul(a, b, c); + } else +#endif +#ifdef BN_MP_KARATSUBA_MUL_C + /* use Karatsuba? */ + if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { + res = mp_karatsuba_mul (a, b, c); + } else +#endif + { + /* can we use the fast multiplier? + * + * The fast multiplier can be used if the output will + * have less than MP_WARRAY digits and the number of + * digits won't affect carry propagation + */ + int digs = a->used + b->used + 1; + +#ifdef BN_FAST_S_MP_MUL_DIGS_C + if ((digs < MP_WARRAY) && + MIN(a->used, b->used) <= + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + res = fast_s_mp_mul_digs (a, b, c, digs); + } else +#endif +#ifdef BN_S_MP_MUL_DIGS_C + res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */ +#else + res = MP_VAL; +#endif + + } + c->sign = (c->used > 0) ? neg : MP_ZPOS; + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mul.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_mul.c */ + +/* Start: bn_mp_mul_2.c */ +#include +#ifdef BN_MP_MUL_2_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* b = a*2 */ +int mp_mul_2(mp_int * a, mp_int * b) +{ + int x, res, oldused; + + /* grow to accomodate result */ + if (b->alloc < a->used + 1) { + if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { + return res; + } + } + + oldused = b->used; + b->used = a->used; + + { + register mp_digit r, rr, *tmpa, *tmpb; + + /* alias for source */ + tmpa = a->dp; + + /* alias for dest */ + tmpb = b->dp; + + /* carry */ + r = 0; + for (x = 0; x < a->used; x++) { + + /* get what will be the *next* carry bit from the + * MSB of the current digit + */ + rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); + + /* now shift up this digit, add in the carry [from the previous] */ + *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; + + /* copy the carry that would be from the source + * digit into the next iteration + */ + r = rr; + } + + /* new leading digit? */ + if (r != 0) { + /* add a MSB which is always 1 at this point */ + *tmpb = 1; + ++(b->used); + } + + /* now zero any excess digits on the destination + * that we didn't write to + */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_mul_2.c */ + +/* Start: bn_mp_mul_2d.c */ +#include +#ifdef BN_MP_MUL_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* shift left by a certain bit count */ +int mp_mul_2d (mp_int * a, int b, mp_int * c) +{ + mp_digit d; + int res; + + /* copy */ + if (a != c) { + if ((res = mp_copy (a, c)) != MP_OKAY) { + return res; + } + } + + if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) { + if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { + return res; + } + } + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { + return res; + } + } + + /* shift any bit count < DIGIT_BIT */ + d = (mp_digit) (b % DIGIT_BIT); + if (d != 0) { + register mp_digit *tmpc, shift, mask, r, rr; + register int x; + + /* bitmask for carries */ + mask = (((mp_digit)1) << d) - 1; + + /* shift for msbs */ + shift = DIGIT_BIT - d; + + /* alias */ + tmpc = c->dp; + + /* carry */ + r = 0; + for (x = 0; x < c->used; x++) { + /* get the higher bits of the current word */ + rr = (*tmpc >> shift) & mask; + + /* shift the current word and OR in the carry */ + *tmpc = ((*tmpc << d) | r) & MP_MASK; + ++tmpc; + + /* set the carry to the carry bits of the current word */ + r = rr; + } + + /* set final carry */ + if (r != 0) { + c->dp[(c->used)++] = r; + } + } + mp_clamp (c); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_mul_2d.c */ + +/* Start: bn_mp_mul_d.c */ +#include +#ifdef BN_MP_MUL_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* multiply by a digit */ +int +mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +{ + mp_digit u, *tmpa, *tmpc; + mp_word r; + int ix, res, olduse; + + /* make sure c is big enough to hold a*b */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* get the original destinations used count */ + olduse = c->used; + + /* set the sign */ + c->sign = a->sign; + + /* alias for a->dp [source] */ + tmpa = a->dp; + + /* alias for c->dp [dest] */ + tmpc = c->dp; + + /* zero carry */ + u = 0; + + /* compute columns */ + for (ix = 0; ix < a->used; ix++) { + /* compute product and carry sum for this term */ + r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b); + + /* mask off higher bits to get a single digit */ + *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* send carry into next iteration */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + + /* store final carry [if any] and increment ix offset */ + *tmpc++ = u; + ++ix; + + /* now zero digits above the top */ + while (ix++ < olduse) { + *tmpc++ = 0; + } + + /* set used count */ + c->used = a->used + 1; + mp_clamp(c); + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mul_d.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_mul_d.c */ + +/* Start: bn_mp_mulmod.c */ +#include +#ifdef BN_MP_MULMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* d = a * b (mod c) */ +int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_mul (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, c, d); + mp_clear (&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_mulmod.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_mulmod.c */ + +/* Start: bn_mp_n_root.c */ +#include +#ifdef BN_MP_N_ROOT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* find the n'th root of an integer + * + * Result found such that (c)**b <= a and (c+1)**b > a + * + * This algorithm uses Newton's approximation + * x[i+1] = x[i] - f(x[i])/f'(x[i]) + * which will find the root in log(N) time where + * each step involves a fair bit. This is not meant to + * find huge roots [square and cube, etc]. + */ +int mp_n_root (mp_int * a, mp_digit b, mp_int * c) +{ + mp_int t1, t2, t3; + int res, neg; + + /* input must be positive if b is even */ + if ((b & 1) == 0 && a->sign == MP_NEG) { + return MP_VAL; + } + + if ((res = mp_init (&t1)) != MP_OKAY) { + return res; + } + + if ((res = mp_init (&t2)) != MP_OKAY) { + goto LBL_T1; + } + + if ((res = mp_init (&t3)) != MP_OKAY) { + goto LBL_T2; + } + + /* if a is negative fudge the sign but keep track */ + neg = a->sign; + a->sign = MP_ZPOS; + + /* t2 = 2 */ + mp_set (&t2, 2); + + do { + /* t1 = t2 */ + if ((res = mp_copy (&t2, &t1)) != MP_OKAY) { + goto LBL_T3; + } + + /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ + + /* t3 = t1**(b-1) */ + if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) { + goto LBL_T3; + } + + /* numerator */ + /* t2 = t1**b */ + if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) { + goto LBL_T3; + } + + /* t2 = t1**b - a */ + if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) { + goto LBL_T3; + } + + /* denominator */ + /* t3 = t1**(b-1) * b */ + if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) { + goto LBL_T3; + } + + /* t3 = (t1**b - a)/(b * t1**(b-1)) */ + if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) { + goto LBL_T3; + } + + if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) { + goto LBL_T3; + } + } while (mp_cmp (&t1, &t2) != MP_EQ); + + /* result can be off by a few so check */ + for (;;) { + if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) { + goto LBL_T3; + } + + if (mp_cmp (&t2, a) == MP_GT) { + if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) { + goto LBL_T3; + } + } else { + break; + } + } + + /* reset the sign of a first */ + a->sign = neg; + + /* set the result */ + mp_exch (&t1, c); + + /* set the sign of the result */ + c->sign = neg; + + res = MP_OKAY; + +LBL_T3:mp_clear (&t3); +LBL_T2:mp_clear (&t2); +LBL_T1:mp_clear (&t1); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_n_root.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_n_root.c */ + +/* Start: bn_mp_neg.c */ +#include +#ifdef BN_MP_NEG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* b = -a */ +int mp_neg (mp_int * a, mp_int * b) +{ + int res; + if (a != b) { + if ((res = mp_copy (a, b)) != MP_OKAY) { + return res; + } + } + + if (mp_iszero(b) != MP_YES) { + b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; + } else { + b->sign = MP_ZPOS; + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_neg.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_neg.c */ + +/* Start: bn_mp_or.c */ +#include +#ifdef BN_MP_OR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* OR two ints together */ +int mp_or (mp_int * a, mp_int * b, mp_int * c) +{ + int res, ix, px; + mp_int t, *x; + + if (a->used > b->used) { + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + px = b->used; + x = b; + } else { + if ((res = mp_init_copy (&t, b)) != MP_OKAY) { + return res; + } + px = a->used; + x = a; + } + + for (ix = 0; ix < px; ix++) { + t.dp[ix] |= x->dp[ix]; + } + mp_clamp (&t); + mp_exch (c, &t); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_or.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_or.c */ + +/* Start: bn_mp_prime_fermat.c */ +#include +#ifdef BN_MP_PRIME_FERMAT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* performs one Fermat test. + * + * If "a" were prime then b**a == b (mod a) since the order of + * the multiplicative sub-group would be phi(a) = a-1. That means + * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a). + * + * Sets result to 1 if the congruence holds, or zero otherwise. + */ +int mp_prime_fermat (mp_int * a, mp_int * b, int *result) +{ + mp_int t; + int err; + + /* default to composite */ + *result = MP_NO; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1) != MP_GT) { + return MP_VAL; + } + + /* init t */ + if ((err = mp_init (&t)) != MP_OKAY) { + return err; + } + + /* compute t = b**a mod a */ + if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) { + goto LBL_T; + } + + /* is it equal to b? */ + if (mp_cmp (&t, b) == MP_EQ) { + *result = MP_YES; + } + + err = MP_OKAY; +LBL_T:mp_clear (&t); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_fermat.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_prime_fermat.c */ + +/* Start: bn_mp_prime_is_divisible.c */ +#include +#ifdef BN_MP_PRIME_IS_DIVISIBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines if an integers is divisible by one + * of the first PRIME_SIZE primes or not + * + * sets result to 0 if not, 1 if yes + */ +int mp_prime_is_divisible (mp_int * a, int *result) +{ + int err, ix; + mp_digit res; + + /* default to not */ + *result = MP_NO; + + for (ix = 0; ix < PRIME_SIZE; ix++) { + /* what is a mod LBL_prime_tab[ix] */ + if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) { + return err; + } + + /* is the residue zero? */ + if (res == 0) { + *result = MP_YES; + return MP_OKAY; + } + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_divisible.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_prime_is_divisible.c */ + +/* Start: bn_mp_prime_is_prime.c */ +#include +#ifdef BN_MP_PRIME_IS_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* performs a variable number of rounds of Miller-Rabin + * + * Probability of error after t rounds is no more than + + * + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime (mp_int * a, int t, int *result) +{ + mp_int b; + int ix, err, res; + + /* default to no */ + *result = MP_NO; + + /* valid value of t? */ + if (t <= 0 || t > PRIME_SIZE) { + return MP_VAL; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < PRIME_SIZE; ix++) { + if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) { + *result = 1; + return MP_OKAY; + } + } + + /* first perform trial division */ + if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res == MP_YES) { + return MP_OKAY; + } + + /* now perform the miller-rabin rounds */ + if ((err = mp_init (&b)) != MP_OKAY) { + return err; + } + + for (ix = 0; ix < t; ix++) { + /* set the prime */ + mp_set (&b, ltm_prime_tab[ix]); + + if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + + if (res == MP_NO) { + goto LBL_B; + } + } + + /* passed the test */ + *result = MP_YES; +LBL_B:mp_clear (&b); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_prime.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_prime_is_prime.c */ + +/* Start: bn_mp_prime_miller_rabin.c */ +#include +#ifdef BN_MP_PRIME_MILLER_RABIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Miller-Rabin test of "a" to the base of "b" as described in + * HAC pp. 139 Algorithm 4.24 + * + * Sets result to 0 if definitely composite or 1 if probably prime. + * Randomly the chance of error is no more than 1/4 and often + * very much lower. + */ +int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result) +{ + mp_int n1, y, r; + int s, j, err; + + /* default */ + *result = MP_NO; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1) != MP_GT) { + return MP_VAL; + } + + /* get n1 = a - 1 */ + if ((err = mp_init_copy (&n1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) { + goto LBL_N1; + } + + /* set 2**s * r = n1 */ + if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) { + goto LBL_N1; + } + + /* count the number of least significant bits + * which are zero + */ + s = mp_cnt_lsb(&r); + + /* now divide n - 1 by 2**s */ + if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) { + goto LBL_R; + } + + /* compute y = b**r mod a */ + if ((err = mp_init (&y)) != MP_OKAY) { + goto LBL_R; + } + if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) { + goto LBL_Y; + } + + /* if y != 1 and y != n1 do */ + if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) { + j = 1; + /* while j <= s-1 and y != n1 */ + while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) { + if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) { + goto LBL_Y; + } + + /* if y == 1 then composite */ + if (mp_cmp_d (&y, 1) == MP_EQ) { + goto LBL_Y; + } + + ++j; + } + + /* if y != n1 then composite */ + if (mp_cmp (&y, &n1) != MP_EQ) { + goto LBL_Y; + } + } + + /* probably prime now */ + *result = MP_YES; +LBL_Y:mp_clear (&y); +LBL_R:mp_clear (&r); +LBL_N1:mp_clear (&n1); + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_miller_rabin.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_prime_miller_rabin.c */ + +/* Start: bn_mp_prime_next_prime.c */ +#include +#ifdef BN_MP_PRIME_NEXT_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + * + * bbs_style = 1 means the prime must be congruent to 3 mod 4 + */ +int mp_prime_next_prime(mp_int *a, int t, int bbs_style) +{ + int err, res, x, y; + mp_digit res_tab[PRIME_SIZE], step, kstep; + mp_int b; + + /* ensure t is valid */ + if (t <= 0 || t > PRIME_SIZE) { + return MP_VAL; + } + + /* force positive */ + a->sign = MP_ZPOS; + + /* simple algo if a is less than the largest prime in the table */ + if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) { + /* find which prime it is bigger than */ + for (x = PRIME_SIZE - 2; x >= 0; x--) { + if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) { + if (bbs_style == 1) { + /* ok we found a prime smaller or + * equal [so the next is larger] + * + * however, the prime must be + * congruent to 3 mod 4 + */ + if ((ltm_prime_tab[x + 1] & 3) != 3) { + /* scan upwards for a prime congruent to 3 mod 4 */ + for (y = x + 1; y < PRIME_SIZE; y++) { + if ((ltm_prime_tab[y] & 3) == 3) { + mp_set(a, ltm_prime_tab[y]); + return MP_OKAY; + } + } + } + } else { + mp_set(a, ltm_prime_tab[x + 1]); + return MP_OKAY; + } + } + } + /* at this point a maybe 1 */ + if (mp_cmp_d(a, 1) == MP_EQ) { + mp_set(a, 2); + return MP_OKAY; + } + /* fall through to the sieve */ + } + + /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */ + if (bbs_style == 1) { + kstep = 4; + } else { + kstep = 2; + } + + /* at this point we will use a combination of a sieve and Miller-Rabin */ + + if (bbs_style == 1) { + /* if a mod 4 != 3 subtract the correct value to make it so */ + if ((a->dp[0] & 3) != 3) { + if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; }; + } + } else { + if (mp_iseven(a) == 1) { + /* force odd */ + if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { + return err; + } + } + } + + /* generate the restable */ + for (x = 1; x < PRIME_SIZE; x++) { + if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) { + return err; + } + } + + /* init temp used for Miller-Rabin Testing */ + if ((err = mp_init(&b)) != MP_OKAY) { + return err; + } + + for (;;) { + /* skip to the next non-trivially divisible candidate */ + step = 0; + do { + /* y == 1 if any residue was zero [e.g. cannot be prime] */ + y = 0; + + /* increase step to next candidate */ + step += kstep; + + /* compute the new residue without using division */ + for (x = 1; x < PRIME_SIZE; x++) { + /* add the step to each residue */ + res_tab[x] += kstep; + + /* subtract the modulus [instead of using division] */ + if (res_tab[x] >= ltm_prime_tab[x]) { + res_tab[x] -= ltm_prime_tab[x]; + } + + /* set flag if zero */ + if (res_tab[x] == 0) { + y = 1; + } + } + } while (y == 1 && step < ((((mp_digit)1)<= ((((mp_digit)1)< +#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + + +static const struct { + int k, t; +} sizes[] = { +{ 128, 28 }, +{ 256, 16 }, +{ 384, 10 }, +{ 512, 7 }, +{ 640, 6 }, +{ 768, 5 }, +{ 896, 4 }, +{ 1024, 4 } +}; + +/* returns # of RM trials required for a given bit size */ +int mp_prime_rabin_miller_trials(int size) +{ + int x; + + for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) { + if (sizes[x].k == size) { + return sizes[x].t; + } else if (sizes[x].k > size) { + return (x == 0) ? sizes[0].t : sizes[x - 1].t; + } + } + return sizes[x-1].t + 1; +} + + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_rabin_miller_trials.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_prime_rabin_miller_trials.c */ + +/* Start: bn_mp_prime_random_ex.c */ +#include +#ifdef BN_MP_PRIME_RANDOM_EX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * LTM_PRIME_BBS - make prime congruent to 3 mod 4 + * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) + * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero + * LTM_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ + +/* This is possibly the mother of all prime generation functions, muahahahahaha! */ +int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat) +{ + unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb; + int res, err, bsize, maskOR_msb_offset; + + /* sanity check the input */ + if (size <= 1 || t <= 0) { + return MP_VAL; + } + + /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */ + if (flags & LTM_PRIME_SAFE) { + flags |= LTM_PRIME_BBS; + } + + /* calc the byte size */ + bsize = (size>>3) + ((size&7)?1:0); + + /* we need a buffer of bsize bytes */ + tmp = OPT_CAST(unsigned char) XMALLOC(bsize); + if (tmp == NULL) { + return MP_MEM; + } + + /* calc the maskAND value for the MSbyte*/ + maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7))); + + /* calc the maskOR_msb */ + maskOR_msb = 0; + maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0; + if (flags & LTM_PRIME_2MSB_ON) { + maskOR_msb |= 0x80 >> ((9 - size) & 7); + } + + /* get the maskOR_lsb */ + maskOR_lsb = 1; + if (flags & LTM_PRIME_BBS) { + maskOR_lsb |= 3; + } + + do { + /* read the bytes */ + if (cb(tmp, bsize, dat) != bsize) { + err = MP_VAL; + goto error; + } + + /* work over the MSbyte */ + tmp[0] &= maskAND; + tmp[0] |= 1 << ((size - 1) & 7); + + /* mix in the maskORs */ + tmp[maskOR_msb_offset] |= maskOR_msb; + tmp[bsize-1] |= maskOR_lsb; + + /* read it in */ + if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { goto error; } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; } + if (res == MP_NO) { + continue; + } + + if (flags & LTM_PRIME_SAFE) { + /* see if (a-1)/2 is prime */ + if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { goto error; } + if ((err = mp_div_2(a, a)) != MP_OKAY) { goto error; } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { goto error; } + } + } while (res == MP_NO); + + if (flags & LTM_PRIME_SAFE) { + /* restore a to the original value */ + if ((err = mp_mul_2(a, a)) != MP_OKAY) { goto error; } + if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { goto error; } + } + + err = MP_OKAY; +error: + XFREE(tmp); + return err; +} + + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_prime_random_ex.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_prime_random_ex.c */ + +/* Start: bn_mp_radix_size.c */ +#include +#ifdef BN_MP_RADIX_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* returns size of ASCII reprensentation */ +int mp_radix_size (mp_int * a, int radix, int *size) +{ + int res, digs; + mp_int t; + mp_digit d; + + *size = 0; + + /* special case for binary */ + if (radix == 2) { + *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; + return MP_OKAY; + } + + /* make sure the radix is in range */ + if (radix < 2 || radix > 64) { + return MP_VAL; + } + + if (mp_iszero(a) == MP_YES) { + *size = 2; + return MP_OKAY; + } + + /* digs is the digit count */ + digs = 0; + + /* if it's negative add one for the sign */ + if (a->sign == MP_NEG) { + ++digs; + } + + /* init a copy of the input */ + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* force temp to positive */ + t.sign = MP_ZPOS; + + /* fetch out all of the digits */ + while (mp_iszero (&t) == MP_NO) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + ++digs; + } + mp_clear (&t); + + /* return digs + 1, the 1 is for the NULL byte that would be required. */ + *size = digs + 1; + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_radix_size.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_radix_size.c */ + +/* Start: bn_mp_radix_smap.c */ +#include +#ifdef BN_MP_RADIX_SMAP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* chars used in radix conversions */ +const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_radix_smap.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_radix_smap.c */ + +/* Start: bn_mp_rand.c */ +#include +#ifdef BN_MP_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* makes a pseudo-random int of a given size */ +int +mp_rand (mp_int * a, int digits) +{ + int res; + mp_digit d; + + mp_zero (a); + if (digits <= 0) { + return MP_OKAY; + } + + /* first place a random non-zero digit */ + do { + d = ((mp_digit) abs (rand ())) & MP_MASK; + } while (d == 0); + + if ((res = mp_add_d (a, d, a)) != MP_OKAY) { + return res; + } + + while (--digits > 0) { + if ((res = mp_lshd (a, 1)) != MP_OKAY) { + return res; + } + + if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) { + return res; + } + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_rand.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_rand.c */ + +/* Start: bn_mp_read_radix.c */ +#include +#ifdef BN_MP_READ_RADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* read a string [ASCII] in a given radix */ +int mp_read_radix (mp_int * a, const char *str, int radix) +{ + int y, res, neg; + char ch; + + /* zero the digit bignum */ + mp_zero(a); + + /* make sure the radix is ok */ + if (radix < 2 || radix > 64) { + return MP_VAL; + } + + /* if the leading digit is a + * minus set the sign to negative. + */ + if (*str == '-') { + ++str; + neg = MP_NEG; + } else { + neg = MP_ZPOS; + } + + /* set the integer to the default of zero */ + mp_zero (a); + + /* process each digit of the string */ + while (*str) { + /* if the radix < 36 the conversion is case insensitive + * this allows numbers like 1AB and 1ab to represent the same value + * [e.g. in hex] + */ + ch = (char) ((radix < 36) ? toupper (*str) : *str); + for (y = 0; y < 64; y++) { + if (ch == mp_s_rmap[y]) { + break; + } + } + + /* if the char was found in the map + * and is less than the given radix add it + * to the number, otherwise exit the loop. + */ + if (y < radix) { + if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { + return res; + } + if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { + return res; + } + } else { + break; + } + ++str; + } + + /* set the sign only if a != 0 */ + if (mp_iszero(a) != 1) { + a->sign = neg; + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_read_radix.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_read_radix.c */ + +/* Start: bn_mp_read_signed_bin.c */ +#include +#ifdef BN_MP_READ_SIGNED_BIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* read signed bin, big endian, first byte is 0==positive or 1==negative */ +int mp_read_signed_bin (mp_int * a, const unsigned char *b, int c) +{ + int res; + + /* read magnitude */ + if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) { + return res; + } + + /* first byte is 0 for positive, non-zero for negative */ + if (b[0] == 0) { + a->sign = MP_ZPOS; + } else { + a->sign = MP_NEG; + } + + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_read_signed_bin.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_read_signed_bin.c */ + +/* Start: bn_mp_read_unsigned_bin.c */ +#include +#ifdef BN_MP_READ_UNSIGNED_BIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reads a unsigned char array, assumes the msb is stored first [big endian] */ +int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) +{ + int res; + + /* make sure there are at least two digits */ + if (a->alloc < 2) { + if ((res = mp_grow(a, 2)) != MP_OKAY) { + return res; + } + } + + /* zero the int */ + mp_zero (a); + + /* read the bytes in */ + while (c-- > 0) { + if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { + return res; + } + +#ifndef MP_8BIT + a->dp[0] |= *b++; + a->used += 1; +#else + a->dp[0] = (*b & MP_MASK); + a->dp[1] |= ((*b++ >> 7U) & 1); + a->used += 2; +#endif + } + mp_clamp (a); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_read_unsigned_bin.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_read_unsigned_bin.c */ + +/* Start: bn_mp_reduce.c */ +#include +#ifdef BN_MP_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reduces x mod m, assumes 0 < x < m**2, mu is + * precomputed via mp_reduce_setup. + * From HAC pp.604 Algorithm 14.42 + */ +int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) +{ + mp_int q; + int res, um = m->used; + + /* q = x */ + if ((res = mp_init_copy (&q, x)) != MP_OKAY) { + return res; + } + + /* q1 = x / b**(k-1) */ + mp_rshd (&q, um - 1); + + /* according to HAC this optimization is ok */ + if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) { + if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { + goto CLEANUP; + } + } else { +#ifdef BN_S_MP_MUL_HIGH_DIGS_C + if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { + goto CLEANUP; + } +#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) + if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { + goto CLEANUP; + } +#else + { + res = MP_VAL; + goto CLEANUP; + } +#endif + } + + /* q3 = q2 / b**(k+1) */ + mp_rshd (&q, um + 1); + + /* x = x mod b**(k+1), quick (no division) */ + if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { + goto CLEANUP; + } + + /* q = q * m mod b**(k+1), quick (no division) */ + if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { + goto CLEANUP; + } + + /* x = x - q */ + if ((res = mp_sub (x, &q, x)) != MP_OKAY) { + goto CLEANUP; + } + + /* If x < 0, add b**(k+1) to it */ + if (mp_cmp_d (x, 0) == MP_LT) { + mp_set (&q, 1); + if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) + goto CLEANUP; + if ((res = mp_add (x, &q, x)) != MP_OKAY) + goto CLEANUP; + } + + /* Back off if it's too big */ + while (mp_cmp (x, m) != MP_LT) { + if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { + goto CLEANUP; + } + } + +CLEANUP: + mp_clear (&q); + + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_reduce.c */ + +/* Start: bn_mp_reduce_2k.c */ +#include +#ifdef BN_MP_REDUCE_2K_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reduces a modulo n where n is of the form 2**p - d */ +int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d) +{ + mp_int q; + int p, res; + + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (d != 1) { + /* q = q * d */ + if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { + goto ERR; + } + } + + /* a = a + q */ + if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + s_mp_sub(a, n, a); + goto top; + } + +ERR: + mp_clear(&q); + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_reduce_2k.c */ + +/* Start: bn_mp_reduce_2k_l.c */ +#include +#ifdef BN_MP_REDUCE_2K_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reduces a modulo n where n is of the form 2**p - d + This differs from reduce_2k since "d" can be larger + than a single digit. +*/ +int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) +{ + mp_int q; + int p, res; + + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto ERR; + } + + /* q = q * d */ + if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { + goto ERR; + } + + /* a = a + q */ + if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + s_mp_sub(a, n, a); + goto top; + } + +ERR: + mp_clear(&q); + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_l.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_reduce_2k_l.c */ + +/* Start: bn_mp_reduce_2k_setup.c */ +#include +#ifdef BN_MP_REDUCE_2K_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines the setup value */ +int mp_reduce_2k_setup(mp_int *a, mp_digit *d) +{ + int res, p; + mp_int tmp; + + if ((res = mp_init(&tmp)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(a); + if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + *d = tmp.dp[0]; + mp_clear(&tmp); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_reduce_2k_setup.c */ + +/* Start: bn_mp_reduce_2k_setup_l.c */ +#include +#ifdef BN_MP_REDUCE_2K_SETUP_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines the setup value */ +int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) +{ + int res; + mp_int tmp; + + if ((res = mp_init(&tmp)) != MP_OKAY) { + return res; + } + + if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { + goto ERR; + } + + if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear(&tmp); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup_l.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_reduce_2k_setup_l.c */ + +/* Start: bn_mp_reduce_is_2k.c */ +#include +#ifdef BN_MP_REDUCE_IS_2K_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines if mp_reduce_2k can be used */ +int mp_reduce_is_2k(mp_int *a) +{ + int ix, iy, iw; + mp_digit iz; + + if (a->used == 0) { + return MP_NO; + } else if (a->used == 1) { + return MP_YES; + } else if (a->used > 1) { + iy = mp_count_bits(a); + iz = 1; + iw = 1; + + /* Test every bit from the second digit up, must be 1 */ + for (ix = DIGIT_BIT; ix < iy; ix++) { + if ((a->dp[iw] & iz) == 0) { + return MP_NO; + } + iz <<= 1; + if (iz > (mp_digit)MP_MASK) { + ++iw; + iz = 1; + } + } + } + return MP_YES; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_reduce_is_2k.c */ + +/* Start: bn_mp_reduce_is_2k_l.c */ +#include +#ifdef BN_MP_REDUCE_IS_2K_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* determines if reduce_2k_l can be used */ +int mp_reduce_is_2k_l(mp_int *a) +{ + int ix, iy; + + if (a->used == 0) { + return MP_NO; + } else if (a->used == 1) { + return MP_YES; + } else if (a->used > 1) { + /* if more than half of the digits are -1 we're sold */ + for (iy = ix = 0; ix < a->used; ix++) { + if (a->dp[ix] == MP_MASK) { + ++iy; + } + } + return (iy >= (a->used/2)) ? MP_YES : MP_NO; + + } + return MP_NO; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k_l.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_reduce_is_2k_l.c */ + +/* Start: bn_mp_reduce_setup.c */ +#include +#ifdef BN_MP_REDUCE_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* pre-calculate the value required for Barrett reduction + * For a given modulus "b" it calulates the value required in "a" + */ +int mp_reduce_setup (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { + return res; + } + return mp_div (a, b, a, NULL); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_setup.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_reduce_setup.c */ + +/* Start: bn_mp_rshd.c */ +#include +#ifdef BN_MP_RSHD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* shift right a certain amount of digits */ +void mp_rshd (mp_int * a, int b) +{ + int x; + + /* if b <= 0 then ignore it */ + if (b <= 0) { + return; + } + + /* if b > used then simply zero it and return */ + if (a->used <= b) { + mp_zero (a); + return; + } + + { + register mp_digit *bottom, *top; + + /* shift the digits down */ + + /* bottom */ + bottom = a->dp; + + /* top [offset into digits] */ + top = a->dp + b; + + /* this is implemented as a sliding window where + * the window is b-digits long and digits from + * the top of the window are copied to the bottom + * + * e.g. + + b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> + /\ | ----> + \-------------------/ ----> + */ + for (x = 0; x < (a->used - b); x++) { + *bottom++ = *top++; + } + + /* zero the top digits */ + for (; x < a->used; x++) { + *bottom++ = 0; + } + } + + /* remove excess digits */ + a->used -= b; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_rshd.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_rshd.c */ + +/* Start: bn_mp_set.c */ +#include +#ifdef BN_MP_SET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* set to a digit */ +void mp_set (mp_int * a, mp_digit b) +{ + mp_zero (a); + a->dp[0] = b & MP_MASK; + a->used = (a->dp[0] != 0) ? 1 : 0; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_set.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_set.c */ + +/* Start: bn_mp_set_int.c */ +#include +#ifdef BN_MP_SET_INT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* set a 32-bit const */ +int mp_set_int (mp_int * a, unsigned long b) +{ + int x, res; + + mp_zero (a); + + /* set four bits at a time */ + for (x = 0; x < 8; x++) { + /* shift the number up four bits */ + if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { + return res; + } + + /* OR in the top four bits of the source */ + a->dp[0] |= (b >> 28) & 15; + + /* shift the source up to the next four bits */ + b <<= 4; + + /* ensure that digits are not clamped off */ + a->used += 1; + } + mp_clamp (a); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_set_int.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_set_int.c */ + +/* Start: bn_mp_shrink.c */ +#include +#ifdef BN_MP_SHRINK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* shrink a bignum */ +int mp_shrink (mp_int * a) +{ + mp_digit *tmp; + if (a->alloc != a->used && a->used > 0) { + if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) { + return MP_MEM; + } + a->dp = tmp; + a->alloc = a->used; + } + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_shrink.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_shrink.c */ + +/* Start: bn_mp_signed_bin_size.c */ +#include +#ifdef BN_MP_SIGNED_BIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* get the size for an signed equivalent */ +int mp_signed_bin_size (mp_int * a) +{ + return 1 + mp_unsigned_bin_size (a); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_signed_bin_size.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_signed_bin_size.c */ + +/* Start: bn_mp_sqr.c */ +#include +#ifdef BN_MP_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* computes b = a*a */ +int +mp_sqr (mp_int * a, mp_int * b) +{ + int res; + +#ifdef BN_MP_TOOM_SQR_C + /* use Toom-Cook? */ + if (a->used >= TOOM_SQR_CUTOFF) { + res = mp_toom_sqr(a, b); + /* Karatsuba? */ + } else +#endif +#ifdef BN_MP_KARATSUBA_SQR_C +if (a->used >= KARATSUBA_SQR_CUTOFF) { + res = mp_karatsuba_sqr (a, b); + } else +#endif + { +#ifdef BN_FAST_S_MP_SQR_C + /* can we use the fast comba multiplier? */ + if ((a->used * 2 + 1) < MP_WARRAY && + a->used < + (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { + res = fast_s_mp_sqr (a, b); + } else +#endif +#ifdef BN_S_MP_SQR_C + res = s_mp_sqr (a, b); +#else + res = MP_VAL; +#endif + } + b->sign = MP_ZPOS; + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_sqr.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_sqr.c */ + +/* Start: bn_mp_sqrmod.c */ +#include +#ifdef BN_MP_SQRMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* c = a * a (mod b) */ +int +mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_sqr (a, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, b, c); + mp_clear (&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_sqrmod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_sqrmod.c */ + +/* Start: bn_mp_sqrt.c */ +#include +#ifdef BN_MP_SQRT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* this function is less generic than mp_n_root, simpler and faster */ +int mp_sqrt(mp_int *arg, mp_int *ret) +{ + int res; + mp_int t1,t2; + + /* must be positive */ + if (arg->sign == MP_NEG) { + return MP_VAL; + } + + /* easy out */ + if (mp_iszero(arg) == MP_YES) { + mp_zero(ret); + return MP_OKAY; + } + + if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) { + return res; + } + + if ((res = mp_init(&t2)) != MP_OKAY) { + goto E2; + } + + /* First approx. (not very bad for large arg) */ + mp_rshd (&t1,t1.used/2); + + /* t1 > 0 */ + if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { + goto E1; + } + if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { + goto E1; + } + if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { + goto E1; + } + /* And now t1 > sqrt(arg) */ + do { + if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) { + goto E1; + } + if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { + goto E1; + } + if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { + goto E1; + } + /* t1 >= sqrt(arg) >= t2 at this point */ + } while (mp_cmp_mag(&t1,&t2) == MP_GT); + + mp_exch(&t1,ret); + +E1: mp_clear(&t2); +E2: mp_clear(&t1); + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_sqrt.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_sqrt.c */ + +/* Start: bn_mp_sub.c */ +#include +#ifdef BN_MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* high level subtraction (handles signs) */ +int +mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int sa, sb, res; + + sa = a->sign; + sb = b->sign; + + if (sa != sb) { + /* subtract a negative from a positive, OR */ + /* subtract a positive from a negative. */ + /* In either case, ADD their magnitudes, */ + /* and use the sign of the first number. */ + c->sign = sa; + res = s_mp_add (a, b, c); + } else { + /* subtract a positive from a positive, OR */ + /* subtract a negative from a negative. */ + /* First, take the difference between their */ + /* magnitudes, then... */ + if (mp_cmp_mag (a, b) != MP_LT) { + /* Copy the sign from the first */ + c->sign = sa; + /* The first has a larger or equal magnitude */ + res = s_mp_sub (a, b, c); + } else { + /* The result has the *opposite* sign from */ + /* the first number. */ + c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; + /* The second has a larger magnitude */ + res = s_mp_sub (b, a, c); + } + } + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_sub.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_sub.c */ + +/* Start: bn_mp_sub_d.c */ +#include +#ifdef BN_MP_SUB_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* single digit subtraction */ +int +mp_sub_d (mp_int * a, mp_digit b, mp_int * c) +{ + mp_digit *tmpa, *tmpc, mu; + int res, ix, oldused; + + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* if a is negative just do an unsigned + * addition [with fudged signs] + */ + if (a->sign == MP_NEG) { + a->sign = MP_ZPOS; + res = mp_add_d(a, b, c); + a->sign = c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return res; + } + + /* setup regs */ + oldused = c->used; + tmpa = a->dp; + tmpc = c->dp; + + /* if a <= b simply fix the single digit */ + if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) { + if (a->used == 1) { + *tmpc++ = b - *tmpa; + } else { + *tmpc++ = b; + } + ix = 1; + + /* negative/1digit */ + c->sign = MP_NEG; + c->used = 1; + } else { + /* positive/size */ + c->sign = MP_ZPOS; + c->used = a->used; + + /* subtract first digit */ + *tmpc = *tmpa++ - b; + mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); + *tmpc++ &= MP_MASK; + + /* handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ - mu; + mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); + *tmpc++ &= MP_MASK; + } + } + + /* zero excess digits */ + while (ix++ < oldused) { + *tmpc++ = 0; + } + mp_clamp(c); + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_sub_d.c,v $ */ +/* $Revision: 1.6 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_sub_d.c */ + +/* Start: bn_mp_submod.c */ +#include +#ifdef BN_MP_SUBMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* d = a - b (mod c) */ +int +mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + int res; + mp_int t; + + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_sub (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, c, d); + mp_clear (&t); + return res; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_submod.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_submod.c */ + +/* Start: bn_mp_to_signed_bin.c */ +#include +#ifdef BN_MP_TO_SIGNED_BIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* store in signed [big endian] format */ +int mp_to_signed_bin (mp_int * a, unsigned char *b) +{ + int res; + + if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) { + return res; + } + b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_to_signed_bin.c */ + +/* Start: bn_mp_to_signed_bin_n.c */ +#include +#ifdef BN_MP_TO_SIGNED_BIN_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* store in signed [big endian] format */ +int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen) +{ + if (*outlen < (unsigned long)mp_signed_bin_size(a)) { + return MP_VAL; + } + *outlen = mp_signed_bin_size(a); + return mp_to_signed_bin(a, b); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_to_signed_bin_n.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_to_signed_bin_n.c */ + +/* Start: bn_mp_to_unsigned_bin.c */ +#include +#ifdef BN_MP_TO_UNSIGNED_BIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* store in unsigned [big endian] format */ +int mp_to_unsigned_bin (mp_int * a, unsigned char *b) +{ + int x, res; + mp_int t; + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + x = 0; + while (mp_iszero (&t) == 0) { +#ifndef MP_8BIT + b[x++] = (unsigned char) (t.dp[0] & 255); +#else + b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); +#endif + if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { + mp_clear (&t); + return res; + } + } + bn_reverse (b, x); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_to_unsigned_bin.c */ + +/* Start: bn_mp_to_unsigned_bin_n.c */ +#include +#ifdef BN_MP_TO_UNSIGNED_BIN_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* store in unsigned [big endian] format */ +int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen) +{ + if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) { + return MP_VAL; + } + *outlen = mp_unsigned_bin_size(a); + return mp_to_unsigned_bin(a, b); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin_n.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_to_unsigned_bin_n.c */ + +/* Start: bn_mp_toom_mul.c */ +#include +#ifdef BN_MP_TOOM_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* multiplication using the Toom-Cook 3-way algorithm + * + * Much more complicated than Karatsuba but has a lower + * asymptotic running time of O(N**1.464). This algorithm is + * only particularly useful on VERY large inputs + * (we're talking 1000s of digits here...). +*/ +int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) +{ + mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2; + int res, B; + + /* init temps */ + if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, + &a0, &a1, &a2, &b0, &b1, + &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) { + return res; + } + + /* B */ + B = MIN(a->used, b->used) / 3; + + /* a = a2 * B**2 + a1 * B + a0 */ + if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a1, B); + mp_mod_2d(&a1, DIGIT_BIT * B, &a1); + + if ((res = mp_copy(a, &a2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a2, B*2); + + /* b = b2 * B**2 + b1 * B + b0 */ + if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(b, &b1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&b1, B); + mp_mod_2d(&b1, DIGIT_BIT * B, &b1); + + if ((res = mp_copy(b, &b2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&b2, B*2); + + /* w0 = a0*b0 */ + if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) { + goto ERR; + } + + /* w4 = a2 * b2 */ + if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) { + goto ERR; + } + + /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */ + if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) { + goto ERR; + } + + /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */ + if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) { + goto ERR; + } + + + /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */ + if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) { + goto ERR; + } + + /* now solve the matrix + + 0 0 0 0 1 + 1 2 4 8 16 + 1 1 1 1 1 + 16 8 4 2 1 + 1 0 0 0 0 + + using 12 subtractions, 4 shifts, + 2 small divisions and 1 small multiplication + */ + + /* r1 - r4 */ + if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r0 */ + if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/2 */ + if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3/2 */ + if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { + goto ERR; + } + /* r2 - r0 - r4 */ + if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1 - 8r0 */ + if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - 8r4 */ + if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + /* 3r2 - r1 - r3 */ + if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/3 */ + if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { + goto ERR; + } + /* r3/3 */ + if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { + goto ERR; + } + + /* at this point shift W[n] by B*n */ + if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear_multi(&w0, &w1, &w2, &w3, &w4, + &a0, &a1, &a2, &b0, &b1, + &b2, &tmp1, &tmp2, NULL); + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_toom_mul.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_toom_mul.c */ + +/* Start: bn_mp_toom_sqr.c */ +#include +#ifdef BN_MP_TOOM_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* squaring using Toom-Cook 3-way algorithm */ +int +mp_toom_sqr(mp_int *a, mp_int *b) +{ + mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2; + int res, B; + + /* init temps */ + if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) { + return res; + } + + /* B */ + B = a->used / 3; + + /* a = a2 * B**2 + a1 * B + a0 */ + if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a1, B); + mp_mod_2d(&a1, DIGIT_BIT * B, &a1); + + if ((res = mp_copy(a, &a2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a2, B*2); + + /* w0 = a0*a0 */ + if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) { + goto ERR; + } + + /* w4 = a2 * a2 */ + if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) { + goto ERR; + } + + /* w1 = (a2 + 2(a1 + 2a0))**2 */ + if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + + /* w3 = (a0 + 2(a1 + 2a2))**2 */ + if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + + + /* w2 = (a2 + a1 + a0)**2 */ + if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) { + goto ERR; + } + + /* now solve the matrix + + 0 0 0 0 1 + 1 2 4 8 16 + 1 1 1 1 1 + 16 8 4 2 1 + 1 0 0 0 0 + + using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication. + */ + + /* r1 - r4 */ + if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r0 */ + if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/2 */ + if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3/2 */ + if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { + goto ERR; + } + /* r2 - r0 - r4 */ + if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1 - 8r0 */ + if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - 8r4 */ + if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + /* 3r2 - r1 - r3 */ + if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/3 */ + if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { + goto ERR; + } + /* r3/3 */ + if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { + goto ERR; + } + + /* at this point shift W[n] by B*n */ + if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL); + return res; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_toom_sqr.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_toom_sqr.c */ + +/* Start: bn_mp_toradix.c */ +#include +#ifdef BN_MP_TORADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* stores a bignum as a ASCII string in a given radix (2..64) */ +int mp_toradix (mp_int * a, char *str, int radix) +{ + int res, digs; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of the radix */ + if (radix < 2 || radix > 64) { + return MP_VAL; + } + + /* quick out if its zero */ + if (mp_iszero(a) == 1) { + *str++ = '0'; + *str = '\0'; + return MP_OKAY; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* if it is negative output a - */ + if (t.sign == MP_NEG) { + ++_s; + *str++ = '-'; + t.sign = MP_ZPOS; + } + + digs = 0; + while (mp_iszero (&t) == 0) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + *str++ = mp_s_rmap[d]; + ++digs; + } + + /* reverse the digits of the string. In this case _s points + * to the first digit [exluding the sign] of the number] + */ + bn_reverse ((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + + mp_clear (&t); + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_toradix.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_toradix.c */ + +/* Start: bn_mp_toradix_n.c */ +#include +#ifdef BN_MP_TORADIX_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* stores a bignum as a ASCII string in a given radix (2..64) + * + * Stores upto maxlen-1 chars and always a NULL byte + */ +int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen) +{ + int res, digs; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of the maxlen, radix */ + if (maxlen < 2 || radix < 2 || radix > 64) { + return MP_VAL; + } + + /* quick out if its zero */ + if (mp_iszero(a) == MP_YES) { + *str++ = '0'; + *str = '\0'; + return MP_OKAY; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* if it is negative output a - */ + if (t.sign == MP_NEG) { + /* we have to reverse our digits later... but not the - sign!! */ + ++_s; + + /* store the flag and mark the number as positive */ + *str++ = '-'; + t.sign = MP_ZPOS; + + /* subtract a char */ + --maxlen; + } + + digs = 0; + while (mp_iszero (&t) == 0) { + if (--maxlen < 1) { + /* no more room */ + break; + } + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + *str++ = mp_s_rmap[d]; + ++digs; + } + + /* reverse the digits of the string. In this case _s points + * to the first digit [exluding the sign] of the number + */ + bn_reverse ((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + + mp_clear (&t); + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_toradix_n.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_toradix_n.c */ + +/* Start: bn_mp_unsigned_bin_size.c */ +#include +#ifdef BN_MP_UNSIGNED_BIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* get the size for an unsigned equivalent */ +int mp_unsigned_bin_size (mp_int * a) +{ + int size = mp_count_bits (a); + return (size / 8 + ((size & 7) != 0 ? 1 : 0)); +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_unsigned_bin_size.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_unsigned_bin_size.c */ + +/* Start: bn_mp_xor.c */ +#include +#ifdef BN_MP_XOR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* XOR two ints together */ +int +mp_xor (mp_int * a, mp_int * b, mp_int * c) +{ + int res, ix, px; + mp_int t, *x; + + if (a->used > b->used) { + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + px = b->used; + x = b; + } else { + if ((res = mp_init_copy (&t, b)) != MP_OKAY) { + return res; + } + px = a->used; + x = a; + } + + for (ix = 0; ix < px; ix++) { + t.dp[ix] ^= x->dp[ix]; + } + mp_clamp (&t); + mp_exch (c, &t); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_xor.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_xor.c */ + +/* Start: bn_mp_zero.c */ +#include +#ifdef BN_MP_ZERO_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* set to zero */ +void mp_zero (mp_int * a) +{ + int n; + mp_digit *tmp; + + a->sign = MP_ZPOS; + a->used = 0; + + tmp = a->dp; + for (n = 0; n < a->alloc; n++) { + *tmp++ = 0; + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_mp_zero.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_mp_zero.c */ + +/* Start: bn_prime_tab.c */ +#include +#ifdef BN_PRIME_TAB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +const mp_digit ltm_prime_tab[] = { + 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, + 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, + 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, + 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, +#ifndef MP_8BIT + 0x0083, + 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, + 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, + 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, + 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, + + 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, + 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, + 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, + 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, + 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, + 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, + 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, + 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, + + 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, + 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, + 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, + 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, + 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, + 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, + 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, + 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, + + 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, + 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, + 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, + 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, + 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, + 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, + 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, + 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 +#endif +}; +#endif + +/* $Source: /cvs/libtom/libtommath/bn_prime_tab.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_prime_tab.c */ + +/* Start: bn_reverse.c */ +#include +#ifdef BN_REVERSE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* reverse an array, used for radix code */ +void +bn_reverse (unsigned char *s, int len) +{ + int ix, iy; + unsigned char t; + + ix = 0; + iy = len - 1; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_reverse.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_reverse.c */ + +/* Start: bn_s_mp_add.c */ +#include +#ifdef BN_S_MP_ADD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* low level addition, based on HAC pp.594, Algorithm 14.7 */ +int +s_mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int *x; + int olduse, res, min, max; + + /* find sizes, we let |a| <= |b| which means we have to sort + * them. "x" will point to the input with the most digits + */ + if (a->used > b->used) { + min = b->used; + max = a->used; + x = a; + } else { + min = a->used; + max = b->used; + x = b; + } + + /* init result */ + if (c->alloc < max + 1) { + if ((res = mp_grow (c, max + 1)) != MP_OKAY) { + return res; + } + } + + /* get old used digit count and set new one */ + olduse = c->used; + c->used = max + 1; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; + + /* alias for digit pointers */ + + /* first input */ + tmpa = a->dp; + + /* second input */ + tmpb = b->dp; + + /* destination */ + tmpc = c->dp; + + /* zero the carry */ + u = 0; + for (i = 0; i < min; i++) { + /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ + *tmpc = *tmpa++ + *tmpb++ + u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)DIGIT_BIT); + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, that is in A+B + * if A or B has more digits add those in + */ + if (min != max) { + for (; i < max; i++) { + /* T[i] = X[i] + U */ + *tmpc = x->dp[i] + u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)DIGIT_BIT); + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + } + + /* add carry */ + *tmpc++ = u; + + /* clear digits above oldused */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_add.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_s_mp_add.c */ + +/* Start: bn_s_mp_exptmod.c */ +#include +#ifdef BN_S_MP_EXPTMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#ifdef MP_LOW_MEM + #define TAB_SIZE 32 +#else + #define TAB_SIZE 256 +#endif + +int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) +{ + mp_int M[TAB_SIZE], res, mu; + mp_digit buf; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + int (*redux)(mp_int*,mp_int*,mp_int*); + + /* find window size */ + x = mp_count_bits (X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + +#ifdef MP_LOW_MEM + if (winsize > 5) { + winsize = 5; + } +#endif + + /* init M array */ + /* init first cell */ + if ((err = mp_init(&M[1])) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init(&M[x])) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear (&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* create mu, used for Barrett reduction */ + if ((err = mp_init (&mu)) != MP_OKAY) { + goto LBL_M; + } + + if (redmode == 0) { + if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { + goto LBL_MU; + } + redux = mp_reduce; + } else { + if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) { + goto LBL_MU; + } + redux = mp_reduce_2k_l; + } + + /* create M table + * + * The M table contains powers of the base, + * e.g. M[x] = G**x mod P + * + * The first half of the table is not + * computed though accept for M[0] and M[1] + */ + if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { + goto LBL_MU; + } + + /* compute the value at M[1<<(winsize-1)] by squaring + * M[1] (winsize-1) times + */ + if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto LBL_MU; + } + + for (x = 0; x < (winsize - 1); x++) { + /* square it */ + if ((err = mp_sqr (&M[1 << (winsize - 1)], + &M[1 << (winsize - 1)])) != MP_OKAY) { + goto LBL_MU; + } + + /* reduce modulo P */ + if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { + goto LBL_MU; + } + } + + /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) + * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) + */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { + goto LBL_MU; + } + if ((err = redux (&M[x], P, &mu)) != MP_OKAY) { + goto LBL_MU; + } + } + + /* setup result */ + if ((err = mp_init (&res)) != MP_OKAY) { + goto LBL_MU; + } + mp_set (&res, 1); + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits */ + if (digidx == -1) { + break; + } + /* read next digit and reset the bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int) DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* then multiply */ + if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + } + } + } + + mp_exch (&res, Y); + err = MP_OKAY; +LBL_RES:mp_clear (&res); +LBL_MU:mp_clear (&mu); +LBL_M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear (&M[x]); + } + return err; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_exptmod.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_s_mp_exptmod.c */ + +/* Start: bn_s_mp_mul_digs.c */ +#include +#ifdef BN_S_MP_MUL_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* multiplies |a| * |b| and only computes upto digs digits of result + * HAC pp. 595, Algorithm 14.12 Modified so you can control how + * many digits of output are created. + */ +int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + /* can we use the fast multiplier? */ + if (((digs) < MP_WARRAY) && + MIN (a->used, b->used) < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_digs (a, b, c, digs); + } + + if ((res = mp_init_size (&t, digs)) != MP_OKAY) { + return res; + } + t.used = digs; + + /* compute the digits of the product directly */ + pa = a->used; + for (ix = 0; ix < pa; ix++) { + /* set the carry to zero */ + u = 0; + + /* limit ourselves to making digs digits of output */ + pb = MIN (b->used, digs - ix); + + /* setup some aliases */ + /* copy of the digit from a used within the nested loop */ + tmpx = a->dp[ix]; + + /* an alias for the destination shifted ix places */ + tmpt = t.dp + ix; + + /* an alias for the digits of b */ + tmpy = b->dp; + + /* compute the columns of the output and propagate the carry */ + for (iy = 0; iy < pb; iy++) { + /* compute the column as a mp_word */ + r = ((mp_word)*tmpt) + + ((mp_word)tmpx) * ((mp_word)*tmpy++) + + ((mp_word) u); + + /* the new column is the lower part of the result */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get the carry word from the result */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + /* set carry if it is placed below digs */ + if (ix + iy < digs) { + *tmpt = u; + } + } + + mp_clamp (&t); + mp_exch (&t, c); + + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_digs.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_s_mp_mul_digs.c */ + +/* Start: bn_s_mp_mul_high_digs.c */ +#include +#ifdef BN_S_MP_MUL_HIGH_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* multiplies |a| * |b| and does not compute the lower digs digits + * [meant to get the higher part of the product] + */ +int +s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + /* can we use the fast multiplier? */ +#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C + if (((a->used + b->used + 1) < MP_WARRAY) + && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_high_digs (a, b, c, digs); + } +#endif + + if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { + return res; + } + t.used = a->used + b->used + 1; + + pa = a->used; + pb = b->used; + for (ix = 0; ix < pa; ix++) { + /* clear the carry */ + u = 0; + + /* left hand side of A[ix] * B[iy] */ + tmpx = a->dp[ix]; + + /* alias to the address of where the digits will be stored */ + tmpt = &(t.dp[digs]); + + /* alias for where to read the right hand side from */ + tmpy = b->dp + (digs - ix); + + for (iy = digs - ix; iy < pb; iy++) { + /* calculate the double precision result */ + r = ((mp_word)*tmpt) + + ((mp_word)tmpx) * ((mp_word)*tmpy++) + + ((mp_word) u); + + /* get the lower part */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* carry the carry */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + *tmpt = u; + } + mp_clamp (&t); + mp_exch (&t, c); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_high_digs.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_s_mp_mul_high_digs.c */ + +/* Start: bn_s_mp_sqr.c */ +#include +#ifdef BN_S_MP_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ +int s_mp_sqr (mp_int * a, mp_int * b) +{ + mp_int t; + int res, ix, iy, pa; + mp_word r; + mp_digit u, tmpx, *tmpt; + + pa = a->used; + if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { + return res; + } + + /* default used is maximum possible size */ + t.used = 2*pa + 1; + + for (ix = 0; ix < pa; ix++) { + /* first calculate the digit at 2*ix */ + /* calculate double precision result */ + r = ((mp_word) t.dp[2*ix]) + + ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); + + /* store lower part in result */ + t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get the carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + + /* left hand side of A[ix] * A[iy] */ + tmpx = a->dp[ix]; + + /* alias for where to store the results */ + tmpt = t.dp + (2*ix + 1); + + for (iy = ix + 1; iy < pa; iy++) { + /* first calculate the product */ + r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); + + /* now calculate the double precision result, note we use + * addition instead of *2 since it's easier to optimize + */ + r = ((mp_word) *tmpt) + r + r + ((mp_word) u); + + /* store lower part */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + } + /* propagate upwards */ + while (u != ((mp_digit) 0)) { + r = ((mp_word) *tmpt) + ((mp_word) u); + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + } + } + + mp_clamp (&t); + mp_exch (&t, b); + mp_clear (&t); + return MP_OKAY; +} +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_sqr.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_s_mp_sqr.c */ + +/* Start: bn_s_mp_sub.c */ +#include +#ifdef BN_S_MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ +int +s_mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int olduse, res, min, max; + + /* find sizes */ + min = b->used; + max = a->used; + + /* init result */ + if (c->alloc < max) { + if ((res = mp_grow (c, max)) != MP_OKAY) { + return res; + } + } + olduse = c->used; + c->used = max; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; + + /* alias for digit pointers */ + tmpa = a->dp; + tmpb = b->dp; + tmpc = c->dp; + + /* set carry to zero */ + u = 0; + for (i = 0; i < min; i++) { + /* T[i] = A[i] - B[i] - U */ + *tmpc = *tmpa++ - *tmpb++ - u; + + /* U = carry bit of T[i] + * Note this saves performing an AND operation since + * if a carry does occur it will propagate all the way to the + * MSB. As a result a single shift is enough to get the carry + */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, e.g. if A has more digits than B */ + for (; i < max; i++) { + /* T[i] = A[i] - U */ + *tmpc = *tmpa++ - u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* clear digits above used (since we may not have grown result above) */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + +#endif + +/* $Source: /cvs/libtom/libtommath/bn_s_mp_sub.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bn_s_mp_sub.c */ + +/* Start: bncore.c */ +#include +#ifdef BNCORE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ + +/* Known optimal configurations + + CPU /Compiler /MUL CUTOFF/SQR CUTOFF +------------------------------------------------------------- + Intel P4 Northwood /GCC v3.4.1 / 88/ 128/LTM 0.32 ;-) + AMD Athlon64 /GCC v3.4.4 / 80/ 120/LTM 0.35 + +*/ + +int KARATSUBA_MUL_CUTOFF = 80, /* Min. number of digits before Karatsuba multiplication is used. */ + KARATSUBA_SQR_CUTOFF = 120, /* Min. number of digits before Karatsuba squaring is used. */ + + TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */ + TOOM_SQR_CUTOFF = 400; +#endif + +/* $Source: /cvs/libtom/libtommath/bncore.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/28 01:25:13 $ */ + +/* End: bncore.c */ + + +/* EOF */ diff --git a/lib/hcrypto/libtommath/pretty.build b/lib/hcrypto/libtommath/pretty.build new file mode 100644 index 000000000..a708b8af2 --- /dev/null +++ b/lib/hcrypto/libtommath/pretty.build @@ -0,0 +1,66 @@ +#!/bin/perl -w +# +# Cute little builder for perl +# Total waste of development time... +# +# This will build all the object files and then the archive .a file +# requires GCC, GNU make and a sense of humour. +# +# Tom St Denis +use strict; + +my $count = 0; +my $starttime = time; +my $rate = 0; +print "Scanning for source files...\n"; +foreach my $filename (glob "*.c") { + ++$count; +} +print "Source files to build: $count\nBuilding...\n"; +my $i = 0; +my $lines = 0; +my $filesbuilt = 0; +foreach my $filename (glob "*.c") { + printf("Building %3.2f%%, ", (++$i/$count)*100.0); + if ($i % 4 == 0) { print "/, "; } + if ($i % 4 == 1) { print "-, "; } + if ($i % 4 == 2) { print "\\, "; } + if ($i % 4 == 3) { print "|, "; } + if ($rate > 0) { + my $tleft = ($count - $i) / $rate; + my $tsec = $tleft%60; + my $tmin = ($tleft/60)%60; + my $thour = ($tleft/3600)%60; + printf("%2d:%02d:%02d left, ", $thour, $tmin, $tsec); + } + my $cnt = ($i/$count)*30.0; + my $x = 0; + print "["; + for (; $x < $cnt; $x++) { print "#"; } + for (; $x < 30; $x++) { print " "; } + print "]\r"; + my $tmp = $filename; + $tmp =~ s/\.c/".o"/ge; + if (open(SRC, "<$tmp")) { + close SRC; + } else { + !system("make $tmp > /dev/null 2>/dev/null") or die "\nERROR: Failed to make $tmp!!!\n"; + open( SRC, "<$filename" ) or die "Couldn't open $filename for reading: $!"; + ++$lines while (); + close SRC or die "Error closing $filename after reading: $!"; + ++$filesbuilt; + } + + # update timer + if (time != $starttime) { + my $delay = time - $starttime; + $rate = $i/$delay; + } +} + +# finish building the library +printf("\nFinished building source (%d seconds, %3.2f files per second).\n", time - $starttime, $rate); +print "Compiled approximately $filesbuilt files and $lines lines of code.\n"; +print "Doing final make (building archive...)\n"; +!system("make > /dev/null 2>/dev/null") or die "\nERROR: Failed to perform last make command!!!\n"; +print "done.\n"; \ No newline at end of file diff --git a/lib/hcrypto/libtommath/tombc/grammar.txt b/lib/hcrypto/libtommath/tombc/grammar.txt new file mode 100644 index 000000000..a780e759d --- /dev/null +++ b/lib/hcrypto/libtommath/tombc/grammar.txt @@ -0,0 +1,35 @@ +program := program statement | statement | empty +statement := { statement } | + identifier = numexpression; | + identifier[numexpression] = numexpression; | + function(expressionlist); | + for (identifer = numexpression; numexpression; identifier = numexpression) { statement } | + while (numexpression) { statement } | + if (numexpresion) { statement } elif | + break; | + continue; + +elif := else statement | empty +function := abs | countbits | exptmod | jacobi | print | isprime | nextprime | issquare | readinteger | exit +expressionlist := expressionlist, expression | expression + +// LR(1) !!!? +expression := string | numexpression +numexpression := cmpexpr && cmpexpr | cmpexpr \|\| cmpexpr | cmpexpr +cmpexpr := boolexpr < boolexpr | boolexpr > boolexpr | boolexpr == boolexpr | + boolexpr <= boolexpr | boolexpr >= boolexpr | boolexpr +boolexpr := shiftexpr & shiftexpr | shiftexpr ^ shiftexpr | shiftexpr \| shiftexpr | shiftexpr +shiftexpr := addsubexpr << addsubexpr | addsubexpr >> addsubexpr | addsubexpr +addsubexpr := mulexpr + mulexpr | mulexpr - mulexpr | mulexpr +mulexpr := expr * expr | expr / expr | expr % expr | expr +expr := -nexpr | nexpr +nexpr := integer | identifier | ( numexpression ) | identifier[numexpression] + +identifier := identifer digits | identifier alpha | alpha +alpha := a ... z | A ... Z +integer := hexnumber | digits +hexnumber := 0xhexdigits +hexdigits := hexdigits hexdigit | hexdigit +hexdigit := 0 ... 9 | a ... f | A ... F +digits := digits digit | digit +digit := 0 ... 9 diff --git a/lib/hcrypto/libtommath/tommath.h b/lib/hcrypto/libtommath/tommath.h new file mode 100644 index 000000000..3c00b9e13 --- /dev/null +++ b/lib/hcrypto/libtommath/tommath.h @@ -0,0 +1,584 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com + */ +#ifndef BN_H_ +#define BN_H_ + +#include +#include +#include +#include +#include + +#include + +#ifndef MIN + #define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +#ifndef MAX + #define MAX(x,y) ((x)>(y)?(x):(y)) +#endif + +#ifdef __cplusplus +extern "C" { + +/* C++ compilers don't like assigning void * to mp_digit * */ +#define OPT_CAST(x) (x *) + +#else + +/* C on the other hand doesn't care */ +#define OPT_CAST(x) + +#endif + + +/* detect 64-bit mode if possible */ +#if defined(__x86_64__) + #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT)) + #define MP_64BIT + #endif +#endif + +/* some default configurations. + * + * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits + * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits + * + * At the very least a mp_digit must be able to hold 7 bits + * [any size beyond that is ok provided it doesn't overflow the data type] + */ +#ifdef MP_8BIT + typedef unsigned char mp_digit; + typedef unsigned short mp_word; +#elif defined(MP_16BIT) + typedef unsigned short mp_digit; + typedef unsigned long mp_word; +#elif defined(MP_64BIT) + /* for GCC only on supported platforms */ +#ifndef CRYPT + typedef unsigned long long ulong64; + typedef signed long long long64; +#endif + + typedef unsigned long mp_digit; + typedef unsigned long mp_word __attribute__ ((mode(TI))); + + #define DIGIT_BIT 60 +#else + /* this is the default case, 28-bit digits */ + + /* this is to make porting into LibTomCrypt easier :-) */ +#ifndef CRYPT + #if defined(_MSC_VER) || defined(__BORLANDC__) + typedef unsigned __int64 ulong64; + typedef signed __int64 long64; + #else + typedef unsigned long long ulong64; + typedef signed long long long64; + #endif +#endif + + typedef unsigned long mp_digit; + typedef ulong64 mp_word; + +#ifdef MP_31BIT + /* this is an extension that uses 31-bit digits */ + #define DIGIT_BIT 31 +#else + /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */ + #define DIGIT_BIT 28 + #define MP_28BIT +#endif +#endif + +/* define heap macros */ +#ifndef CRYPT + /* default to libc stuff */ + #ifndef XMALLOC + #define XMALLOC malloc + #define XFREE free + #define XREALLOC realloc + #define XCALLOC calloc + #else + /* prototypes for our heap functions */ + extern void *XMALLOC(size_t n); + extern void *XREALLOC(void *p, size_t n); + extern void *XCALLOC(size_t n, size_t s); + extern void XFREE(void *p); + #endif +#endif + + +/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */ +#ifndef DIGIT_BIT + #define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */ +#endif + +#define MP_DIGIT_BIT DIGIT_BIT +#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) +#define MP_DIGIT_MAX MP_MASK + +/* equalities */ +#define MP_LT -1 /* less than */ +#define MP_EQ 0 /* equal to */ +#define MP_GT 1 /* greater than */ + +#define MP_ZPOS 0 /* positive integer */ +#define MP_NEG 1 /* negative */ + +#define MP_OKAY 0 /* ok result */ +#define MP_MEM -2 /* out of mem */ +#define MP_VAL -3 /* invalid input */ +#define MP_RANGE MP_VAL + +#define MP_YES 1 /* yes response */ +#define MP_NO 0 /* no response */ + +/* Primality generation flags */ +#define LTM_PRIME_BBS 0x0001 /* BBS style prime */ +#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ +#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ + +typedef int mp_err; + +/* you'll have to tune these... */ +extern int KARATSUBA_MUL_CUTOFF, + KARATSUBA_SQR_CUTOFF, + TOOM_MUL_CUTOFF, + TOOM_SQR_CUTOFF; + +/* define this to use lower memory usage routines (exptmods mostly) */ +/* #define MP_LOW_MEM */ + +/* default precision */ +#ifndef MP_PREC + #ifndef MP_LOW_MEM + #define MP_PREC 32 /* default digits of precision */ + #else + #define MP_PREC 8 /* default digits of precision */ + #endif +#endif + +/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ +#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) + +/* the infamous mp_int structure */ +typedef struct { + int used, alloc, sign; + mp_digit *dp; +} mp_int; + +/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */ +typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); + + +#define USED(m) ((m)->used) +#define DIGIT(m,k) ((m)->dp[(k)]) +#define SIGN(m) ((m)->sign) + +/* error code to char* string */ +char *mp_error_to_string(int code); + +/* ---> init and deinit bignum functions <--- */ +/* init a bignum */ +int mp_init(mp_int *a); + +/* free a bignum */ +void mp_clear(mp_int *a); + +/* init a null terminated series of arguments */ +int mp_init_multi(mp_int *mp, ...); + +/* clear a null terminated series of arguments */ +void mp_clear_multi(mp_int *mp, ...); + +/* exchange two ints */ +void mp_exch(mp_int *a, mp_int *b); + +/* shrink ram required for a bignum */ +int mp_shrink(mp_int *a); + +/* grow an int to a given size */ +int mp_grow(mp_int *a, int size); + +/* init to a given number of digits */ +int mp_init_size(mp_int *a, int size); + +/* ---> Basic Manipulations <--- */ +#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) +#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) +#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) + +/* set to zero */ +void mp_zero(mp_int *a); + +/* set to a digit */ +void mp_set(mp_int *a, mp_digit b); + +/* set a 32-bit const */ +int mp_set_int(mp_int *a, unsigned long b); + +/* get a 32-bit value */ +unsigned long mp_get_int(mp_int * a); + +/* initialize and set a digit */ +int mp_init_set (mp_int * a, mp_digit b); + +/* initialize and set 32-bit value */ +int mp_init_set_int (mp_int * a, unsigned long b); + +/* copy, b = a */ +int mp_copy(mp_int *a, mp_int *b); + +/* inits and copies, a = b */ +int mp_init_copy(mp_int *a, mp_int *b); + +/* trim unused digits */ +void mp_clamp(mp_int *a); + +/* ---> digit manipulation <--- */ + +/* right shift by "b" digits */ +void mp_rshd(mp_int *a, int b); + +/* left shift by "b" digits */ +int mp_lshd(mp_int *a, int b); + +/* c = a / 2**b */ +int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d); + +/* b = a/2 */ +int mp_div_2(mp_int *a, mp_int *b); + +/* c = a * 2**b */ +int mp_mul_2d(mp_int *a, int b, mp_int *c); + +/* b = a*2 */ +int mp_mul_2(mp_int *a, mp_int *b); + +/* c = a mod 2**d */ +int mp_mod_2d(mp_int *a, int b, mp_int *c); + +/* computes a = 2**b */ +int mp_2expt(mp_int *a, int b); + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(mp_int *a); + +/* I Love Earth! */ + +/* makes a pseudo-random int of a given size */ +int mp_rand(mp_int *a, int digits); + +/* ---> binary operations <--- */ +/* c = a XOR b */ +int mp_xor(mp_int *a, mp_int *b, mp_int *c); + +/* c = a OR b */ +int mp_or(mp_int *a, mp_int *b, mp_int *c); + +/* c = a AND b */ +int mp_and(mp_int *a, mp_int *b, mp_int *c); + +/* ---> Basic arithmetic <--- */ + +/* b = -a */ +int mp_neg(mp_int *a, mp_int *b); + +/* b = |a| */ +int mp_abs(mp_int *a, mp_int *b); + +/* compare a to b */ +int mp_cmp(mp_int *a, mp_int *b); + +/* compare |a| to |b| */ +int mp_cmp_mag(mp_int *a, mp_int *b); + +/* c = a + b */ +int mp_add(mp_int *a, mp_int *b, mp_int *c); + +/* c = a - b */ +int mp_sub(mp_int *a, mp_int *b, mp_int *c); + +/* c = a * b */ +int mp_mul(mp_int *a, mp_int *b, mp_int *c); + +/* b = a*a */ +int mp_sqr(mp_int *a, mp_int *b); + +/* a/b => cb + d == a */ +int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* c = a mod b, 0 <= c < b */ +int mp_mod(mp_int *a, mp_int *b, mp_int *c); + +/* ---> single digit functions <--- */ + +/* compare against a single digit */ +int mp_cmp_d(mp_int *a, mp_digit b); + +/* c = a + b */ +int mp_add_d(mp_int *a, mp_digit b, mp_int *c); + +/* c = a - b */ +int mp_sub_d(mp_int *a, mp_digit b, mp_int *c); + +/* c = a * b */ +int mp_mul_d(mp_int *a, mp_digit b, mp_int *c); + +/* a/b => cb + d == a */ +int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d); + +/* a/3 => 3c + d == a */ +int mp_div_3(mp_int *a, mp_int *c, mp_digit *d); + +/* c = a**b */ +int mp_expt_d(mp_int *a, mp_digit b, mp_int *c); + +/* c = a mod b, 0 <= c < b */ +int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c); + +/* ---> number theory <--- */ + +/* d = a + b (mod c) */ +int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* d = a - b (mod c) */ +int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* d = a * b (mod c) */ +int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* c = a * a (mod b) */ +int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c); + +/* c = 1/a (mod b) */ +int mp_invmod(mp_int *a, mp_int *b, mp_int *c); + +/* c = (a, b) */ +int mp_gcd(mp_int *a, mp_int *b, mp_int *c); + +/* produces value such that U1*a + U2*b = U3 */ +int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3); + +/* c = [a, b] or (a*b)/(a, b) */ +int mp_lcm(mp_int *a, mp_int *b, mp_int *c); + +/* finds one of the b'th root of a, such that |c|**b <= |a| + * + * returns error if a < 0 and b is even + */ +int mp_n_root(mp_int *a, mp_digit b, mp_int *c); + +/* special sqrt algo */ +int mp_sqrt(mp_int *arg, mp_int *ret); + +/* is number a square? */ +int mp_is_square(mp_int *arg, int *ret); + +/* computes the jacobi c = (a | n) (or Legendre if b is prime) */ +int mp_jacobi(mp_int *a, mp_int *n, int *c); + +/* used to setup the Barrett reduction for a given modulus b */ +int mp_reduce_setup(mp_int *a, mp_int *b); + +/* Barrett Reduction, computes a (mod b) with a precomputed value c + * + * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely + * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code]. + */ +int mp_reduce(mp_int *a, mp_int *b, mp_int *c); + +/* setups the montgomery reduction */ +int mp_montgomery_setup(mp_int *a, mp_digit *mp); + +/* computes a = B**n mod b without division or multiplication useful for + * normalizing numbers in a Montgomery system. + */ +int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); + +/* computes x/R == x (mod N) via Montgomery Reduction */ +int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); + +/* returns 1 if a is a valid DR modulus */ +int mp_dr_is_modulus(mp_int *a); + +/* sets the value of "d" required for mp_dr_reduce */ +void mp_dr_setup(mp_int *a, mp_digit *d); + +/* reduces a modulo b using the Diminished Radix method */ +int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp); + +/* returns true if a can be reduced with mp_reduce_2k */ +int mp_reduce_is_2k(mp_int *a); + +/* determines k value for 2k reduction */ +int mp_reduce_2k_setup(mp_int *a, mp_digit *d); + +/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ +int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); + +/* returns true if a can be reduced with mp_reduce_2k_l */ +int mp_reduce_is_2k_l(mp_int *a); + +/* determines k value for 2k reduction */ +int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); + +/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ +int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); + +/* d = a**b (mod c) */ +int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* ---> Primes <--- */ + +/* number of primes */ +#ifdef MP_8BIT + #define PRIME_SIZE 31 +#else + #define PRIME_SIZE 256 +#endif + +/* table of first PRIME_SIZE primes */ +extern const mp_digit ltm_prime_tab[]; + +/* result=1 if a is divisible by one of the first PRIME_SIZE primes */ +int mp_prime_is_divisible(mp_int *a, int *result); + +/* performs one Fermat test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime + */ +int mp_prime_fermat(mp_int *a, mp_int *b, int *result); + +/* performs one Miller-Rabin test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime + */ +int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result); + +/* This gives [for a given bit size] the number of trials required + * such that Miller-Rabin gives a prob of failure lower than 2^-96 + */ +int mp_prime_rabin_miller_trials(int size); + +/* performs t rounds of Miller-Rabin on "a" using the first + * t prime bases. Also performs an initial sieve of trial + * division. Determines if "a" is prime with probability + * of error no more than (1/4)**t. + * + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime(mp_int *a, int t, int *result); + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + * + * bbs_style = 1 means the prime must be congruent to 3 mod 4 + */ +int mp_prime_next_prime(mp_int *a, int t, int bbs_style); + +/* makes a truly random prime of a given size (bytes), + * call with bbs = 1 if you want it to be congruent to 3 mod 4 + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + * The prime generated will be larger than 2^(8*size). + */ +#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * LTM_PRIME_BBS - make prime congruent to 3 mod 4 + * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) + * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero + * LTM_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ +int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat); + +/* ---> radix conversion <--- */ +int mp_count_bits(mp_int *a); + +int mp_unsigned_bin_size(mp_int *a); +int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c); +int mp_to_unsigned_bin(mp_int *a, unsigned char *b); +int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen); + +int mp_signed_bin_size(mp_int *a); +int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c); +int mp_to_signed_bin(mp_int *a, unsigned char *b); +int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen); + +int mp_read_radix(mp_int *a, const char *str, int radix); +int mp_toradix(mp_int *a, char *str, int radix); +int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen); +int mp_radix_size(mp_int *a, int radix, int *size); + +int mp_fread(mp_int *a, int radix, FILE *stream); +int mp_fwrite(mp_int *a, int radix, FILE *stream); + +#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) +#define mp_raw_size(mp) mp_signed_bin_size(mp) +#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) +#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) +#define mp_mag_size(mp) mp_unsigned_bin_size(mp) +#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) + +#define mp_tobinary(M, S) mp_toradix((M), (S), 2) +#define mp_tooctal(M, S) mp_toradix((M), (S), 8) +#define mp_todecimal(M, S) mp_toradix((M), (S), 10) +#define mp_tohex(M, S) mp_toradix((M), (S), 16) + +/* lowlevel functions, do not call! */ +int s_mp_add(mp_int *a, mp_int *b, mp_int *c); +int s_mp_sub(mp_int *a, mp_int *b, mp_int *c); +#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) +int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +int fast_s_mp_sqr(mp_int *a, mp_int *b); +int s_mp_sqr(mp_int *a, mp_int *b); +int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c); +int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c); +int mp_karatsuba_sqr(mp_int *a, mp_int *b); +int mp_toom_sqr(mp_int *a, mp_int *b); +int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c); +int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); +int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); +int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode); +int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int mode); +void bn_reverse(unsigned char *s, int len); + +extern const char *mp_s_rmap; + +#ifdef __cplusplus + } +#endif + +#endif + + +/* $Source: /cvs/libtom/libtommath/tommath.h,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/03/31 14:18:44 $ */ diff --git a/lib/hcrypto/libtommath/tommath.out b/lib/hcrypto/libtommath/tommath.out new file mode 100644 index 000000000..9f6261727 --- /dev/null +++ b/lib/hcrypto/libtommath/tommath.out @@ -0,0 +1,139 @@ +\BOOKMARK [0][-]{chapter.1}{Introduction}{} +\BOOKMARK [1][-]{section.1.1}{Multiple Precision Arithmetic}{chapter.1} +\BOOKMARK [2][-]{subsection.1.1.1}{What is Multiple Precision Arithmetic?}{section.1.1} +\BOOKMARK [2][-]{subsection.1.1.2}{The Need for Multiple Precision Arithmetic}{section.1.1} +\BOOKMARK [2][-]{subsection.1.1.3}{Benefits of Multiple Precision Arithmetic}{section.1.1} +\BOOKMARK [1][-]{section.1.2}{Purpose of This Text}{chapter.1} +\BOOKMARK [1][-]{section.1.3}{Discussion and Notation}{chapter.1} +\BOOKMARK [2][-]{subsection.1.3.1}{Notation}{section.1.3} +\BOOKMARK [2][-]{subsection.1.3.2}{Precision Notation}{section.1.3} +\BOOKMARK [2][-]{subsection.1.3.3}{Algorithm Inputs and Outputs}{section.1.3} +\BOOKMARK [2][-]{subsection.1.3.4}{Mathematical Expressions}{section.1.3} +\BOOKMARK [2][-]{subsection.1.3.5}{Work Effort}{section.1.3} +\BOOKMARK [1][-]{section.1.4}{Exercises}{chapter.1} +\BOOKMARK [1][-]{section.1.5}{Introduction to LibTomMath}{chapter.1} +\BOOKMARK [2][-]{subsection.1.5.1}{What is LibTomMath?}{section.1.5} +\BOOKMARK [2][-]{subsection.1.5.2}{Goals of LibTomMath}{section.1.5} +\BOOKMARK [1][-]{section.1.6}{Choice of LibTomMath}{chapter.1} +\BOOKMARK [2][-]{subsection.1.6.1}{Code Base}{section.1.6} +\BOOKMARK [2][-]{subsection.1.6.2}{API Simplicity}{section.1.6} +\BOOKMARK [2][-]{subsection.1.6.3}{Optimizations}{section.1.6} +\BOOKMARK [2][-]{subsection.1.6.4}{Portability and Stability}{section.1.6} +\BOOKMARK [2][-]{subsection.1.6.5}{Choice}{section.1.6} +\BOOKMARK [0][-]{chapter.2}{Getting Started}{} +\BOOKMARK [1][-]{section.2.1}{Library Basics}{chapter.2} +\BOOKMARK [1][-]{section.2.2}{What is a Multiple Precision Integer?}{chapter.2} +\BOOKMARK [2][-]{subsection.2.2.1}{The mp\137int Structure}{section.2.2} +\BOOKMARK [1][-]{section.2.3}{Argument Passing}{chapter.2} +\BOOKMARK [1][-]{section.2.4}{Return Values}{chapter.2} +\BOOKMARK [1][-]{section.2.5}{Initialization and Clearing}{chapter.2} +\BOOKMARK [2][-]{subsection.2.5.1}{Initializing an mp\137int}{section.2.5} +\BOOKMARK [2][-]{subsection.2.5.2}{Clearing an mp\137int}{section.2.5} +\BOOKMARK [1][-]{section.2.6}{Maintenance Algorithms}{chapter.2} +\BOOKMARK [2][-]{subsection.2.6.1}{Augmenting an mp\137int's Precision}{section.2.6} +\BOOKMARK [2][-]{subsection.2.6.2}{Initializing Variable Precision mp\137ints}{section.2.6} +\BOOKMARK [2][-]{subsection.2.6.3}{Multiple Integer Initializations and Clearings}{section.2.6} +\BOOKMARK [2][-]{subsection.2.6.4}{Clamping Excess Digits}{section.2.6} +\BOOKMARK [0][-]{chapter.3}{Basic Operations}{} +\BOOKMARK [1][-]{section.3.1}{Introduction}{chapter.3} +\BOOKMARK [1][-]{section.3.2}{Assigning Values to mp\137int Structures}{chapter.3} +\BOOKMARK [2][-]{subsection.3.2.1}{Copying an mp\137int}{section.3.2} +\BOOKMARK [2][-]{subsection.3.2.2}{Creating a Clone}{section.3.2} +\BOOKMARK [1][-]{section.3.3}{Zeroing an Integer}{chapter.3} +\BOOKMARK [1][-]{section.3.4}{Sign Manipulation}{chapter.3} +\BOOKMARK [2][-]{subsection.3.4.1}{Absolute Value}{section.3.4} +\BOOKMARK [2][-]{subsection.3.4.2}{Integer Negation}{section.3.4} +\BOOKMARK [1][-]{section.3.5}{Small Constants}{chapter.3} +\BOOKMARK [2][-]{subsection.3.5.1}{Setting Small Constants}{section.3.5} +\BOOKMARK [2][-]{subsection.3.5.2}{Setting Large Constants}{section.3.5} +\BOOKMARK [1][-]{section.3.6}{Comparisons}{chapter.3} +\BOOKMARK [2][-]{subsection.3.6.1}{Unsigned Comparisions}{section.3.6} +\BOOKMARK [2][-]{subsection.3.6.2}{Signed Comparisons}{section.3.6} +\BOOKMARK [0][-]{chapter.4}{Basic Arithmetic}{} +\BOOKMARK [1][-]{section.4.1}{Introduction}{chapter.4} +\BOOKMARK [1][-]{section.4.2}{Addition and Subtraction}{chapter.4} +\BOOKMARK [2][-]{subsection.4.2.1}{Low Level Addition}{section.4.2} +\BOOKMARK [2][-]{subsection.4.2.2}{Low Level Subtraction}{section.4.2} +\BOOKMARK [2][-]{subsection.4.2.3}{High Level Addition}{section.4.2} +\BOOKMARK [2][-]{subsection.4.2.4}{High Level Subtraction}{section.4.2} +\BOOKMARK [1][-]{section.4.3}{Bit and Digit Shifting}{chapter.4} +\BOOKMARK [2][-]{subsection.4.3.1}{Multiplication by Two}{section.4.3} +\BOOKMARK [2][-]{subsection.4.3.2}{Division by Two}{section.4.3} +\BOOKMARK [1][-]{section.4.4}{Polynomial Basis Operations}{chapter.4} +\BOOKMARK [2][-]{subsection.4.4.1}{Multiplication by x}{section.4.4} +\BOOKMARK [2][-]{subsection.4.4.2}{Division by x}{section.4.4} +\BOOKMARK [1][-]{section.4.5}{Powers of Two}{chapter.4} +\BOOKMARK [2][-]{subsection.4.5.1}{Multiplication by Power of Two}{section.4.5} +\BOOKMARK [2][-]{subsection.4.5.2}{Division by Power of Two}{section.4.5} +\BOOKMARK [2][-]{subsection.4.5.3}{Remainder of Division by Power of Two}{section.4.5} +\BOOKMARK [0][-]{chapter.5}{Multiplication and Squaring}{} +\BOOKMARK [1][-]{section.5.1}{The Multipliers}{chapter.5} +\BOOKMARK [1][-]{section.5.2}{Multiplication}{chapter.5} +\BOOKMARK [2][-]{subsection.5.2.1}{The Baseline Multiplication}{section.5.2} +\BOOKMARK [2][-]{subsection.5.2.2}{Faster Multiplication by the ``Comba'' Method}{section.5.2} +\BOOKMARK [2][-]{subsection.5.2.3}{Polynomial Basis Multiplication}{section.5.2} +\BOOKMARK [2][-]{subsection.5.2.4}{Karatsuba Multiplication}{section.5.2} +\BOOKMARK [2][-]{subsection.5.2.5}{Toom-Cook 3-Way Multiplication}{section.5.2} +\BOOKMARK [2][-]{subsection.5.2.6}{Signed Multiplication}{section.5.2} +\BOOKMARK [1][-]{section.5.3}{Squaring}{chapter.5} +\BOOKMARK [2][-]{subsection.5.3.1}{The Baseline Squaring Algorithm}{section.5.3} +\BOOKMARK [2][-]{subsection.5.3.2}{Faster Squaring by the ``Comba'' Method}{section.5.3} +\BOOKMARK [2][-]{subsection.5.3.3}{Polynomial Basis Squaring}{section.5.3} +\BOOKMARK [2][-]{subsection.5.3.4}{Karatsuba Squaring}{section.5.3} +\BOOKMARK [2][-]{subsection.5.3.5}{Toom-Cook Squaring}{section.5.3} +\BOOKMARK [2][-]{subsection.5.3.6}{High Level Squaring}{section.5.3} +\BOOKMARK [0][-]{chapter.6}{Modular Reduction}{} +\BOOKMARK [1][-]{section.6.1}{Basics of Modular Reduction}{chapter.6} +\BOOKMARK [1][-]{section.6.2}{The Barrett Reduction}{chapter.6} +\BOOKMARK [2][-]{subsection.6.2.1}{Fixed Point Arithmetic}{section.6.2} +\BOOKMARK [2][-]{subsection.6.2.2}{Choosing a Radix Point}{section.6.2} +\BOOKMARK [2][-]{subsection.6.2.3}{Trimming the Quotient}{section.6.2} +\BOOKMARK [2][-]{subsection.6.2.4}{Trimming the Residue}{section.6.2} +\BOOKMARK [2][-]{subsection.6.2.5}{The Barrett Algorithm}{section.6.2} +\BOOKMARK [2][-]{subsection.6.2.6}{The Barrett Setup Algorithm}{section.6.2} +\BOOKMARK [1][-]{section.6.3}{The Montgomery Reduction}{chapter.6} +\BOOKMARK [2][-]{subsection.6.3.1}{Digit Based Montgomery Reduction}{section.6.3} +\BOOKMARK [2][-]{subsection.6.3.2}{Baseline Montgomery Reduction}{section.6.3} +\BOOKMARK [2][-]{subsection.6.3.3}{Faster ``Comba'' Montgomery Reduction}{section.6.3} +\BOOKMARK [2][-]{subsection.6.3.4}{Montgomery Setup}{section.6.3} +\BOOKMARK [1][-]{section.6.4}{The Diminished Radix Algorithm}{chapter.6} +\BOOKMARK [2][-]{subsection.6.4.1}{Choice of Moduli}{section.6.4} +\BOOKMARK [2][-]{subsection.6.4.2}{Choice of k}{section.6.4} +\BOOKMARK [2][-]{subsection.6.4.3}{Restricted Diminished Radix Reduction}{section.6.4} +\BOOKMARK [2][-]{subsection.6.4.4}{Unrestricted Diminished Radix Reduction}{section.6.4} +\BOOKMARK [1][-]{section.6.5}{Algorithm Comparison}{chapter.6} +\BOOKMARK [0][-]{chapter.7}{Exponentiation}{} +\BOOKMARK [1][-]{section.7.1}{Exponentiation Basics}{chapter.7} +\BOOKMARK [2][-]{subsection.7.1.1}{Single Digit Exponentiation}{section.7.1} +\BOOKMARK [1][-]{section.7.2}{k-ary Exponentiation}{chapter.7} +\BOOKMARK [2][-]{subsection.7.2.1}{Optimal Values of k}{section.7.2} +\BOOKMARK [2][-]{subsection.7.2.2}{Sliding-Window Exponentiation}{section.7.2} +\BOOKMARK [1][-]{section.7.3}{Modular Exponentiation}{chapter.7} +\BOOKMARK [2][-]{subsection.7.3.1}{Barrett Modular Exponentiation}{section.7.3} +\BOOKMARK [1][-]{section.7.4}{Quick Power of Two}{chapter.7} +\BOOKMARK [0][-]{chapter.8}{Higher Level Algorithms}{} +\BOOKMARK [1][-]{section.8.1}{Integer Division with Remainder}{chapter.8} +\BOOKMARK [2][-]{subsection.8.1.1}{Quotient Estimation}{section.8.1} +\BOOKMARK [2][-]{subsection.8.1.2}{Normalized Integers}{section.8.1} +\BOOKMARK [2][-]{subsection.8.1.3}{Radix- Division with Remainder}{section.8.1} +\BOOKMARK [1][-]{section.8.2}{Single Digit Helpers}{chapter.8} +\BOOKMARK [2][-]{subsection.8.2.1}{Single Digit Addition and Subtraction}{section.8.2} +\BOOKMARK [2][-]{subsection.8.2.2}{Single Digit Multiplication}{section.8.2} +\BOOKMARK [2][-]{subsection.8.2.3}{Single Digit Division}{section.8.2} +\BOOKMARK [2][-]{subsection.8.2.4}{Single Digit Root Extraction}{section.8.2} +\BOOKMARK [1][-]{section.8.3}{Random Number Generation}{chapter.8} +\BOOKMARK [1][-]{section.8.4}{Formatted Representations}{chapter.8} +\BOOKMARK [2][-]{subsection.8.4.1}{Reading Radix-n Input}{section.8.4} +\BOOKMARK [2][-]{subsection.8.4.2}{Generating Radix-n Output}{section.8.4} +\BOOKMARK [0][-]{chapter.9}{Number Theoretic Algorithms}{} +\BOOKMARK [1][-]{section.9.1}{Greatest Common Divisor}{chapter.9} +\BOOKMARK [2][-]{subsection.9.1.1}{Complete Greatest Common Divisor}{section.9.1} +\BOOKMARK [1][-]{section.9.2}{Least Common Multiple}{chapter.9} +\BOOKMARK [1][-]{section.9.3}{Jacobi Symbol Computation}{chapter.9} +\BOOKMARK [2][-]{subsection.9.3.1}{Jacobi Symbol}{section.9.3} +\BOOKMARK [1][-]{section.9.4}{Modular Inverse}{chapter.9} +\BOOKMARK [2][-]{subsection.9.4.1}{General Case}{section.9.4} +\BOOKMARK [1][-]{section.9.5}{Primality Tests}{chapter.9} +\BOOKMARK [2][-]{subsection.9.5.1}{Trial Division}{section.9.5} +\BOOKMARK [2][-]{subsection.9.5.2}{The Fermat Test}{section.9.5} +\BOOKMARK [2][-]{subsection.9.5.3}{The Miller-Rabin Test}{section.9.5} diff --git a/lib/hcrypto/libtommath/tommath.pdf b/lib/hcrypto/libtommath/tommath.pdf new file mode 100644 index 0000000000000000000000000000000000000000..33994c35a81f43911b05ffca60e0b6066954fcfb GIT binary patch literal 1183099 zcmY!laBe~m5?D_MbR+n$BteVsQ`M0mFY(d3tH+!?~ z(lK>ESZ!_YXE{k4FemaH{&t&9+`^5~&)G*ZNOD{FZ2fl`b8HHHG+n=Et9&?Nx%+gX zlY-|XIh{u;hu$UG{z(o@;Cy1&Bj+VD?a@1_FK4twbq>DGIx^*2iAcG1y7N1qDVA9VZ8-%y0_aaeZ^})jhJ_ z0hgw%Rb^BS@(n-LDYA5qU2l})lv{0_qEdHH7j`}9yt-`jL`5|ow<}SVTv~^lQ{Ee{ z*ufClv_Wvz6d$fz6;5o1T2l`i`!0zId7bL3B0t$WKgB9;?eVo@dRmKKEa3YRdVNOe zz7y|Sm6W}!R5rXWxw$FLP-bQRek~JDE6q0^_YPZYLo^&>Om$b-dzq1nAtshjG&e$yXKmEh+U16%n-_&JYW}4xxf9;IY z#iP-Cv^3xBebjTR(?O#k;>JWb?cJ|y3ogpsUHe9?H;&ux#wWF@3vXGy*?)Mh=<5$x z)`#5sX1Z=>*hv^mU(|LShY%^xN!gLZ32^bikM#0j!KVc&bsuvkZZ!8b05|v z-|De5pS)wztG0^bj1KMVm1=@Px$TbXyW?l}=c>(r{V(0`u5U%UOw*0oS9L!aomkTT z`P9a|qZ4;dJ$T5{-mrZ7qKmK8FIblqeTXWtGi%^fV*0%9#_Ql;f6duq*X}!dPE1`? z|CiI*-P0x?Zu_cRlf;m}e(U09hWlk&_DbKfcK=*4e}DRX?+dAUDbUoJnwJ7f(V%n; zrp*kvphAY2sofByj9_w~8tz>zV=A!k{rVY?d5&_d{Q8WAbEiOX;|BIs8hqQX-;}7{ zd&I2&!|RvxF0QCHGkQ9OKd>tL?)+ar&$jz%U(Woc{Xb65EPikA-G7P3p4ON5u3J9) zYt2Z9yRx68q%5bpscDZ!$mtHBsu-~Sd7Ph&ck?U!;}%rJ-Vul->Tt}UKo_42u8Ue)S8bNLsC zYd+0U4>r_b-?sli^a7?CQ*{gXC`UVH3jeZSwKlpf^vtpw@#m)7EO~0DFirO0HZA2F zKMhwHNPpE*55Fh$nMt%}*=sX((Sw}x>#tpQ4V_cCW9vunPZA*=l5_RT`-IQr^t|V1 zK6WxIm+PBn#o1}^R#lqz9E@<))O>mITFoTcPmzU~lLIz!v8p`cu z9bdN`zrXE%zCxqZmI(9PvSM8wx|N}~BE5WlA8%B9vW{u);|YRSCRM%X4(gwA)B2~h z;_;IYGZM;9em$1IT;}GIn*ZYaeZ#M>aywRZGj&hWrb~(^-MgZ8uif7AVM*Te?~}?O zPg#9_>HPbGDgnXFfA}95Z_1rp=BV;v(W_i`o$D=swUjKU^0>(Vk`LgQITj?=zvkh^ zrqGLNfjggWe6ZZ6eZhv`x&MDR{8-DUV60Wu(R(c+sH|X7ie=z|2a(B(&Y9iTUuO7d z!+MiNR({846mrQ3G+xv?dgXtNNYav^FA=7Z$NyPRi~G3MdRpA(FAKdm`wcV9jvw8h z_`hwv#JB%Vx%13z?{56EOY`ny!R5}I*43Zp+P%tP;VQ<;!wqsbk0lEqz3=;S`kVK@ z!U4B$)EZYD_it*yAhu?`r1poY#(eVTY$sX2VfR(?LGt()&{zTSjh zmt)Nm(WEKoUV7eQa#@|=T6#cxzF~uJnnHlldka_3@*7Fn2fI^SBwdRZzcI;jd}w8~ z?R)B1tCK5^ES+ipL#FAD+xHUf#ETUht5}17l^^{vZM(5u)QJ-XnfbG3o?_{55K|Mr zS)Z}y7IWowE$amb_iR{ybMLjl3A2vwRL}Ex$S3)$zxeM9gW_3BPJWKKF3Q*-$?!4d zeCy($Ct95oGQ!mY^_pfH6fgY1JZ*7*)5d8p63fD;Zv3-HzjW%S;+d!KG$mO5>FF@5 z%yN{mUgx~3i4LEwFf` z-gs=PN@f@9TGNHJR#=yl5PrleyT7%{;%y&e<-8w4-

b9P-d$eN&9-Pcf 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 Xe5 zIeTNGC(9n4`0aB`a{b}T&z90Yt6#@`eZt_A@RRMt;|Ga*`7d#JMqKJ)VDA2Y{{8gQ zm#1Exo2PtoF|X2t3ztKuPMtbkU;pZT*=L@zX}^~L`~K_e(PsCDAO5s=|M{|juRf-3 z@17s;oUZ<#`TBOd|2hK)&0>$>Pq%I#zPgz^l)a*u49T^e%&%fP%*2n*Cw2-z) z?(Gcz@Zjy$;19;4*N!@@kGr-%_Ep38^w_waZ*}V1d@bxBe*ZW>;&4=dYkY%*^xd4F zv+bX?Uz_##bDf2L$9=uTH%m8GXq^AFgMWc|?1BF+kI(l^zptnMzw7UzIfX@vvhy1z zR(*F6Hg>UM8i%L)z5BuZ&+hECACFCCyN(6^@Uq@}^Z%Xt+RO1ZUfE51 z8ka~fvh+2~*l^nK+L^e`ny35b`o6jOz4Ca~yvI%kPu~A(iFN6}n0-%W>79>fvrbLO zS$y{8iRW*&I9ul!O%7`8_MX3Q?YvtBZ+&KmG%q=>E+qVx`Ch(I$d6TqZF_&%7P57- zowjf;v6vg$u(xV+&;ED(`LiR!^j`W2z3tfe@aHGB*~ONxb*@gm=N-zri~DY_V(`q? z%__UiUw_^n<@j&Q%s)2ldJJ29MVE_g)i`;?FJp>!(}KyKxydSb*0X5tvrV*O-7ERz z@1zqRQZXyu7({&Fm1|nEKu5Uslya&_^25ogKJgv7kG^_74li&$F}3}rfiI`wuKE0( zy9tzi&XCCiKEO?wAB`vdUR&U+G)b5DP%kwhwwz=`w zTkW(s`-Er7-x%>sK7(o7JdM{bw$(i^;gRN_Ts2{5qUpqqX{LW8m!zkZUiPfIxNJe! zRp;Kb~!w`eTmj#q_uC4IQboFVC zi_Vo5wDUig9W|$qeV<0;CCMWDie{b5pNwCpw6K@uwB>(Z6m{`qn$v*O6jQRK+GmUHgntmJTNbz2ux8jt zzc^|Xn7(M%q~e*Kw+=m7TC(HU<)c^Yg}y&%59Ts!s=cwd^Mgp4cSv?q5se z9L^pP`j9l4z233o==>8Z6XtUz>5^~ zcpiB;bnmev5Aqe<`}bPym{4fw?Qz&Ni090M{FedEoCQ^rF1Jr|ot*U8!BL@NgT-MM zu6a6k(k_YDZ?V3+)cv8V;w+PW&-caa-$ik+%)OIvEdF@qtc5E5FW(z$@)-9l=Fi#o zQo732&r1IHrV#TBDqG}UFFT?8dNvcovy12MhHP4sc58c?iT2qvy-tshDKf_DHaF6L zELit`u3+u={FL1jzKgLi?=#A~es_KS?it+MxW9eaw)@!ZQ!)o!`23C7f~y*MkFJeQ z<1nw=+SFB3=gO}RISPMtPH48eGWL_9u4dcnVDk6VBg8#)}8AdFFa-U zV2;bWaod9b-@e?tMFA&GN*3|wvvphM`u_7| zZR`=vzV_M4`;`@+4KFReoXjbs?;JAG_%*^Y0ANn-I6ncd3X@{`r zR3Yn%RWFVnY8Ct1vUdN{c-sxPj~vUklCXE#t6G=Mq?|X^F43cBbLSxV8VZVa=E&3S3~9biSu7vak=|yXOC3o z>LY>~&1?6q-pzbX;7aVKJfE+-e5?F!hi=&OXT^yR{u8*))lZx`yFfHY_Y_a|yT@E9 zh37A`{D^W2j6H2`Y02gMDUKGwWFFqhxJrW_0#7$y+%3 z9_*i4<6RY`@yh#Bv88VdzG&i@^ewuZy z+woXc?BdOL4!2iM`hK)~?c4Z?m8WhW;to{E5q_#V>-~v!-42PLBD^{ix&*R|Ea&`? z;deGFWT=oXb}st9Bx&-58E^gsiOo_}lh=QBd3)TXWVJUf*EYR%tC_gML*Q&4n`N;4 zAzPP@2hUB`3;3qVstGAdZT?q#p*S+^){Ny}C$ydTJ55eafpPy?ugxAuRjoS;&2EWg z=q4Ubn7VPH9dV&HFAYE+@_%6Bfy`@$m$`jz^JRf$!h``jcrQ%+=Odv4Xv~ zOzlHJ9Yg8OlI0r?2}`!Q{TBO}&%EZ*lG%@!?@bL5U-?PN?fq(=iJp_6Zu*{P*=hRg z^zrNE=Tsi?3G7KZm+4t@tRNPW=cW6 z@XUi3woK2~@v;8BRL5kwBXgMKoL2!$f@>WX5pABvGo?66*}~9HH2LJgCtqJ|pZigOJ=f@Kq1XG#E3exI|F`@%XU<2( z4^yiA=kJeFe-Zjf-%h)#S4s|0N6N zTSlI<`FBh|tU8^U<>K#Hm5j#elPvpVj;vBS>+e{+;roOSc`v=6y3e`z!^glmT{}te z&yTYQ`!=kYyZZjxMO^9+eR*@a?o#k)ot4|4hpgeV zo^x2hT&~#BSn=IcQM*N@4|vZ04D9BA)b``(ZRPVuQKy&w40YvdT-oP%Vw<&1{r;Tl zuc^st#_6lS)Q0zSP3@MspZ<^|xO%G_TT0P`%VpU%Y}5Fbd=}!LTiw9?F>AZihPUyr zR)5nu9JXeL*t_q&PxuxllqYPsb6SP%iObyWlRLvsSYDfyz5Qlu_~v_0ct6ER9zOQu zQPdmb=F1#DjC^WYc@I`@S34`zbKdO48A}n}O+DME3%rkKK6vH*gYVT5Sx0?NWtKG8 zXm6U_9(VhsxYTNybgu70C3g?!3Ef?}J2biSV*O&S-8ah59^z5Hwosr`RJ;G=+ghQ3 z8)9*DW2P#VsW)i8y=Pgu&&)B<-|KkJk=k_uRm+x|=B_@YP;JEZ(=^*ID)YPskJDMp zH=Lo`1${HSVvb%e?3rThoc1W_q<(PYj*}m~jFn5H*Dn4pdv=M=6ZSv@1Gifa7pN+=~7b`KWb8$ZuRi_RhL9*@6h80(SFTGHo*ok8Ew4!Ywk1Ql{eHR9XFb83F8X6)yZ4QvvF?6B-@Z0uD0_#Ij_7} zD6y39uEMOSul7ssi@efy-0#}e_ev^p>OyA^p@moK--HTZ+<2vBP+0)O3Rf+Ugo53NbU_>YdU+u`f04jO~z@*gUVYD zN|!`<@~)ZHB)y@^)T-oTvt@~3Xuiu7t=yo10<~`Q87G4R@8=iilygEU@ za9!LgeDyosJ4JSjKTlqLSV`x(%aS)iy&oMMl`^9kzD~$D;A03}z5TG_5#{&adTQR9 z{9n0ST7Ac+$28VJMGcOQ_U7jcku9KhHPZmsWIy|{NI%NKNXD;cb2^%}CE&u$j z%DOx4{dcXZmWy#WIt?OLdM#OCHf0L;?mt|)@6&F4`4=XBafkV`x4*fYytXwkM_#VoN-fv0H?HeT|6<9#Zx z>(G`eXKkPBD^@R2u`^w5$!ojo$OMz(DIa^}gd$A;pP!d|AgA@w(P_p9?^Rd}DH(Pi zS+aAMesaWqwQX}rqR!{0e@DeHh-V2J+DQVaffvAg5)%>FA+lT?(%nM z>PlGcke^|Cc(*2dtlrk<0<)I}96O4WcCI?M`4-=z8;2*yEtH+TPH5`;uCSJzEqh?aXt%jf6DPcbsGVMY0m8H!ic zudw`oLg9KuwS=&G(&_m93*)C2aj(30uJ5{@$-=xn<>qZU$L_3qvr3?K-r9?&|K!*2 zSY>s=U{}NWw!LpM4OdxL&*}N3yHWCupNMXjME1jnyxptgcs^7`p7_Yt^-yQUU-g%T zCFeMIg~rX3Ta{q;dX2R3%uMl($1;|`R(JikcTe_e6?I(`?)~9xWh=|}AI_VTWxOT z8ExA#b>7c_qjAqGX1}-|w7K_3=#26V<8voB8@v|m=wEYd>5tf`Z{0r*-HTSe6Y$9N z^G2BmpE?ZHHR=K$q`Di-zU`=c)xq}HwGaAQYd|o#tKtRqqW~& zsN2_Ry!egj{4lw5uh-Y2J8m6V5`4;|XX3PlY%}hz5B4}0;M1UMocs4k^_1l=ymd79CI8;Z7<~NC zGrwD_WDB!XJ|&xk?bCg@Ls($9WmJ{&662YSfvV?3+}iJWw0%7Gu6D74v7LJ4tlPX* zg}dcd?oY~h4_JDs_v3`QXH%Z!KiSyHwmg1uh-><~>N&4WL$_RZtS* z)ScsDuyc?5^i11_>0P_0dOx-9oK?pDta6vJl;>66S|;Vi4D1%!UOr1+E?@1$AU#z! zTDqCp(PQ5&^QUgDpQ;7!3u~|PCE@4}&CI0uY z$?BXxw|z>p)$aS`8{gIO4tmepbi4A#&D@tBYDV9;OBemlnRn-@3Fo2w6HyORzL{$$ ze@cJX;qm&0{QBwfl{*ETQiA`N7_lX6ujy3X9HPF@qyBT{y#?p)aVD4K>E(T~U#vCr z^t9*4Q?*UAm{+}6y7czsjSlT^wPhT9d=o~B0TMu>4wEEm+9SrD^K@o0?aWSOI)-zuBrFFp+3+N}3v(fVEmY!yTtkUqj{J-}meN8(awlDcd{IB0HS8ulFfBWv| z`SgdkW$)L<+5Ii~_N-@l{e~}J-o3Nrc~JH|JijGy_viQLE2{2&zFPdgJZ#p~*>``g z-kdMK&;G^L%4Js%9dduZ_s_dO?=3i|pVf(57j(eo`T2x9>c5$zrzTI*pa1r$mW6QE zPwl#-YrmeZ{(EpukLBxWpMO2s`|IuDzm8lxt(IOAo3r`!F8c^>_3)~l{fk?YVqQO$ zPh~W^et7SN)kZOT@sBFj&6#+5dG%hSvpn(tLXS-462T)6OYf=7XX z*uE5{Af@vuz0rCPLxR>{JNZ=h%#tY^Yknr4PYgVJ4;8U(ylx(A=zb<4cC$pU7RI`uq>H7fv~SggL!9-eH_ zUXoNPeNFVh%ss3LZoh&ucK%@#F5K&-Jw5*00n@jll>*zfWY*|Tf4ymK+W!hWMw7~E zCz8)r{7C*YcfCSI;1s6+moj%ucfu0}1dk6IXhe;Lu1L>_hdcqDdy`TSv-{2m{ zxtGlTs|!NE`7ANGa6eGDru|H-qg#Gxu#x|=Jvu#W76qoRNG!g0{UVt!8;zDd;Ndn``*uX34>x$<3Z;!+4jh zaarpfepb8bT&KyzWOu_0=eC;ZbmoiP+Obh-OaJQrQ|%3{`wloB&`dQm<9%*(zxl=C zYnGy$cAeEYb;-nSyS>FNH-Y-I2W&ki-Vu-gw^zKTRLsXoeU*oOa(mjZRjaB*&p-cq zTK+?VT$!Ee@yc@+X z9rw=HEw1oTOSr1DZLOmDhspPEd~{$Aaqq3U;-bDxX@;0(L4t{a(mK&+qH(`mte37h zsx*|FG%dI1cAyeydLjT>P44npmpp7$vd1MCr}SZnn3dIxcpY9Gfp2-ttiTmRZ@X zH*X)mIT(}u+mR(KaiwC`d9fF|M-F^_Fimfg;8q4s%Z-Z~xf52`uS}SHqsVElR-1Hc zhr1uo(gQ7LTsp*WXh=RjS#wNR^mk;X^M+?)pF_Dby5^QOvCn3#VrYBo`Jk!M|HY(+ z`5i|V**ZLlw&_n+X$VT(}lr@UWEGMdMdMv?(qP zc^Q0;6CB>W`Sc<%@yBGR(jmD*EfBjIf zoW>TzecT~XckA!PC+0u8udsx{Yt@9jM>AbmXWU)a_BC@Ohn z{G_E8&#Bka7BzP^m#&(p;Z=F3y3piE6rbbw*G;R|cLtwWbnU30+`q&>H!AnO;0=Fm zcVcn}*V-uF3#+$l>`2QGEXbF>!MLND=U}D`i^Vb14{}dpRK9t0`<=Tn?OKK0mhAQI z2~8c3j_5s`e{plvzM>iX?QSZ4s5!wrFHPidk{sKdZQ*Cnq*y!WDltWhb|3iclf_uw z^Gtl2#>xq=^E{3uMC)8v{(mIp<(aI6{nGk=Wqo!HDNd^j`&=fToAh4l%}tKdJ7w9s zR!-y-%hcYkk$awdqrTLVr9CYxj{7e7+1;nGcB8x-v+Yx+5T#?xi^9|+IgUuxv`HHt zPUToEs1p%TaqnTElAXd|?H_Yj{%_&9XMOq5eBZLRf)AQUuRfT|8?=&J)M!>lO?|}4 z6_#!0I!{c}B<3}=H{H<|*G|s}5&B%?pm6nY-Mi`LSJPwo&(t%2J^XBO8tXBGuC5Nv zb$Y6*Uk}|vIU2~ z>^oij)G}QxK&zwZ3(EyT!Lt|JY%L%C3%72U)G_|a9w9#O0kI8bB?W^8vd*-!2h6t|>^)Tjvf5rv5qZ#k=Y8K*hRKc%{}(2k zhJ0VfGi%WtN5B20m4_cr-}}&^y>nfx(~O+EXCAa=@jX|zuC)Dh`@B%->?bMh3?V1v z%NWBfW-m{un!K@B&9p;5B0ucFfzvyd&Hk30py+wB@Xbv|S)B(tiF{HwS&Fwj`znwX zWtsD)@J_DbacRMM&!U$1ipiYmDtGS83f{Z0=1?jhhx5k8lPYdcODZ`&{SLF^wqMz2 z8Lt0{ncJ0(j-tCrra{AswXcZfBb+=Pc8QTX=SAMy=F%c$#C{PVp193(PtuRNsFS&2Twp z?xfn&T${vZ*ZQrNHw;|nDYip3dDV=ZT>@rL`|muT#@=iAW!YoaIzLY1y}mE~W@)m2 z{n*`caEY;SKtREi{JSXz_6IuTG+J|X-`+lDEqU$g38(cF_yznc_CICLv+|nr?OMO! zvkRQ=Q&OC(C3o=3{W4CEmAYMWL}R;U{@E8lTKc*gJBx2W;ns^ayu~|LYh!?)aEYc! z<|bvKM+P!>lV5STs8nf9n&z-iTkRO@L}gx?#~McMY;`iR{n9q;y4h^jhwhX=H9hux zx|OS=M)>0tcNgJ9=S>v1iSj=@eXMIibLLtPv6D$sM~=9b?3G*ibyFv!SuB_Afm58Z zcE0H;ESI*Qn-rzkCCs=_ls8fzFr>nc8B|{&4(Y%`FhW$+a>4p5x!I1 z6F&%i^zECuRq3ml=#iO=FJ0%F^`Xwx>_lwWO&1;>^lt;_=wHlWurM%j|POMrZYwzFUGl%CqPvC*e`|5V{+8&J`aGt~H?AK3 zyYlZ;%YD|W@4WiI6<*)=YufxbT)KXZUZH`P9%#!&i}63gST_rJQ;ll5gn%Wp02 z6gu%%VR?O2nr?&`gYDjZ&*hFUdiOJ}Q~a&(CE+jotaf?5YdAiqP^3BUeb(JO4ua*z z8+IIibLfi2vnP)XIbGH|CRzK+OB`wqWK`ijeki0lAo=*`wbC~}&ayI`a`We*IpxmE zQzp#$GU0oJ{_ZCiziwOTw$+`|qpy4(n}tv4L%0Y>52!r#Grw`3~GJOmUIReXx}I zQ_|MjOBWV0s3dD&+4AvPm#8$S`?nQoa|(-JJXrgO`S7L!$q8Sz`(&K<Ewxr6^frNV>eyB*<7|Zv2sC8sPLyl z6aABvH9miSop&SG==}XQG57l=sa9Q+3M}5_*XSy7ZVj)y`Rti-(ycr9W$zuE{bQm> z^{f-CJ>N~to7TO`+-;X;vz&T9hj_I6K|RA;tEXp1oS*PIVO1gLlVrj7D{3CF6r8#y zdFGVTL$=+yOAWRNb5(6#B)5V2@WNF^x4&;JS(xp6c>Br(+3pD`0ir#gr#0JH4*WkG zy8Xf8>c@L)%TJlH27M2^eI-Kn?5XMVk4vyxKYpbtG%xAc(Rs`V%h~QWU*7nfVX-=A zeNeeeM&a}w40T2qH|AT3J}^JZuxDE1cCHnZGi3v+YFM)mS6(@~P15Sl+-+N~Zpw0d zyxQ!fon`Tq4hT4CCM7 z8B%%m>tnZ|HMh99nBKep-t=tN>ywX;s670=-%a_hV&+k%*D=$oVh$bpmExQ5$06%| z<)^TzLFcM3PcS{LUB;Nb;KPl*0kh@$7w5g$%Bw#qXy$&4%lb?AJM+a=Y^i+et(UZ{ zHE&Xqi~oA>zZ>q|l-@eC%t9+S{llTfK{~ls)8}6adaxzvP|c3C&7!`4W~2!J-o-h= z>(WVE_m@4v9{Vy+yI7v}6<@yZ;xlINoENqxhf5wZn14!K{9%Px?VF-kJEqBnC6=|B zKRUhO2&Xxdljh~Jqw_fA8;*&dldpWrb2Ik$vY8?OZGtY`Tedd!zz>t(;nufLcyIO6 zxVPYO_4D-j`Fn2`?s=?w$onr}R;hKr%jP_Fo;dEJALkD2{(k=5o%#*c-@pBO^yZwo zbzRwW<3IQBuD5I4|E_-5@5?v${@%U*`FsA9tmOyaM!lUS&QWziw_u6Wk>J z33;6TwERi)%$t!jn0+|TFpqXFmf zrfml<`FTi7iM=e>iP2}iRIR>O(fPuz$d-*i9yR`X`h3L#4(%5+cJEN0pnv}GZq_B+ z9Kz*yt!r4QFnfcwL35b)u9~}PCmfFP#R}GmUDV3uJf$PFLGk#?mM1*?r>&EeuDSEe z=e>R`m+MiRXl`+D*RG8H+(!=0;+A8(!kh1AVGt2_AzwIk%Q=w;$0q2~ZmkM#5l3h$NKpcz{x#s0yrE7MZp zU%yO*F=yAj`r2>tR~K%3hh<)VpKYx|ovengDJG{Nz6da6 zJs$3U{xo>s^!!inFF#lRzVGAg&)3yozH-a^XZZiu(fK&x0?=vdulWTh`Wn`WyD{TNzhi#OAqWNuS&zx0b$4>Igi1bnkbEj>6mL z%c>1$Dy-dhTfeL-C`e=TU#a<1)hzbbHt=gGFWGwc@cj4RqP#2aU0=TU=08zAEmPL* ze~Y$HpKQjoY=QEf`){u`MOj^=2Ysn=SmPB#c9R9ePhVM^XF4Y+7 z>rKv4>iP26=F)1HNkL)ZuM%XRJhEOA=XdDx@5;HSj#UD zp8tOP)-8WFd*&T+rSF?ws0p6k^0I2@V~wck8(8wyZ)_CbTqC}$({JDT*#cL8FA#Cr z(#4c9`9`+m`=*qoD=u@*i1jyP*>vNO>Ex%8mh6X*Ej^(6uG(HR;K%kO31)Gz6XHK; z^f0R}JgIQ}-nUbci9Bnb=NhlQ$Qv1r>_?Pm z-R+qNT%syj97_+aR@z_36{UIz}De04f6 z(W^13>q&!iLu1RC5Yycyw%v)dzh+Lpt`?B{G~9QA-o>xCPFB0erMH$CtY@1u?Lx^i z?XU+Y{f(T2rLR3XJUObN*nHv*&ZJX69p{@hUk$sPR@Ls!D*Zxv=1VPSe!;`DQkh@Q z@##6@W|wPy^Il|u`AzKxgQ`zf>v-c{uH7QZpO(tM>FE?1S>LUvZ(4D>r&mpVD%P`M z_Cl{t%Ovq+gGz-u0GOvdFjam4m*8sPz-s zI;o?(%F}-AV|%YSHM(bhk6_^{Wj!y2#S2@Cmx#!)6wG^ZNpx#ASFHS*|F8K{l(_D4 zX6}<+V!1-R)NO*#>PIaP%8m-9Rr5q#3Ei2u$$eRx;2G7&8>}wR`Ekueihb9-Oy%E` z!ld_H`J8s^!r_aD9wx09-q~X_`LC+O&V%jUWrDg*TZ9$9ww_qzGI^rjtk^vYXV`ky zsYrBg&+vZwB%$Ko>)@B?zMa|;Ix&2K>w|5xBo!Yxc~`g#DXQF>@?xUH+w~G#H5axn zHL5r!>FOe4*p#{8-*3sy%Wq06Yba^I*zWG+A|2b_`%r0vY8ltJ`);w%8cZjCG+R;T z>9|#3Qrw;l?^V(nfi*b{a*}iGPi|(`k)8Ib=IqLRXXliHJ6xO_6OR0zvwz1EiC==P zMkiP7-tow96<=!Oxi8;1Qhc2b#NIkrd*%2n!}x^%X*M~B4p>%An>)k&sIB&lRMj7+ zPf6{0#K>MKaP%tIZQHJIA}ywDTd!;qoBwcq{EnH=bT~KpMVT;X1Uf&HIvZk=yUyV7 zdNpe~r6){tH@7W)a{T7>kM~+)))u||x# z&>AywmdV*ByW(UY>UmhaQ)1C{xU}n!ROheUaOUtyISl!1DtZkH`z{xm>)eUwE;6_$ zbWg8oPD)Z_aNNlP_nd8x&($OqB0p)kbv>E9;!XJK+kbr0d4lVlUu>xTGlSb^M@7ZM zis_MalBRH~=x}g9$}y~7k``v~mgyl_rJu+)^^CqSqi1YnL)pC>XS2+{2bI~)+;Z<{ z!GsRc=ayB5HWiEFmU3N_(JQ@F<6L*hODi|I>Cv(yX}tW>$JYydY4|KSH+bgTVighL zgt+OM(;3hC{@ly*Tu1*w%Jfrjv^pR3cJ{Y^_Y4=GwW}xLRWx^it#gN%kIJkLJs;~= zS-!s8*6+GCWfJSM|Gaum9b6rYPfyik$iDbd?tfWb*@+Y13>K~B-yS1y&gZZDNvx|i~ElBH-npn4`-`1S zlB+z;-FU(lS-zDKTf=!Kl<9_K-S5mkwc9tG_etO6dG$qw+hqeQN5=!^wVAcnnP@$2aA7m!O1MLe#cwyI($Mzl+%1`|YM3RT|jf(=tc%zwsHJDO>wiU$~KZj`?px zWdQS(R@XoCmCk;?C}k!*vq$q;ljHAH@y>nO60L`SxuncjW==GEYUQx;M48wNU!}Dn z!5`|LGJcwT-sak()?jU^sO21O{yhTIx1Q)Nvou)Nb!GQy700$Qz+CsiURZEoF_y0hQ&22ZQFS>omEFJv4f4p(=%<@O!Q>DcA&P#T+D zcGOegb6fiC3yO;!mn$i}vC{~Xd$285|Kd@ZpBpM?F<-j-)HAsBK=~uL=_i-DYIUEq zzIpuD5|z!i(x(kxG@qEVrZ@Ma-E_|A8$l`6)Ahm`{)X_pUdOiW(5ljnel=6uKcCK& zk^Zqn>7!-0OZJDk57Hj%EuS6S8rrf~=FZuesY?9+3)$Q5af`n=x{kr%ddr32ipG$M zqWvvO=jONOPfJ%i*R%2SlW_hbK{JM3HG5JY&CiUf_VaskYBFc6mx!_cM(^OeGrrGQ zee(1Xt*)otjv>W|RtEj>)YHv67_z6QVDG0hkLs83FHjIseKz^gZl8!Ig*#kHBJ%HN zRldzpEo55id|;i;hK?NLRV#EE{Jl0er1v=TuRQlMX;O%^|D(-%C9KZR)zsS=bbUpX zx#zCy_|lwOv!<_nk6v&}iJFvw2TjJkz$9GxS!z zFOvw=$c)(et}Hy0@$fBa>D6`~{~Qz5B6yDq@kBoijLLk_#GOvBB zAo%REk_2~lpV!%`_nNk~wtss%OIY9J^}(fAtP?qBFL3z9^mTX2-Ya{<_dc9ccDhPf zXye?&%>|a{-FB^=o7uU&=$Bsljm?7dc!;O?}g*~fCfM|NB(Q`z~-$V=2*Xf?Ze$-W2H^QU~1 zS^M(El9uqS1wrksUDB(LPv88mX!CtmrI1H1N$N*f9%OW8#qjJ{Gk=1%@u#1Ob`d!_ zs~K*e*)~IjDSTI^_LZ!lFGin3EG9*!${t(vb(!Mhh|3F?MrW%!$G)0q++lV^OgQtc z)-%lsMU$Mmr2bYNu;VX2A&~l{+1@Pr?iy41{k`AvPR!o?(_HJ_lGVzsnzgIeb25bg z%l>t9-QThUTK8oxOt|yAv2Mz~K;`9z{ALZsx2|uWoY23)Bs)-T^6r0yZIW%Avb&WO zt{*()T3|Xy^kLt>#I?W6UW#-u`fDqQzB!!hW4QE{r_=9MRaf|xoZNJRt=WGG1TMMV zmUvX=!*bT%n82bX*COuKZqd5);LC-HX$x*Ct`eM_;2*K!0*2^+f3e&G4?I#hdp=A6uNz>*C9A z>T&6vMrZf5wrbZWTMV!4xbOAMKsl+(!_HuzjNXdc@cq?ycYm3)-##hM#Qcdz%t>Ci znF>!eg}yVk)Gk&JKcATBtg@*0&*`Teb< ze9oHYAyFj<)>&UGE_c}4KiPMk;*t;U>q~ZTU9hrLm-ncBd;6th_q>*DI{l+O*V|_! z)7C2sKV{ghc{nL5r}dqK-s;&lktXTyCi$#r?0i-mxpE_`&)=YkNSVuw+`HMtvbHMS zp7o;e!@X-g2^A+KCe}ROq|p`bS)GucJ1O(S#r1Q3NbH_);ZwoQ|JD}1|E?UIlbZGN zOf#cjc~AGrU^Ay8{>&|n&!X}r8@$*9SI0TreiJjJ?P=Vnu9J2zn5H`ll-5Z8*EFeH zv|69{?79EvH3S~Z<}j-YdS3q*sE`oF68!b;?*5IMRy(pJe#LEYy&e9}b)E0C+{LH9 zH7rfm4*7erugEX+gl%G@pxIip_gj7HR)-Vo2AVDj^@JOS$1-ZuKM0wmU{dDE5~a(j?*f3JBMao zlkN5GnRz6##=d3hvBT301GMjMKXG`91K0h$-5PJd`0dxPJm|8{IOVaS@Wafa(u}3< z^WX71p6`;_WAjAv=acgKn6;;O-PK&Vf0=qmsZaQ+XyaFQKl>f0c+Z>cR`Yew7RBRB zyDLr_E*aQd*V$T@Cfgmb;rf+e;likS|M(I=d|hGb zw`QKu+Sq_21+i!MwK{C*_x?Uh&QD;u^Vee~*A~caKH|WWEO2!BVM~*;&xPx+_&;*Y za+w}nbMwR#J0^$OcQ)B_pPk2hc4DS+zvaB(fSZ#KiKX%5j@T{e0 z;rz2Z75_Z?bg|jo`F>79;JpclNwCPs?b5r`X8K&O*SxWD%6qZxLqMp>9mga0 z6s~n2J7>D#cHaFOgVp*ePx5X#G#`KXLSB#AyxDzA?40@64{Vusq4`Yl) zO`gJP)z%k%^c;6DR&ey4asT8ic}7m5IyvP>mzn~c)=mBQc30Wq`a{d5wDYZnLl5sf zCx4A4;`HAh&#r@Vn|;@=)$!{)G-;0HTlVbd$?458DK<_O@6z%Qt?kM9UT}hAf=R`M zY0Dz4(*m~$J^%gZ%ae;IPxl^Ch*+xsgmD+2H2VkTA3GRtH}6&b!Mg7^zu!CCA6cKD zUH$5>{(ax=6O*gsAH;u`uVedf^W*e0e)akGH*BK*OU*Zs{_|zl_Qtwiev#t|xs2Wm zRtW!`TvH*(nNamN@XopdX?|r6&BB&1XBAp~x%SEE{SuL0nB;NudC3X!+XwEyQCN3O zi@k$UZp)XQ8N92kIaj}a%ku8~k4`Pw&lBaI%r1T#c*nGPp52NVPnPb-OqKh2{oShO zu65^0U9A{#@Snv5`F{C4p;>lwjvr$4Df(!{+x_?a4_p2<`zl!#Sl4tM(yy**^{*0r zn8djzcg>PV;qH3rtMoq2FiV}HxbI+CfYX=BKc^b+S^JSW@%zM-^&vj@dsctv{P=Wv z$BTQqzc>{?8`(&m*~M!%;kvYI?xHMhJvS%!vq!+F>|9tuF;?(Uu*IPP%9aM0= z;~KRk@Jnk+87EK7k)ZsguV+1s++K6%PsZ-t9Ao~+E?dm}FUQKB4Z64HY1!&0Ew&n; z()ypvZuAM4lKGH0bC&ugh8;bhe?GeUXSKlcoVlFxPqr-F;QaJGho*{2Ezjnz2RUkT zbN}#vIJ)!_=71u2m=H3cXn-`Jh-IClIcVrHh|vD-r4c75iI@xQ_5Y##E8^*bRL_-P zU$lPMCzu;AV|Re(a6+4;0gu_gs{J9lUZJZGCtGtgIjvQl`t#FM@4fdjQ_E)kKl6Xy zew*Jf0`J&X7l*l(r+xqW>+7R8UuVwzzxesh-Tr(L36Jzv%j6X7KKyj%%;)KgH=V2$ z*VGU$YoDIJpC|23_0&z@@-{p*e(JMdZr>wc9@E_^K`9$AK4f}rC;L5W=aQ2=@jXk{ zT)f6B|9N_!A-{dk?*&`@40+qFJ}1i7n!GzX$?M!%wIw3#rtgxEoSiGb?@8#j%*TH} z+^uT3@%m!M-lBsSKG?1|*JG8kliqtNj@|grmUV*Dx}FyOuWU{Tvdt=Ue0==xo2I?J z5?9JT9XXq^VR^C1oppRN_mbqFJDD7QZ1rQwnJ>3^uP+X}7@6Px{qa2|y&u}wV%7@J zKjeE%)5|fhWc$B+(aL9j%q=h1%2syQH=H$x%iw49noZ}HswN#ZT++K}!jWm0Z{C!! z-}6v+t^0wNbaZalc8U|7 zyypCmThXg)_#EZx4oauSoaL+UIWRpxjJr8LL1}~6E&lV}l6r?b&0l{zf5Sa2^;FVd z-@AK%J^NYJZLYldnA@=(kwQ!3g60HIRPd>~vw5J9QiL^3#6At^FX%@L1u-lAJGx>KYehG5m2!nQ}4CW!v$$n?1_{{d=6A={Xw4C%||DG$ax%Tbm>-*Jx@58ziQNb2R1H^|N#etTcUJ-uOMInQ1T6r}Zr92dg&Jl;n0z*OpYi9`5`z zVD;2d&m;+OS0V&U01HEjp8v8t)x3^0S`#^lD(c;X#|%v#UNAwa7l0WFYUU z_~l}m>DeXR&&0?x9-i<&ft$~Yej=6`23l9;;7|w(~s5B`=oVk=G9ILi}{j~ zJZt8p$*nIt+-4_**{~R&T{($!f5nmO^PT>S$o;W8$bU*>t!T#M13i}}98O7nW>R^} zH#V?h+rG4#t{=Inz1Ir4ZyjAU)l5G8rseOscTTyrN&UF;_~+@CNt*r7cQOC{p7$j| z`Gq-WoMVn@Ta)kozJv__iSIpsltj0>oDhG~`C#qqsM0KvRSdgj<~qrRAKYNLIL&eI zgeafcPt+WjDr?+}o;G`fR-oVR!{+Jj{E;h}k6OA<->@d6YDw||1)03RMiPe~6nZ;* zINN8&-w9F|>qzK`VA!#)GVU5n%~XvgFPI)nH{U$Aj*V?+z{Gu%12?}ok*Rx1GW_rP z8ig&N&#-$hov4-FuTT)EUn)@IF+ub1tjNvpGV1wms_ou>^TLbZqVpazqe)SU7 z|L>s7pXOJ#(d+8Fhu0^ICruH0G0iyg=@RMgckj+?bW6tW{hXjT>11i^yUkzI!j-Jm zK4yn_aDV35{xxE~`{t|ftiD|jbU)a!2j&&QO-}7OT$itr{B5us9MBi-QHaG z_lwy6p7wJRadM0}bNVFXl&~pIjPI8*B!qYTE%|iuaO(OWlF#dkj6EdsS95dU3CET9y=vvUaPFS;+=!eE=~=&) zS$s7^n`ytq zk*hqn)@)mH_NF)YweXPjVQY;x7ne9in!NGxnQu2|Q?JPf?yGawY| z0b47sNv^vn`PXi_)5pB2?3;qteYvG|VWn?oC37x={r$VnOQ)!tpL$fl#&!MMr>spX z;qiQXA7oT%-T`Y5)_gv-UQ~5U@=bg&=`n#}4Mm;bo{3vIz{OAe$Ev#^V;zzsr=vV_5AfV^E4k$-o$mRsZ?t69V5pM&&r~& zvgg)6xLUHKQ9V)M{hx&8XPuHF2!^9A$VZ<~5A zsDy_}ye^$)!x??_+J-#IHCxyVO`NorUUobfG^Oy6?7kD-lib)Q?E3eI>8W|x;dOgs z&7z~5nWPpLv>v`Ye_E>LYd-&nLf;}9SNy$MetgfQjF&v(7P&mftUvwUBqaKcQ)K1d zqf;BK7I|*eduH?AJLH_j1>0B0qnLjer6qg~%etYXyymOo=@%|nDiecPR?ltA+$wg_ zv-pQx+(b7C*^}DaE&PNoEj`?yvdC&uPs)maVf)J`s~QES$DU^B-nt^J!dflh_u0V1 z^W695M9uuCxBrQQ{riI7OSXRaC;G1cn$@hs+ub8(`l(G-FZ>}N5Wu_r;VQp-M=LJ6 z=}gK_UnOC9VYWh>pFv>Pj&GlSZ`X(xVLTA2!le6s{`(yl^>^)A!Nd8X@XIq@Kb4?{ zuW{SH|DGIMHYc!h;Us-)nMr4>PVRnr^47b)4)M3LHZAiW{Sm5hmS2&7Ms?5HUXG~8 zY9U(-yl0zVRttEq+BL6bd$(H8m#VGOx0WudnX+d6hWuZWe$!2CI)mniZam2Iu>6am zhHd-GXs-FGif&UIC$oHac;32~Ih*bO$H#(lB?j`f^B>GOFyH1v=aWBP zJ?|1)r}5q`aT8Sx+p#ROYpb|#hy1T~v5GxQFBr~kuw!);Eo42uEu!J zuAjAD-?&(+iCfMf>i3gZ)1qH;%5}(b%u5gqa}tp9`I-88!sb@JxXC+MxLuqNO^|rK zj@*NM(KPXZCug$(|zR}5v zACCQ>7AYg4IdNmOn#2@;#(U=N=^U;T+%4PREy-hIO`bbBLgt+*OH#+lBYj=mL0KFV zPJ5i=dmk@iz-78e$u$8bdSr?#>%z>dMx#(9?EyLLLPrP zYP>t5U`}g}fm+|T-yNwEQxo>a{E3~j{Icb~SrRSnE8V9F3Pn6Rz^i8!a%_iXWamcR z8Cv`KOn*E{uwvs8j&HiY*T8M})pN}9#oE#5&Er4EU35vH-;5` z-u7B_vCN0-FWgHP9#nPx`z%!c->#eNJ1woapRBlcq%-S?M#4Yc8#>&)hnLB7(nsFDb1u`Y$gPP|jVg$nw!zh* zt&nETBy!e#9o5ndiWP3w3&HuPJi9y`o%U+WuP3`@}uIu!+<8 za&|V{WfuP|`Z|2G{;|d#UkeU)-xlLZwqtlGuk+NL_u3v|#k6xf+MG6SzB5N%KUpeU zQ+cQCmw2&|PlCFcMlKIN&tDv-q_|btoRg1pMb)J;OLw7?ZTs!46wYfEwzx}fT_&%m zw4~8mtD|Nf+l0_72YPGncAR;Weof_cL_}st4#R>UE91IO_oS((E?IIy{EDn5dli$^ z>(sz&?-MfCF4?9sGvTaw>rtMvlLa3yHB5f5zwzeTIjbHnTl46-2)E`YMFWP^4Oy~2 zGWMp7F8q&~!=u~2lo^Yto;dL}Y{}cGceftyIQLY>*K5w1niMTY7u5~Z%ADlPQtLt( z53!is-*NC$9#?5g#LX3tMK}V4X8zbJIO)ds$5ll^m#uRb9PMo|-eRLDWAxr!YjPpp;Q=G$DSnV*!`%4ttX1ZYrHfyY9%#_O|t2V&CR- zr+%{uv3)zx6%ahnRHyL4sj{S%{VpfEs@;xk>~wm!>B?DcVUB<0E4wqS4SvNXziQRI zCbpqw#vTqo-@;{f1zHEL@42|v=A?TsYfQy{J=4i|>N8U^93<1YZ}7e@n0uOW@hUA# z35leeNy@Rl{Zl%1zQ^kx`h8$gNAlF$Um2fxwdr@qnumB>tGy^**|q*?*vXAgq(yeb z?%U(NiutU5K`f(?o?6^S4~u8_`5ArmtOecAg!#8O1i#RIHBnQ!FhgSX(qu;S!;Wp7 zpXN?q0?e)?x3i-jVwuZAajYwJm>Krq7r#SG&!IKQyuAZJMEw&ylMk zv5u>}vz4A^a6DP^x3|CNnb%CshYDAFt|?3IzOqwbiqq2apBGghe0aD0l5u{e-tJQu zS9u@bDXZ(*r`vI<_)+BXHx6!d=Bb>Wd8uW?&WGO_t8U~kiDF7k<`yoU8uiuTj_Ug_ zDcU&)v>WVRA1l)45@*&8D62oImr<~2Z~tBae%}v!E-sJjn!hF4@l8^m$Fh0z+e+^; z-OjiB#93OuB|u>B)Q`Qrvt^DYcCVI|?C9^Fb zM*A0heYJUs)S=rEoCSt6ZyHZu@rftB>CdUpe)AUpx!n&5R-~2l;laStByP zHY%UH>&TbbrduUtGx|>P`k&evQ}zCe+SSdH(Wy>Fn{%g1$7*X6De z`17DE{^K+C+2@wrEj#oy{o^sFGJoBCO^@k98;s?*M%-;qe!a;rQ%h{xWfiXMy;`Z)^Z9(a)&C}hUV7oyTUdEC`oWRM&o0W^?O}|_eLVZ| zDhZxBIj>mKzm%PbH|$LJR^PQ-EE!mA^G8ATlv}A0zdxLe82kc z>^+@$-FcCM-`VVWJ{GQ@dp76mqpR;;ZoWG?J^tPO{d;%cvignSGOteZy*bM=54a6F=rEeR(H43qyqz0gr1=Q7ZMbQcCQkz6kGd ztN3luEAwmi?!w?H0XJu_ww*Ci!)(c|YqQOqZa-UJ_MbgKFzf(k7ZKd?%TLPUGB!0b zhVNsyz%ssT0qRT=9N*ml;5cx zRkW13_38R=)dnqYe}d{(UL?UZ{TB-X(MI{^BOSOYa{`%q>c*|5T*z{afR>M)IBNw{9=LsqcR`kMC2# zmgJ5@vkorlS9JUP`Q-gfft9lZ_ei%MbWlHk@%_7p8g9ZZ(++QEx7E^|BKgm2e#`g5 ziV}-OTRH4_)VDtU`|IuG!-3kiY{_g>pYzs9@Vmd?Se)FR&sX#%uzi`ZbXRSSgZxy% zOSc}%f9BeEkmXjN#H;xdr&zRktXO?I|2~Bcu3 zC7!OZ*(aiPn~gh2u`lZA!?TV(_cT_w#q(!{oXRw=nQ{Gd-oLL$A8LHuEZAqN6TfOf z`*-$K_w2;J^AS4@&w1Z_Zh7{FyLw5!T-49MlkYyhdwlOX3(HxCZHqA7Zn?7_ zp3juenlfwm-^jLjp0Xe1X*!u(Swmi4nfv*0zR5JUzb&GZI6d>VCf!&z@B0M5{mu6{ z_KD72KSO%jUG_CBDSi{IXV<6lecdJ}ldIVwC=$D8#0>hT? zciVF2ykF68;__|z-qKHo>J0|cF)|z~4oVv$4?WQTEa#V*oYfPRD!MVo zm(`E%nGY5matmfF?@PS4$S-Pv$)=ew|Lb62q)V7$1> zRB6ulb<(F+CEKnJ*6W|?Q++IU=93xMKdLz%{3*f{V-Rny;UN4h^WXgi4!dVIHQnps zyt(39h?(`;d65+kyWjM8+@Ht9TEdp7sQ7SJfSS|GQj>2!m z3tP6H-tA}cs(bCyuhH&nnYzwhZ<@3wdggR1d-d5$^+H+Nc?UBZ#ARLt^9l3i*cY-K zeto>_diOaS?nxy_gf>XsP_nT2nJt&UZ0F~uB$J~OCtTi`EWI#u#$3i(JCd(#O?O!S z^c-UvxA~;DLUT`}DSn=9#fK(u`km#;*3hNGeA(fLiOR+aDU}Bm>f73P&Fxg_iQ3E( zsl2hJV{!XU;jda&A636zdU5{M#PDRjkFkCHWvm}LuCl)Nv5|2V{jZu)l(AE@RO*j}7k%Cr4_#!HL!2YO4lExPk4&hs&= z8;|}=>kkpLIIWv5zvyh%?0o)Ynr+YqrejV!Qn>fOt9a5Lx$|nq#miD!54LB1DUND0 zj);yjymDP*&73E06GZwpNqF8{esaI~#TNdL4-*VGo1|oP|FsM~dM27FU*u5PR<2#X z*23dK`lXgz-opVYhG4#Vl^^QvGEhR5(b@Fpdn?iDDDfS)- zYLN=`%U)PmD#Fqi`p6?P-`{HQy9F6uwhepK0fyeev>mF8R+*MV$)EHhzn$zwDm2q|i+Ex_rTvC3_Wk=BUInYe}s9l)FY( zwN&!azk4^|9W!G7$fc9NWuEqndg}nC*F7=UJvgqf=6bC1HmGjJ@>k}jvd{l*s{8r; z@I{5H1Cw?N`ARM0zW(mb`_mIGx1DL7ugz&9m^$gA*vC+9$Iu^VC;0b?Bun15KD^Yf znd7@=$s(y52X!x}8V=pC%T_jLzB=n(+pzEk%X%$~8{6MkbIqK>w)CwX-~G!e5j!3{ z4?S)1wd=u}$D#cEB4rD<{(Nx9VrHo7qi-#*cb%11dokyt=Y{a8=b8P3_p+R2p6cG* zR{1H(`TX)V$NNttcvPHn;}40vt$M)!3TMefv&r7ftG*f4y@O ze`wi9b#8DK>@isru4~oX;GDDAc)jwUI@L)lPh0lpF5q}<%CeQgA?Q??~ySQ)eAlAvHM=-MH%I@(-(8gT3ktwRC%!N zj9&3~*G?5P$y7V3z+sJWM%ZKupEA=hus?)Itr@6Pkn!vs0e%8-zIg8HTKDX*ZZpo&PO{>1- zXfL-A+i z56$G*)z6A;>1|GJy1V3CiuZN@|EDCE$1KRX6PNmRZRMocl9kt&|5?bihI5JVs)|Ab zM%hO1b8Dif9+}N|fB)jII}8tT&#GP;%2`#}e%#aC*L?H4O>VA#c6ZfIzrG@3V#BK_ z?~jdbCY!f#n?G1@6k)ets#w)?i?hpC-Cye5d(VphE>dk=x##BUsasROelqSecTLN` zq+2oDFzBJoiC6dEO-( zP1tqiYPU|2mBsZ6smmu$O1@a>ytmi;*frM|ndk4Wh?#Ivy1Vtt0-+;1LJ>cAZ<1Fj z`pA0pz0Y)`_LxTR#-;80EiY?M%S5$)6!nt4Jhy(ffnUMCi>yrbUnZVD@b$}$xAp$V zuC2Z5Z~7>1@wutT%EDvgboAef-E-V($LMFWO}i#Cv|;7b?xn}W3unD%pUfiID4MgJ zHU4AAg81t%WAbi4Y`g0I@~+BZkMb{FjdNc;)^V-a+S@r{`p!QxX3h4gAIn@>Om(j< zbiA5*-L@_|bmFPiQ`SZJN6BTqE!CWJ^>p{q4Z#bK3JUOLoc=N z@F}nAKXJ)moqxKPzbqj^PH zs?1N>EZkO#L_f1Ry?ST@n1FT%Dv9&YIPgB7EYb4x_+P1`?{-3o32J%T~eQ}E$S6N zcX@BwYi-}dCnNQ&td>`W{x7_yuhS@xV&@w=j&;ozma8eLAy}*?uXBRUh8V@Vmx(lEmv~4`>G?k zA@eTq<}5p-ZJ4a`G2m*fX5zEbvyE^1H-{x#?X3MdM_%u%pZA;TU7TBbQuz4GgW z;nwW+371}XT%8)t`N%eP+m2Z6^A~2NvvllU;ArV;v|;5-o3%T&uD|rVxo_3tqsgE2 z*`-&!divvDw(E-|$(ggQUepMGt@v(lYuc~{OGnH?!9W4r5i>Tkgm=U&O`xJSHu^rP zdFdq?3Wk=TyHE*s#ID9f7snhg^otYx-%)!|jxdoN}iA{kxst&b&OR=lDSJsg|%+wVthUe0hEC%%6$d^^&$f`u}PF`unkaew=!H z@6T7IxVxQq>#yzKxBtgOrzig-KHuGaUjHGZ;uSregI=r4r{9n3_|p(-z5I>Rn|Gh? z9{vC3>B9^$`LM;`PbbFCndbJa+m3}*y#HLI!mW4zYXZCtf?oW6|3F_eY~}a;mKED2 zc(3d6yDvTbsOjE*8=32_uRXSW-^%~{|GNBN>zk*4 zsM=B1*`KZ7V{~`*zY>dEsiFnX19iMuSAL6sp#3pc>Hn^(=ilQGzMeYO?ZNw}kMb`^ zhpV#vWQj4&*8eJB$kg&J?Ct*s<_RB!Zr}abuJt3ey71Q=0fn3U4_C(q?3=8}xvcr_ z|I?0ox4iWKeg9-%uvR8kYw49org}G?n(9pSSpD$sy(LG54n0UdUUWaus-j}*%WvCD zCD-4&^-tpel-0NQXNvDX*f}NW<&WJ(i4#}f|Iea)`Ignj{VR)$uQC*Jmsc?`{W*7c z=KYn4yY{VaI&k~zDlye7|MuOR=_+K9|5Neh)qken|HMC>eVVIb;*&?QbHzkXcB-z) z`p86ja_w=q^46N%GXFYKG{e9Ubth@nzd-k53H;q;F<8J0h zE>R7g`Wd^@=V>%C&oY1A{3!4GagX`W!&<3sZw z)_WM2Jq!Q(egDB(O-z~_@?ALB3I3{!oX`K0(YLRe|LZBK=NlX!YVmt2*d2(IU^w5d zR>-6haX)Y4=_eJA_d?W9rYQ_ z{{yxim=oOdZJJ8Y#YVlSKclYNop}``S9>UT(yB+__AzZ%oN?f3sqsmc>x-*Q1zfD_ zX4kG+VD|o-!da%vHv@d_E{pWV=rBFy=i0qs{c^FdX)|gR9oNRmGg#iM;J0t~HtPNy z`dWmEUsvFITHw7tBQ`i&&m~%jK%~jY+#fa1Xqx|yzPFTBHVZ+k{UUE0rNblS9 zX&Z}0uJHpgMJJE-e|=N6Edtm-tz1#_;$D^&vd$&Hj9|#VeD( zOxrMT@Bg!I_nFt%K)as9?*XZj}P9{Xx~8 z%o|@PIljDPeC-tPDrw=4yf?cRC3Hu(_o2 z%4Lp)rhnDzGY?u`g)G}^ztF9;?)S8HCRS|>WveZB?&hpo!s@NVy!Tc^+1Up1nH{AG zC8_UAIg=jiM4q<0m+(XO@!wh37-g>&u?F90&-_uw!_}PVn>n+hy?6@G0&NWyBcZH| zOFD{|Uh|S!^l#5m@k2bUS%OAe8&xx}-`H8vUaTsfe$?mIx!KKY+!@Wzu74!V5F0Vq zCy)D1OL5ubr;A_jmtE_euXk~W2LHk(_jOWPZ1zt(*~)mzeBP$|>gQUI%kOyjedS7= zd#7D5dBIk;>K7jK6e4vZ*1pL!xw`a)hN9gz;mJ*A@lCSKYu}fIt`v~fJ?JG~Eb=gZ zzSkOI; z()u5YzWv_v*JNGRDR=vc&1+w%i#%4>I9f8b{lF*R9ZD=U2_nD0Yp`$Jed)Q;iGyk1 z1!de7C0E_K!qt##62mtyrT#?8WFN+b{1zf6+vasLu($30s_D5;Op>>|$38y&mttjn zfmG>4-d}&?zdg}OhiHuS`syiQX2${v2kWXjBF z=G8@(HOx&quFkdn?vf6v&2M>}Kdsf8bnnHJr6;wUr7peuqb{+#K&ikbiy^NmgX{3a zxf?_-eX(3}Y`>&Z|DTgb6<&r$LEv(0I9 zJ=^>b1+CAT&2;d-{o#whT@PxVU*YOduOjE2RJeCfu*y@d*(F*R1Nik{*m!x_ajcS0 zc~@~DCuAqf!pbG}b>C&hh^nOlY=?UFPF{QNn|tcuU4z$U(JQ}v&2V66zfh;| zT%5>#?~K&y*1CAcBMY~)%vo?@6YpmE+sC>}X80rrFXwOu&z?hnkAIzNrOyAFkw23cU5^zoaT_ z$jb{kzGXG5-<&EFQ(Cjh=)Z@t?c#ou?t5W9*Urst3>UZF&9Zz?r+)nOtE}6ZC(o9f zVz57gn&kq_kUT$;E`Ixt#I^M(D8zbsxQ>F8Y^Z2I~ zrZ10ev@_u|C@kD`%Ob$=K)coY%#)in9Z#G0m}+Gny5^R8T;g=OP^RtUZJqa(rmdBF zEMs{(RrTxaIXTnYUi_SqOD zCvS4d4V>-3@!`RP*{e#Je%L9xTzl@jd)HCpv>vmsLWU=2Zv6N?z)*3Y9&g5}J-cr8 zGr2D)d7=N!@a>kkl1&E2t}|uc1Yccr`a@;OIo%ZgBZ`+dH3?o7g)+ZGTF8<;@rzFs` zvPz5b-+}T7^~pZVR(o50Q9iurMb4wDW;xaMY_;=d_IJF0opxi3a!b{v9Xs~S(@^bB zVY;w?>ZB#oHBLIL=eqyb?rELq8Qv_Mrm=tPIZdhb(3^Em)tqabs-|t5l>c~c!{)2y zx+?cK_*4bW@l&(;@NZM?mr&VTqQz@JOHTY!HLF2Sm&tkJgkwK55A?YjHO5!}sTPr~ z=oOypQYaMW{k(hA%wMu`syi&RJQA`6d>`1IoNlvx?z1I}+^@X&AH2`OH0u1Wh;<#l z_fA}#${XYP#MR_$U)IxYiOcl&WS-fmeRXwF<%*X!2L*hC&YXGvVB&hq7;(v*ea4zo3_9yJvCh3@~eXIH+ z@bUYG0*UL@o9eQv#{HlX$R}x zsqtRhT2NYgd0)Mn@|5(;<*_@P_nw>NUftXI!_YsZ%lpvf)z_Kd z{Q5ET@E;2;q3cT*dFOW92#S5m&7Zq4=j_v+t&g{~YsmI(ezd@Q<3aUkzcp2y)#tu- z8*g5_B&~c`t_A-l?#bTWuRff+v#@&h!`x|6d@mPgq{iF{`6wtGU=!i_v0!$@i`@Y? zR?Mi_yC^d&Ppc{{YfG7scAW^fTGfo-PpXVto)+4_*XpbOc_oG4&2aUPB4vfB zdulh%eU#|Dne_5i<5|zQyK9&>XaCf@aQ{pG`L`zLS{Z-kKifH5?@rGrA)DjVwmvZ9 zoZS(g$1nBsr)d1;E^7{}UscnKmc8&e{*f=W_=rH>p@KaR&-Tvo-xi#*@|2_Te1R`Z zU*25h_AIxsLu&)C{Oqpko8=up?XSkC$een4mSyLahixky*WO4ucmDRW*P*}KMXGre z)^GljwCV7>jk9`XF7)0FI>e-;o4?m{?Xay)#mdn6OH;UwimfGpJ!@`i5Sn$5kJ8aJ=<=d~utN?WcbS zw|!seaqra+?{gQVD?UyT%9UDlo9%_7_JxlJ5c)h*t6nt5ikE|;_P&NDF*+FcVI7`5|LZ2tdfjgVj0-$^o`O~0~Q zp>F|u@4l}N2U+JcDs}eUJ9AWV{w<@R>ix~ny?3+xPEFp$A3NnrmEp;_LvPDA?Y?u2 zJ#h(FPiE?NzOTQ}ezyLdt0ZUlYTNDn-DzK9lDy`>Q@(j^$MkQP*$sP^q)aoroi4bB zx0yF0p=ZxD!w0{rB7S*XkdBp2xBR!~q6JIx^+WF8B(v`1zQ3aK-MEZ1!Q-#P%++7! zK2dpabN2)J4{Ww?X63pDFZ-LsynpFTDfbENZ(Gwd|Glu^u(I*&;*w+f>M73O=RW!t zJy|n9pmX1%0yq6jXKy81E{t&dx-HiutM`+-+4Hnj`n&qBvZXf#b$#?widuiJJ!adt z$$3p?caI2dviqkOu6DgI@{ZB#U;CJfJlqpyi-h|5G^<&8GMoxL9X}UFI27}X0eISeRI9@eWr6gSCwObSWbG9-5Hn4y6O|9x!P4n!@7?7{i&;dy|RTndX9dy`_h@}{x`(7U(!C# zIQhPC0Q1C?oXq}Fky99_g>YV*Q#bz=pVQXD3%f4Xa%J7o()3w=JEdV_wE41$#Hybl+WRtxvq}q1s+)|^MrUSMT%7Nz=cUas`R8e{r7$zhasA$m}nDOQd>**~!IaopuJmL_s zy)Ddq>Up5qh4ksgS$VOS%J_JdC-6P~{zW@dYOY!Il%tIC(&ERDT=^la<7fY3mj&B) zyGQ9_e-w57S?c&%2)~{c! zt>|$26{}j-$sgG$CcaN%$>o^xQ-W`9tqOnQBv-l5e&XH3|I#1ID7uHvRqql=sC0NX z_mIMSOVPxme?>n?{@$SE!5iZJ!dI)&WVhlhsjEsVTkr1l-1w9&OySjOskSwXTE6o8 zo%INx6Krk0_g#N`#i!F!<+UCLS`UueWo>3V!ICh&Xwt{~LVL@$a761@ha5HKycq1v zxsj*M=Xr(eQ?a{VTK(E;i`UJM^giYqEa7%!=b@kF@21qt^qF#(eN-;~-EmicX;8tu z?QgQn(sSw#>a6}e|CNrXn&Bq9zX2z8uCp%FaF^$P!Z8ZfgdU;b z(i!s}h%SH7^Z1F++a?>epC`f^{xw+Mag5=g!Cg9atMXU5ptGmBD``m8oc@2r;2L`Fm()-+B+I{}^cB5j{{EggC59Vp_42i@#D5ul^Th2bAxV06?0hJxLhWu^Tv)p*|V%N$Tz=wm&KxjOE0H8Gw+m1 zoo}Q$_3dQorQ3q0yk~LT&RaBFRF8j$rE^)e*S%EhHR9pCh1N%BTwSAfq{1Qo!1RQ< zG4s+c9hI+h@!&kjTg1i5WUD=ytzYN~AO8~z?IksFG0z@nf4CMOs2pvwNydrkTFj-@ zt`BzA+sf)qmKCTk3h`Bb@v%Z_3um0L&c@DVdcs$Jq~7~}qr79{G?_^&HQlqme>0w) z(x)(|_L$+>i=uWyiQLQ7GYTvs#Lx|Y4jw_rZWZDD_&vN$0TLmOBwi>g~>R<8^0E+wkb7?dLN!^S8%b>@ojzdh3%( z&%TrdTKZZ$dd&O!W!mLgYVWc?7+Pkld4BM>ms~4nU3zuj(Z;T|tFPYKbZ1w`@w^@D z4?bBrFNZHvsX=-Bl{+a*Qj3)@pUlh1+puuGV_{Mr&oUkPBl5b7wg^kTns`*5d#mb0 zdkYzkfGrk#Up`jUx|aJ@;X>b)N2j~@GqZj@U4c1h3?2#w4H}!8S|AM?TVf0v8yOf7 za|^}Zn8;$8?SkKoPfxwSp?`O0dCTt&+WZ?IJA2;Tm>L!{)q=lEBXE_+624P?UtWJU zH89RdFnFTpyEG=XKb@U-!TI&ly!&o-IOehZHU9VgV)x`~{y)$Dob{~QJ#qH_bN>G= zD@&D*{}+6GefD{OLx*3!GK+%G<@n8?bK>J~jdqRXI~8x)UYae}_xrbV>h8U=P9oQG zVyk!zU)9h3*V^F`8~8C#fUU*vyurKfyKy{f9J<@@zxlFYNkH0f^(vuz$KQV6ZM#qG zVEfz5pPx>D`gSmH{ZzRo!)VYV9_u&X?j=7zmbd@j$%F2)s~meos`vQ!pW?`T`)zk6 zYkV?OF8hREf=hfh97+f{Fy)4STxQhg=GYC*+eJzq+6B>% zP9M3tSMrdX=gW=Fz0(_)DJ`t6`~T$L-+c4%_4n=Uc7DI?Ht){wwtruLevf}(|NZ}- zpD&)A{w=-8^|7$x%#5ZfszPzUTt0CGW$#M(tLD(-$G(oIYg$jH%eCg!bB&y@nC0BR zcrWzBp}hE}_M!m4Jo)!m6t;dWs@`^Znr_A88>iJ(&KhJq-=2TqrohXWS=*;OA7Ib= zU8Qc|#&zOBuH5?EJ9bKv(Ts^x{WrhTRQx$BS0?RfHB)6q=1dbQzO2r(p5t+2*LZQ%PxFMc*P}^hg&z_u9w#MMOlvo<5)%6Rhx4Z6 zww3KOOK(3ne*39p=WXp5>qPasS<4<=j<~US+N`rdVP$rgc57&TjQn*ms!#;!ONDTmM8PhxForzBef;47bhRC>n?_RE`wASRh}v(yh_BW~Gm0)XmEE z$I1n6u8CL7skiT%7Ww*Var2bxoZyM`WcKTXcXco)J-dr3iYS7~mb1>%Lx@}8--&*i-)2+*!W%6Y2 z=*4i)F=KQ5BBtl`L-ULIuBB}L2NLhRGJIqom$v%i)k@j-8Y*QEC$iWv9Vis5NO*EJ z{KJY{7Rm=r8JDj}P<<|G=&1RyRXydS)!vX(Srv&#oXjPbYNZ(S>c6*ZJ?5bM;mCyJ zmuIS6yqIWk&vCl|t9ge_(Iviq(H_AmsO@v^JdddCd1t1{BABo$@sIc{_I%6ymIsBjvq^y&!)Zn9(Mo4 zUlHS!EB6HyE6R1AXi77)E?blJTl+81l65n^t1N=gFnzg@f2kxwxlZ?VrmaS=#`~@l znVcS`f(a5YkL{0IBJ7oRn(6wNZ_{NH+9tH=FBhn{v!5FO-&TLkAFm~I4{geQdUk`H z#+;69H`Wuq7510>yv|NLEw@>jBdXEfbAGS9&e5xTWlDc`{nmQ?Fh-V~NnbChqW)Wa;{jfQV# z6@C3P<aP^ZD5|iWs2ovE~C7OXmMW_Wz{k{yqW($w$#2v%JoaW15AqT05F-vaop z1#=p{&G>NLBU-+Fi?D-Xi21AwOt(X4>x$htzaV#R$5$CWrfr5v-*%+0Jhx`cVx==* zZhT%T)Y_)UrL4%5d`Z>RD3r@}l&ziSNBscD-1c8Tht!bLJk#?#ij# zX9^_Te{9_0{;a8Hq5s_3r`J47XXTMi{jOlb68>BKvF)GTdt>V+C@j3H)B3XM_|NA{ zE<5zh3aQ+-ao<6moV|r7OgZM?n|9@S)*68q6?=Ei`~Kz4bXmzc7pAht_(a-fwo7lh zHjj1FwHckRtq)G0D-TZOw5pn$yg1h|{LCSD^JO9Ha@Pws&i$_Ky09-#bmsNUw<-%0 zwWj@iwWnWn#;K6}PnlCbWlhXo{#A7DeB8w$t71Sr7J(3`Z6K%ysP>_g}=;i9j~h#Ts>peY5q*f6TCIaceYwD7ZsI@ z74)>8v5$9tvGh9CiFN-g;+`sHP5I?NVVO^{*{rFFYnjb0f32}NRyK)a(%D4^TsL(8 zwY#F(xF|}8lJ#$Z;3*}vUY-h-qRR)I{(+sC=%HHn%$7G&v zbFZFu)sA)PE-(K29(^lzC2eOz^TDQWl`b7WiAa|eY+mHGJZXi zHSd|i^4ezGW1eZMI#chSzUJY3!tBAydmE3qw^zD|?wp;ib><11?V;pXvKoC0>%A^1 zEIFwgSST*`p^)ExgUwVkr?;kMhQWocz0t2z~x@pqxGaWW?R-9mD zIG8&j?U|>FY!G+C$vBhm%mttRWCoVrGJk5KRI;(W@I>V6iHcR%AN1_=3u9L}c~Zh_ znnKpfra6~4d+S*1(1%ut!pdzzK~%qi7(qMqEp<;ZYnCR6lAH(Aa*wQcU~ z>93h(xf`rEaGLIQRdfC=c;erIrw8Ket$HVaRbK6+6E3sL=|$zKH?b(UJ|u9V9Pb6Q&Z(I@cHHBb+pm|mO0fRS1v`tolP8PpJY1}} zT(0(s@Set}lV^SZx=r@!xl3zvX3y8t**@2Q#}Bo<54JnkFWdfh(#0#cr+M0U|5tG> zaati)JNb<7)!S{w(VkOfwg#SQ{5^~5vZ8c&=HqqiH$5q-p8YM&^~y9&CF9M_=CLWU zf%BHyNH1F@pDn$1?##6luPpj;uv;qmSWM#oDQ8z($o`n&e6CtZt4CY4XSSCN>kOH& zbCF5i8>bb8FYQ~mVWLCmT+Zt^x5}4h{Q1Fuy^5zQrR{9ZkK-p(-BOn~_AYrnZ^PoW zhlYuUzRB)QWy#!mf!BZXO}}MD&1C#?24bqY9xEAi>f@4EmT)E z?bvkW?fnkNTbfJi?Bi}YPcg?2G5 zQ;fdosLCI{!zr;@BJmYt9 zs-*9AkuTq}lbk2S9bH$F(;DseQm5*#m_8{rcuS3tExBQ^+M}V!;HA|{_gBvE=TQB?57*9$y{+{R^An3Lv^WY$>JE#M<;Ce z9XoR`;PBBtzSFDKLQ0&@7HjFZIL>}$vb((C?wo?j-&XI4dw=Td{2eELOkS&J#XoB@ z*Q)ZP98XtEKmH^c9>XjCB!eL-Z$(Y$M}6LpzUpjW(|2Z_vDt39%-E)@Xt>|l9-MRJL2f^^~5=S=tT4cQE0e{l%MaDHkmLHA2X+L*ev|4sq_rGbIPQ`t- zJbiGQGqcqc3+bm%cFcHfbT^Lk)rO3$l+xzZS6@2&zLvxlO@1l+&R=xPC9~@tEero#dk$v^5~W zwcJXZFYRlZt6szDRZDK4)LZ^*b?oXV-)?hu&(ThO6b-pIJfAwk-|0XtQOF z>D86j`|CV*E?CkonbXO@Y_f|13tLHjseOQ?J zF=Kl2mX1|{b+4uy{8~|wbos2_hac<71a;E{`jq?BShbKHJ8Xj3uWjFJ7-}Ki{KBhw5l7Oxu6uXqDxLImsu1_u znLX`S-{VbhjN;9d|ET&ln@w|HdN)bamNSK8-F>B)#;a1c;br0Rvv!zeg|}~B@NzcW z=5ISz@4b8MU)zC)>BZZ$ioRLtJ##AE*>hye4A-xz{h3##Y_`of_md^__mo>_beGvO zWIA27^jWJ@azopC>HB3pAh+=Dr(W z-6#vz{jwnR_IbZmOY^ViS$&^=wVZdC?IrhnZYCi)9-(^=$6hdbmLQ(8O8NBtTQ8m$ zEh<|3+E8VCLU?SyAt(2}e|_g(*z?_Z7aMzM;gX$JjV}{9iV}>rv+7Beu2$P~gki1p z{n@J0Gu`f0G_K9IT<^(LcR^8SPVr+;{bQ!5?@g6GV|8zpqT7jQQM}$9@l)NpgVsDe zC)AeX@n5>a&wRtyXuXRg_PH9mYo z$5fAdQ%gVVR_x?%+48r9OZ(2T;knC{rgRy2@vaarT9m%R`PyYc(y4?Z5xeI|rCGVSw84taM`b=I~k(e)NT z<^SHFL(P5&YH zeILhDMF9>!1;dm@9*r7O=Nobj<091B{`?C08g+O1xjT}{$|@FLY?trewQJh?Y4hIu z9aZvY{TKYN`s14?|HS`&`N*%H`6XoDzooXd)t~Nm>ikzeb$hw|oP+E^uP*O!Sw6?o z_V+WFY5a5SzTVQkGirm#mlP#D;?I1}<^U zo^FfvQHugTRNRbvP_g*Ko8LM9(!J-uZRjhy^(M|N>o?!0>L5nr1Wk*CrA=;3TgtmH z7JgTj={2;Qbx0vqIM8axQAvK6tCqjJ`fnfnvQhq_F#D6NP)knx>yE-FXP>{_GkwbL zsaxhxFxeeZ@h2-hQ~OPCbJB?&9@5s;iJ|%q?giyVf=tT}cQ#&*V!Eu~=r1;nyLESx zh0anj@s>54_cm|#6rS_!oKsW6`lVl1*WQ2EZT5?ouT8aSRqlpeZ{`RqDko0z6ZPuo zH1y(5ubsT%M9H>=b=Uo${Qk0J%GEC)YxEB*HJ9$5A1E`G;j7=QWlA>~6Mj3cihQ$* zL(|u9$_h7mn*+1GLoT-5{r}5ydav|DEmbELE5;QYLkk118D#Z*7V6DyG85dv!ThO! z|EOe%xzJvP(~~PLGT%#A_N=Z5cy%J@NYj>H>6P#A#kH=gP9j@7_-HPsy?TeUX`)=93N>P+9 zJy6cg%lFOa+|sr z&7u7;Q`OAuRG!uR*t7DWCVo z0UajkT3g1ZOY_tU9+rmL@Otq4s8Ws!KAd>2tz&~+3s2?xrr0^xgx}|1aCdl|`|JFK zpvA4h4d)uI@{@(G^`G;zv;X-nWVY%OjYkdqUN3iaFfg)Ol#3g9{d{onHe)_IjJz=T8>1FQ1?9rZd@XN&~CTqeYjD95T8h|FNE# zF1E&Bx#+ujO4GKB+8r`^m-u*n6w{V?S6Kz#u{yqFM~1pWN>#Gds!mRs1#MhRGqT<- zQGNe7UBLSw_ne1{e%tjJ*nJYD9nZ@C`n1xE zT-RZ%mvz;#4DQGU2ScP>r@LA(L@>9wRI+g7JBX=24^9c>vao7D&9Hs5LD2S&oDN=o zkJ{}U0-ic#Z7?#J%(OrJC?n%RT?YMwoC+r$c0_I|-6=>Fo^t$qtRZ2aUSCHA^qyv`Q*$~fZgPKIy%8m%km zI7=^AjXEH6ukt~!ub7+S8}}VeSv;F~f|#qAH|5yW*39wGQ)-&@g?tg9ogjOvYMOk`1~vF;DWA4bEo#7`P^_Nd&BcGE4QbD z7B_frI5|X!clL3IuSyFR;Fx?UNKs&^>g94@RlX!;slYgf;x~oo=Y_G<%Ix)awUyP3 zHFJH>uqb%u%nV*r=8hdx{Hqr)W|=2YSIVn&BdhyjOUydZJrUgP4jYKmZHksQA?N-nG>EqcwzhF&b+(I^0l`Q{nZsT zZn)pOA)2vy;)kihvf+Z9HTRShnxgxgLKm}0soz`t)qJm;wxjger6`RGY zEzBjZeF7?{~uIMvsqcKu;gjZnx)Kvw|QiPjTDbv zow?+3^ve>zV}>WKQkGrd)Utb4_rCD$Y8i)x>MAy`t|TUL?b+4waQgH5j-BT>$r>!s zSY)f#V6f#%q4Vu3rc}Sg<*J=;{+mdz`Qj8-BeLP(7s(?DiECW8*ow~d6X`em9USAw z%ww4SyE}W%TjsRhHOsH<)pj=9a%-odq&q5jX$Pcz{yQe{Y5 z7VZ{WcAzEQDL`zxhpLWz&QnHb&yLO47DQ>?b1GAmTdY!IF6H!1?CRP-oOZEa^50F+ zVBuS6BgCrwS>T|G$X=bIwT6>)i(-9$36y@UcwQs)QPOL}8pZp{&lMd^?g_PRc()-l zK=8Fo!R9MDw{}ZA-k2!b@N%t+(od#hqZM0f-RGURw|n_fI8CQ_&PSaUXPY?pmVPVu ziBFqZcuv^p#|ln$)`{GWOK%jIZtUd{$?0^Ci)2+?R8cLM(KUrvk9pM=!A7w?0Tm|_ zd5XSW-)vS=(z+t!>5&P!E~ietv5YM5NXRt!Tz+lt@tAbY2Mbh|KDK&kd+=Z2*9RLE zERyFwnQ(jU?E4>g z)*j!qL+;dJ*9S*eRM^x#KegzDWv}Nh-Ua>B?lwrd>^J&zQhJTf-6`!2H_k=~)UREh za6_VjcebPgb7FeSgrwB431{yHJS>db+#r>=^ws4@x4-HnJ8Lc5^iW3df!^06jl~B|2-k)_RU+m;j>>)T^qPUc+HeT?rUc*%wAJ&>gxD2B1`s#sA5r= z?~+G_aZ!96ecFTS$3z+Oi#gYR46iPI-7rf#=+*1~__iI{j}dMAT=@RvyW|Ci-Y za$kRX@wdoV-HYxFlND-ne{8S)v8Vr@v#yCpd8J~n-K+Qa4!_zNrPN^b=@4sV^8NPv z?X}SXX7c6Vf4`_s<(jzf@Novm!|#7TuB@+FZ_gwc_E<~I{dLjz+sZ|Py?K5gWmB(J z*6(?7F&Cq z|EVisl&oXGzoMB-`*m7jB)2(tr$k(0NR^C;^cII8UjgA_sklJ%8WGXyJOUdlp1ht~ zuKnyv!XEvv5*?Cv7Wf$YoI2wf#Go9vt=@TqfMJRK-<0;zd<{#E_)#aRc^}crYk5{U*mdr`c zn6xu+b*%HITaO-ONVK?W=ad=OY;j%oCMDEC;_AD{wq|v|1Wrte{p?-V*y5XgV(GCb zdci!;T*Y>OQMj=&YqPbcYQj`K%@dm4TVK6CJUw2=8#_N~YG1j5hGk@DJJ+@yE- z$()|Hqd#Za=ix4W$gJIG`?O`Z7*|88?ZpWjd!%mtt(Ca-#;)~bQ@ioh-RvJUmL8b4uYKoYA@A7! zfW3lVPe;Fft=6-8H~PpfW#0BeP0Kv^*o@VM zVNIp7r_RS(MM?Y*B<4( zYuEIGeDwmOeH?-gZ-2FUhpS}I*~&|6Ojq#Mn8s}V(RpoA{_Q2Dd!86AY@Bp_s}LV! zh4GWZ?8`0rf18rs#MiosWW|0wc>m*$jqJx(`Es6%eZGF`676v2gjLs^9)_}u+y339 zwX|^EE|CSoZw}>&Pr8(PboY6a^z!5J7ay#6At>hSThHozr4H)s1VDpWfcKc}v;hj1#gl+X@rX=4>jQv%I4)ec|($xo>wBp6N?VJH@3h zv+7pwUi%ckxViHUrk-3{5|d#n+C5uGcICkWx8L`8B8A?b37sY1ZNE8qLwxM9QE}s@1!f~_qC2@c21wgHl=4F`!^By@+}wcu+G)*;fYS;igjto z{_yD8VsCNAKg(_&dUh(oyy{iw!$ak*QB`ewDntauzOXEfR^XXyx_9GZ6K)IVeed#G z%u-W-eyfOHG<}xmb%wm--MPkl?wx;Nuxi?RDb?Nl+|Cbkt$(zNcDtl!xqrFXU*;yh zG*C&gR`Kt$+y1Rh=VrA(HG9PzBD`C|;%+?0#no~Zd$o$UZJSqA-S+ml{83|fy+A(3 zSlgM_UjnbqZ?9_JVshf8dEV}9l|642`EDDBPU=c%|5TkQ8-@9*i@46!`n>OaodF{7rNtV~GG}8#S zKYP`ewN+R?t-pFheqwa{g%?-$O_^u*EA?7?;;G4vj7M#Y6gDPoH@I>+KKJSUY~}}R z{$4(>d8#Mk(CkM%GCXbP1@flwZ=Kxv!~E9K*aiPqi6+iz-(i2RcIxhVRspwffAdtn zvwG&&O5dLHDG{+rKAC&AJQbO#`E1wMXzj)2-env3q<8&!_gJVc!K}fTUvcUs{*MBj zbK_RGMJJ2zotCw2$GnVerafMV7d^bSt1W=_$0iele(^csM>A$g-rcbye)qQn>*P*K zSiTXHodQnsnp!7*o;rjaBOCK#3TX4_WxO)0~?_;Tj^-c`>nnAp^Y7xm;t=u4M8F&1= z@X7-3{n>Y~bj({9ox`TT(>^kfCHe5x4$}|v?^i2ialLwLBCz~Xb7yl#EpBBp` zX!~|OF=M!OHf+|nz03Ekx_d>br*py`le*nz8+{}_7hmN`eIKiHRCQV?Smh-juCEQ;IbZbdfn}j_7Qr@ZQa4U>y*K0BuhHh?@#|Ss#Ot?m zEN2q7nF%v7ZWc<`5IU&1O7xRox7$DclAM^}vl|!8edfRIjNi}wr5|>md?Un^quMj! zT)e5yiQOfezq_Abu(GtyaXE|CStXs^aE*EaWxx7p_0wialeBKVKNr1vV)>RImdU@4 z@ufMPm@)gzp-nTRWe#__2nvTyIO4ngv~9ZC&nHEvYkKy3PwL7pR>*yj%oOoBe&-Hf zW4_t_UWG@VtN&-$ezW)qmhm>wC>nUY&BDR}wtv^i5Ol6CNEESu*T@jGrADkI*n71bB+OLQ2b~JCFxjD~bMgF~2 zi@zV6D^gVC#j8|z{br(6`L#pmrpnpL{!H0ha#m%NNadd1eka3qUq7TSd=UJj;fk=% zSN{kv%d;XrMIStG_%AWJP?KL$WpwU@sFS_i*CSg})Qnu2l&`8x6+AIHHtCdKM1qL$ zMDrvO;murj76;QMo*&}Rx^pm|ySiDw>!d{5(GMK;X2*EeCwgcz9+}r`&3KyoX?ySz zcj<*oB>NK0`O=EbYmBYTJ(*|MGF;wSI*h_TdC!V(BuDzz z&)k>0b5rKe*Xo4Rewv1w502HlS;)O@Z7waV5jv2-d_Qq=s1tX^Elte_H_m+6!eiH- z%aOQ5Do$kHb?&qni8Ma;B4Z1UIBJ~f`Psb~`U>3MkJ5#GpLqg(^)b!#80ybeE6 z=KnZH)%3$Ik9(6hRXMBf;i^j1m|1!;ydo=a(-}dvIa8Nk-Y`KxYUfsAg_@?~P2My3 znwo;#R_r!gw1$J5W!IX|UyrI!Vb7eo`P{_m#>!WOicW~dFEO9GVDZy#k289Kn;(0g zpCnT0%c|rhDD(dV+cXx*ZGO-5o7~immI_DSYgnR{ZyQ%PbR$)D6BUs&!tss8fiY}fc7x4s-m59rvp$!_)R_=u@10v*$2nXBieip6s2oSGq@ z$97pmWxAuu0m}n(KA&M)_3k0Z9~S!s9cLyxuQ>LgaHedkX;5H_X|dt!&Y&WF#*&N& zXLoZfXl(VppvOAzNQ9R8*VX*pRTEzF@9I_()^*_8eauxvJfXSeczfu9LUXwqtrbrn z&;011xuR&dfk@ztiRs5~EDgLG>Ns)2;*3p=t;T{!?pFKzq{fTaNwT(2eqQu)u}t_u zwdjH)lcM%%@wwZs{h?fG*rl~dbYAMzH_V;i71lm<(RlqS$e-izj@dgVGik6fwl6-J z*3`IV?v=+cs#-Mn&s<_A#1g@JgO|T?9oGlH57AAp?W{axK4+JGl4_D*JyY)TV0F~O zgbx}^QtVP+`ZYbM5SXKEwes(t&5QaYI?_~%Pe1z?!Q>=%YF+ncmVXs5J00IKb{zA2 zD^e`H}#M26tbz{yTriEBybY z-mML5Hs9FisO6}AYU8?~o3R_)wGL#>UXW4uBgN&=+Q5)0ubnt06fBQkoAmg<>8h51 z-sgKw{8&3#r`RMO`LIDk?uLFs(Sb)PWv{PAZ|BYOYFYeI!b!5DDC);1VX1ot>t;6J z|EBQpR-<%4NK2KQjESql7Li5$I?uG%&$=AEgl)o7;ob|!uByt`1iraAXQ|_=d!p^` z%OY-P2;Q>QKUw+5L`$KYRbTvwNT&GFePQa(8r8j<8K)e`{N7iQm?;#!$ya&t*Vp~K zl;*q5EOFuBd!1l<>tp)+=_{0SS1>n9f0%l7cRyP|qM}IXp5D|?v)6x2@7UM)B;&p0 zWJ{NaQCUW-dCwax*zUBgW{QT^sdbSxns=A%`TtjC<*XTBw2h`^CulBkc^Uge`>dwS zai1pL9~C<}g%AEsOm)Am@L=_!h6x3y-p@}6VSL9rb$>Ir$I&T~4n~vqUpV_^m0*0& zi+v6Szy4G--QPI*aS?Bw_gOXGl5;;zgJ;&Py0+fKs?tVr-eMjlcNUImZ;uO_w6INj z82LRhahm*cAwTm4HU3pn()HI4^v@Smt>D=jy+)!XJV@Hfvp>T(#k)w*w03QMn8+UK ztO@4bS39HL=U)Ax)ub-C!DC~I{w3X9<33%3_c|#Nf6l31-NAmvL!eyn$^9F8l6!kx z?lQBf@wA@f``&I8)vL#-#(CGvZL^i<_6ZZU`;;BF?fieP;^}rRrrOVaHrwii&aL5a zJJ@5(@4sU8@jK4-?RPnz{p)zryrpXE4AH|s6{fK*zNItss+5il6JOcYi3UsBwWT<8 z4T?2Z-i|t9#C++*PSqP}GuGAVc9p8^={2>Q*t|ESX133pDU92*axA2To;e<@eSGrS z4BJ#QRdI%ScXm}DS-QjS{EG){lP)s8|7m=V(M0FhME~p$LUXgtq%NON5O_Uv--2V0 zt{r^#`t0eoJzpDScT8P-LFb8*$)4tV{`vWN_wL2)|9kY?*OxaJpZ%J@y{7oD@t^Bw zcgr7~e_KBP|Aw8V)xW>ad&(-H+VSe4vB1V7j}9>%Y;#Gt`B290@|5_=e`n9mnjmpH zZKmqUoD&ny1hY!4-oNtA`lvhIw>stGIy@F1{$QMZQ{Cwh`Cds(4ycv%c9Tk>WsfE7K}SnT^ge{$_1Ud^uu^<=nVN!A0t@W zuB~nIUaPM6bkh7E)$=c`{nlr(r+s^2q#2s&JICDOxIau9l&*#J z7uQd?u&l&$ehSZIVU_MMM{E7lY>r#Sj^7enXQ1?P;e}hgmLAtu{reMq#HD9V3MK?LY>U?2(=Pgrku7?Tyx1cq?MDw{VVfft+b%5<_j?L%9q=$|;JPxc@C&!A=(z^oS)7?oR@@wa9(>{O zo|VfX_Dbk|t#s4tpJw|Q%0ni*d!$cUyJu;#&co{W&U2ha_Vz5w@r$v}zFx+@DrIBM zFR|Ux(`DY&-zZ+Y?@597I=0#K^erW%cCem)-{!_8ZK|*Q!YTd6217w-WBrMp?|c24 z6;?0&tZfsS>0s7={^G2P{>EFq3g6jeUX?#++iAWr`+3a9eMWNYAN*Ij*7B`6F4?(F z=~|5HHYb-9Up=3TGqloYi})U$dv?E4mSII(vKVJ=NssNR`K38|@vPtNJ4;1Vs@`w? zrFCM8yJ6*dtrZ7;y;yp6_a3f8OuwsEZx3|zdTy@F9;KrZ8?^NyUs-FVy8buS@MBkt zr}hQ?7WJ|Vzj5hW%B$p8H_vYnF)LiF-V%J`g0u7ABXT~BnMvZV2Vz^MBm`zz>X3;$*YWUypbC^!~j`xK(aam-odrg}Mu;X(_&!nvy5l zHcjQ!qx_j0{TiRU{`w{MeEYifeS5lp7VZ9JG9 ztF7Ldnf+BKu4Uu?#QPd95@(hjTHNCCdC#H63;)imzA78MZpxR?_(d@@jOQ=8Zj%}^ z=j|7UrwZ0eTLfI9uV|?`)o<%G{IXp+t-Qtb@090-xkj^6TMMpq@7?S)!$4ruS)u2X z!ngNkPBfjXcsXzJu|S>b4O3-~-PybS=f%e+maFQ|eTtbole63V`mzOq%V)eV`yX>7 zSjMPi+O@3Tx;2)PNB($4DoibP6x9#3zpVP$_O&C|&7?P4I-;s)BByo5uY33?-0RpU zN8hJ&!ZU-Dmaa@tWZlT#{B1S2ndQ9`$!9l}x4yCPOX@AUT9>KxSo`M23m>=MQxlAu zTw8CZDRC`GQ}WGr#_Ln-UZ)+>*PYeN9n5pEw*9!q+b!?Jg67>@W3e)CGDBC_cSTFD z@F>l@o==^9eG5%o<$ZkRmuF9H_|G4_y*VzpZu?$;z3S3{=v{wXg1_!y zU&8ZuiTE->bALPk!x9A(Hhf&Rd&BL>;z_S`?&+@V;+njBPu;?^hLaS(Mfh)4p6euF zwny{t@xA|UxV0ykMcjS%Dd5=bq_0H>KXp%)&NbwE*k8&kxidHPbI`{Zu~$#dznIIo zG2!l10h3Oj?@H$vyo#N zxBU6~U49u}(-e=z{bsO#_dWB)tgoySyCpR&`VUt%B{TQI}&pGLV0jwShB%sFXu%^JeIvQImKG?Z1%P5d&+7j8dP07-d?-F zM<*xp$KFHp^3>HVdsnVJ-!%Q>mD4S3(cBs_i^>z1Dl*2*DL>=p&eL%2^#sRDa~}52 zZjiXdz5HwIWvgF_lDxKalNk`254S6EgmX z#GjN-Qd4t!^y2Q%X@`X3uUHL#H%(>5GhY?=A_ z_~c*jUM97kn(}kEeOYGx-M>eIcPVmTxGya|q2~01B^p1PW*LjJ&1J}$!P?KIXjdO$ z*Ep%+m#4|Q>+g2%j}s7R%fI@t{`$q+rC%2G38~ctx#yQGzq@kr|3hyxnEk%pi<$H3 zn2~VQ>&>f`=DoT7|J16z&$tU*rd8`-&@#$d>bIg)R;Q`JVofg>z2_Yfqo0yx_aH=i%LuXle-u80IhgbU9iyq!oZ4?Rrst~>2caMq6?X3*f+b3)j^v(zh%NF#`2>JSV zU9i#a*{N^UUj4S+wdIId;M&Itc}(4 z4TK_netP;|3*A#ET3)&&((~2CIhEB9ne&%=ZoQ>HyLGZl-b~ZFrv{g|MqZC;i;bCG zy7c4pnLoEiW-T=+y0UJ5%>v%{ijNuMww$#{s92I?FSYV-q4(vBS)SkjFErdg>+asq zJ2xqQn6_o6!Rd{9k&o}3yrrU^(amXiYUjJF@9(PWs-52Cw&T9TyX^L!hu3HSXP)Dy z7MPlsQe0A$nwX0iLIDkzfQC>^j7{K|7#SI2S;%Av8iFA>uyQmea;3iCUE0}LiP1c2QIBkJ7REJXuM{7H#D-cuCkQ-|MT@8?^-m)@R>pIf^vynXRpCy{G!mN(DX6Bzb3cb7!cl^qpdC7#d7<#+-^+(D)D)Lq z%4zK9|8aBXjo=y6MDHE{EB|44ztxHQIsZFvys@0V^;)n&!k3?{GqjE6o9`b#lct$l z=jANI)>F_m&uZH7zEjDX3qM_cwLtCRL2V94bt7d@wxX@Vg)Emgd9iJ-ueH!xv()F# z{yFde@cBnCHr@S2rrwiZ>s$Q!>$le13&k^)9G)h<_8FV_)GEUEWdq_PTE--)tFxCuF4z#$@NxDrTL?M zLBTiX{(t)BPx$=OTc1VE%nwTR>h^0ntyu8mb>!Xkvv~Jp%=&NiS8p-LZ~YEau2~LC z!Y0=BE}b)TO6l)>&)U|De19$pTRcwPJ29+k^1l!!?XCCY&)wedcO`OSS-7Kb;IF@? z|3W4=tBHS-@cpUCs$0SRJE#;JHE@Wd8sTGP+Gq*)pqlysV}~S#NAhOovZ)td4F2h!ME|UQ<|q{o!7{$ zHnWm;U&sDkv@mJdRiea_6{`sk3 z=e_PvyC+YrRr%-_|H^gQw=;F-YpxwwVZ*U^7U$nddTt&5MmN)sX-Z2!w#l^G_N731 zGuvc|`Sa%2mV7(w_k2N}iGb!A8SU1&pRIiK1oSGt-@G|F{r%g0)t|q8dUG;KKIIeY4=?z~+pE2CR_Mb08DUG}8-XrH=Q8CSkKP%Kf*wlzDQxMzkFlFhxEuJl2>;(_4{@;!G zXZoAl*{yX(Go!y})+#zbqT$bs3-<@sUaBGdYcDAQ_&qTp*MVeeX##dU* zzid%S>(TxDyLnQuitDZ?c8op;Z?1X&C!|a9+@!Bl6)u_W-*q&($8XwxzqbODu~C)X0U+zZ`q*Bvr1fOF%L18bM*&a|z$XW7V?a(8A!nq_|ag%77A z%_H4@6-i#+bUXiLqGO_IK!9__O9i;z5{_^Z*<=3M#SEeSW>&rh1*B7DPAqEaPN zQtjmD8_!HODGP4cCinEp^7{fmTh?A>DsUEHSv>99<>Zz?2eqY48;bnaH#mMc__2G* zN-u`LKN20}D=&!qO7C0LdqrjIO(rY1$wjx%$xW_0v}1PFJ?*3=y3Qf?caQNp%;9TP z|K&aBRyg~ny7Wuw`)}{j6n^z}&C|p4+q0(lJ3dwAdU;Lw*Tc%>^~Rw~XI8hY-?YR; ztL&(q)8f8K_colH@|%gdF|ys|klO6)=Ps9N-?)-~RNrl4&5;10R9 zQD%olwyw|1Sm3eR@70-AaREVzk6jLYme#tWxv(|$mA%o9su*uWyXLF|(Xy-Swig`q z`@(F?(mf^bsch!_^Xw~{ZEcsVHO>iIrobD%tgv&%4)Yl~*WNq*Ui08^OX1nn8EmxbHyLAc4}`3LACl^0opC%< zQ`C3k(j}*r&L3J_x^>&ppPaH=kBfK32R(irsuB6-|I@Q8bG+-tf0jH}W&T|fxZ~XM zbY1^S&%jSv(|)m-9)5MFLW*;NOXmBvOD84XT$)j~XuE#dAC1*C91&Zec}V^SeYTi({(2*7MIt zB>v#}n!?;7!2G&(Th+bqx);{=xg3&9ea^Exv~>En6tAtJrs{V?w*`0SY+6`+>3<%3 zk}rRmv-R=q#nata%V}@tl03L8@~rahy_&BkL`SA`riOZlo$j*#=G*Xs@!DK|1M>oh zf77n#%Ff>XCA@9g#8a1AVl{h>{@JxYe^%OFddQ8#)%;1}6~@eeQ#seh?va`$yjnQ_ zYf+HyZC<9Mi~7q=1qxNq|41y)eYr*Kz+%m_1`7JVl~<>(aXDu!u2PXH9vWvC?P$sQ z$?yE!(`i%xJzV2=(8pC)eETx4T|KjB3u|As+HiMm!BW8wQ=fVpExUeyVq6dF-RTo2 z`MFr05!fe@b-Yb^=IM!x&EA}l57T4&ZxI>BHlb)%H-oe&OW4W_B9XnfcWpKcJ=VB= z_1&xrzx>qa@42GA`rcP$mU{a#z00a?4t+ZHlwHxyJ5nuPN@vp_zwMqoOW=Lk#^CD7 zZSrz)-4KO zc@|yIdbL1jipRFcUN>~|jDE))6q-C|@h9fIv6(pw%*S^>2ti#H!r)bYxqQu)kb&Xj9V4E_WYEM65be|t6i*=Z@aB%5tr0f z_QShA7n{GC@hJUz!)k*Y$9FE<_U(D1se6FH#SIN%^FQ5rlD3yq+Ab}$qPKFw;`fEs zoV7jNCw5yNa?j3AKBckrl^X-=rH5tDw%<6;_0oG|(xgK>RD4Zc9i116zhqlFSC&uY zmYMFcOUDyi*Umn%y64ubx{%dxcrUz|5_$hPgV_SZ>|^?tBDu#Ek4>AtMQl%anB|2> zOOy`pn&@0IJ0M#&TEnkA&i?$}4V^dQdg?y)ocP{xqUWHU&*nvDW%sVD7+y8hd>|q< zdDD)!CX3l@b3f0R!u}v^%UPT351IxOw;VLp(sXt=OIK$4t^PpeLD-aJzeAQreq}Qq zV#J~R0;`}|C#Hm^UzT=mwD}4$8B@IeRT{rz7lzC z<;0l&OI%S;IJ&Pcx$GH}dvDI!wmY)PE-P$y>}r0!p}*5`(dm~O-xN(semk5MNHbY~ z;7;i7&x`sNooKaR!s*GCDi=*ia zM-7d28~u)cF`Rm*dYXzRflYccox+SkIp~6*p zAx|<#qu6%W%MS#(O9Gxb9{qHxxBQgKJmc>N|2$1#ja4|C>rrPC`SEDuJ=qNx7OpQ~ z=#o#f`FN%)OT~K0<7;Jy|HWS9`R~&$SofmOh(o5T_)gHy9MkBfb8e?8M@(ANps^@A z@BItW?z1wHk(aK!&wAd2@?-q@Yp)_(ED>?B5#_iddtlx=p(epKD8;DsA1jjaBlImJ5~wv)_;=w z{$c6tk8{#iUo>!uxaulBo2$t+Rc7i#4)FsC9L)C9PF3)VGi~7VylCc`Dzzlhx2^j0 z?(goK`DIi&)6SiZyI6Hf@Z8>am!>8*DXjeG_Che@jfszxI>)7ejng)Fq(E&JB9|NN94eQKU=EFWj&@9=Qmz;XM>$=v2!i~3skZj9!5bxh*JoHdeL zvhAm_HqGnV<~U)Fh*hTS`T&t>+54w?T$(KH>a;dfufOHgms1+%yB@zf_O4>?jYVaR z<^1mrpKkXt+g34s$*7&bu-#0 zzDkbdo9^K;C!Kj|)(Y#>9~owSGRxCmfBG|{^vqYxUwTb{{J!bVz^5;Ac~RoUbc>rI zb0Z@7!nR)enI=5#T~6ND_toE`R|m3(%t zYaEi;CAgzkTzP%Pe`kl_e!I;Vcn&2PmWX03zjgrAIN=wdAe_b z)^b-%LnY7umO^W;ggi*Ej54sW6=Mr%nB%x4M`m9_Mr(O)U(oNLXO~(Ye-W}$YUiFn zlS_^Jo5B;SuBg5}chS21;HA49rgm0E{S&Mg6kauPbp4|7Xo6^C599LJ^KL$r{PXV4 zhh)8=QeTaWvJX8%Yb_enoYD&3Jxsi+QNCc>q4kw_B^X>IeCwt;37?ytcGg3(sWf|c z6i3{Zr_0MDBMn*CZ{VL9+E%_O25xk-7U+~Kb`-DYO3pl+xG%YM97}#w(Q}AC%rW z_e%>pxrDYKR$UpZ^$+FxLjU}(`O9{}$ne0*<9~nkE-kZt{JFMDvGYU!xqsXy z+jdRBGHwMLjRKEbnOT~_N3)EuEC@0Jjc^ejw~CGImvJw;_xzyUFLskJkMbIVPyPPT z+&J~f-KSNl-bRel27et2H6}eUR8d_Q_WQN$MEBH`u$1!i8E$P18zbgUO^=C}ImvIm z@x)XYg_#_?}^?qLkkG#kJZts#)Gw(i@ z*GtKie=3yPW4->a(%p9-Z+HK{x%%+ZSkMTTE9iKp|FwU_-?+S5C;nb6alzu_;UDf! zZ};9fLt)FE|34RqtF{{bwtq1BgWbFRmN8D*f;Bhn^K|96ZND$8xAl^@!7?93mi_U3 z)9)QV)qD57PhiLufAPwGp|}FpPV;xvTar_34*9?@aN2`fzDLW&Xc{fbJf>SAV5rW_`c4 z>M!>U{x`q=?fUamFil{MNZ$WdroT9sW%>3b{{N&Prah&s?7!H)35kYY4;RNy`Kn>`IYs3cXxY#*?qs4tKw^yYD+$u7SaFR~}87Qo+=EukOfZ0k_>( zCbs{)?NRrSG5(PIp+hZSlY07>@$~V=AH1~3@S^t{4_Av4*@w!TB^1P6pMA`$tt#6w zh1g&w7M3(Cli_e??;1t#IP};!jc|z@1hVAydQT#K$U8-a2OyAP<(P#P26FWD_{GT#0 z>aAvQR8K4K)Tx`^wKnALTqILDGkn9PACfHWDM`*Vgyt|;Go}30sGp#3v2o8gjng@E zj|n;+KY2sY&ARV(o!x@cz?Mrt4_#mJ<9ofehC#7QqDl4w<;{^1N*h)?CEO|zX(&?k znEWhJS3)^4fuCLKEbF(N*Oh^XD~dby1>V)aNVy`+iBAv~JB# zjP$+qZSO>G!LOw=4KA$qxxYbOaLo~?hu@cat&%ztTp-n1{@-}{qmvBh`8K38a(+zp zKc9MRx=>2FfRX>6$4a@Id}^+-C{FBj2{IGPHP^9 zdg!I+V-4+ICE@w&HYxIm3FKNnFHBkG7W1Anc&>r^B@L@d^XnaiBNs-^I$5>$;JcoQ zTXodttmWm&{L&J3JL|;GxWL4qmrT)K?Dd?7jSj5%t~YO%VQ6vZD%n|`Q&-%+nKp|{ z>0P|JS=6wn9O$mKvC4JLT&Ba#a%B@OPpJlR z)fL{l^#0=<2eBgx=|U1|tRg9$7JIi|xybOjVXJw`^tIQIHCzzb!5h&O=pz#{=>UJC zEkg#^q(}*IO&tvhPpvL#iv)#aw@pj8vro0z*%*6RVEzJG0rx4}{1|@NzvR3iabk6N zHnUhCgXN+M&AqY4X}r6OwpJM3T<)NBk!$B7XK7p3E)Ic%PMmVzr8)fF>}UEYOis+z zS;E6F;Whg{gS1IBb4G;z3Ffuerz>|mpFR_PPW0ZX*BT-`C0BzB6tm~84rpI^V`}if z;D(;q^x5CVcy4j_c_}GJ2VXH1?$NkyAP$}x+%2%DDcV*X=wYtD)&EqVKAYk);(?qr2K zS=|oTKkSuXxu-qu#>M5Ob}fGQ0)shR%nSC;<~VBh{dJkdUWITs)y*qED~0G~EV17d z<~F}nN&nit?p2e%Af^YObf^%I>}kS**@2o5l2m?ZKma3(}&69&U?rvoW}%dFl!Ug}bY~_qhemJO4^LqKl<*)p9$-1@lulEZ)Am zs@|rPP%!0HRmAePb^guMBsf;K?@-ig(DV2glHI&s``uDo3EQwDH%md$vy8##BUf|I zpVK5FJ?Yr=nco7glr*SEW-8s>>7gD}wy3Azyfs_LmU$K&+y2ek?s9Uj^GvCnTbT|u z1r1VHs&5Ii-nBm9y=L1NhMO%VyH9WZ$#lx`eSBuyjqNuJoKwrYI64~Mi5|Pw^xp4h(Bk@oH|5O2 zxxdM#zY%_N-8q=|!iA{6(lhm0`ya8n9z3+B(_PqMzWeKIn#Jqoe0lG>w;ui?cXp5A z$;FzXPKkW`%_h&6oV-ZV^2t-5l4xe#2MsGvZe%Q6!D{Z_aOB3kI!l(V9URSeE8cfC zpYl6sqvw|_qW+0v|M!?oRYqN*$E_M_VtLo|Yo06on6PmnOHii99?v!A?J9~s>=)K` z>pOhbyW141c_E8wj{4oRT2+C*%j)Xa^!l+xz7=?0b+Je&UCr5P;prt-FWu}#qjLVA z(cSrO?={R?D%*}5-jWi$SAGU?2Rf6LdU+D>||)3Hm->ZEp@ z`b6I3$_C@>n#p17`Fg7UnWaj#b%t}L&AnnFpDrf5EWtZj;Ov@f+jEp;R6n@geRO); z=h_e4hsBPZ+L^b5nK6~&_2CzNDHl`w75^M6)bin}*E9OSv^#`B`KpiIHHT}0iN!pn zOE#?FV7Aq6IIU-OP4{1>MWfE`?R&fyd93mOTh;6Kr>DC|Gwwj6v=JZMMy44nC*JZ^ z-K084lI5k@mSeLVj9>3&(Y)1ltd8yVgU4QL4-`y|d#`iJm)~i@bA?Znrq2?%Ak^`= zM&kMQhVxhcbnN4gO;OV@&5xSFZlX5^TCzmz^7hv9cy_f z?31f?db*=RURCGX9lpS9hsO!Oqw3FhNcrSUZrf?>u~)Am+q3ILb3#(eM~&$d4tU;P zZRjTND^zvy?s;`58J8~tR|EHa{qSX%%Zfeoj;WsZzLu1=ZrSoVHZK=$V!0@E_v4FC zUN5#!d2?0XG(zh|z@FTE^%9@itNI7xmnz&QO`nlzx8vr@s0S7oy3(!o z=BK^hbn(o}iy<>+v@5x6O^jzdu$wE#?Zj1&EzdmO7_Pl{_fp8VEJpA5Tb#V-**c4U z?J{}mVP&DH`g{^k^44kZU&=>5ZEn5x=l!1ShMFUD8hd#A1%;;+vZsj3{taZeD729K z9$g&ecT}(8`^u+klPXd;*|jS6SV^_C^lqE+xzbNS=)BywS8F~z@4T_xDLqxj`KD#x zo$e=(*5A^&(y`pA-~Cn3wtTt%CDqmJKlMY4{!QCwFBI-=Hf7ck^{VEDPc%#RebN%= z@JSU8W)JsszrDBRrK8EO154(0EfRSaxZUH_7Pp8ko8MV#3b!4+m^XcDWXZ}cxALZB zeiS{pqT6VXQdY*+j);ky&vk{bIA&h0>At3^w>;P2!0CyH6VDt{pMG*i>~zbsE0T?q zcUa^q>&}`uHsS9O5uUbL z(@^qzY}04N~&5@O&0SUZwOWKU8i`I+w=K>A{EW% zirNDryz-%IIWLrMiJQ={QLXbWv8sl1o1a?YoD>``}IKni*<80)E_H5vMX@j zbT7u+Mf@|@v`tR5o78mfncH^*Ggje8W{+1}>qh%)e`^$8lw}uPzy9Ej){NO_H!4Q{ zz4U1D(;F>wez#|KrSUwKW{JGV#thC{4%)KKONeyZzPyFQfnX%!+1JT6bRP%QX zA(C5X9Qm-QM&sMTM^dvDO0+z=O@1y;wXZp!aUxh!Sa$wZ7dN9Pe~m-W$+ITaZ%Xeo zEfiRxKL46Kx7+q@(OYZZMA(Kexb(lfp`u9R%?gH?`Db|7Uk$7^)SS2Tdb7gXqZ?CJ z?L5S~=4G$v_4GNplV*C(nYYqcJ2?KU@4FKcdsmhg&Rf#&V==Gl6qmabyQ!Q?n-k-g z=Ji2u%CCx^E0qoQ+HVy;L*kZU`nHWTw~FrcIF)?e)HbzXMZWH-StlOtdT=yi$wl4M z=fkhO7v0s>VgGslr#RN-kta2*++Ti^sj8X2XL9yy&z&i}j1t?Y)|vd8njLDE@wV(i z(lim)q??s?SLgkBWTu*EJm2|urO*AB#rtpU^^-iF{_2|NpWsCccdWHJoLLZ5&vT8# zu{`&Sn#}Wm3DVE~vn_+-+?^&}mAaj>b3xZnNnPbPTrZyT4xO(sJFu$1~`E|p|ziy(4`}|2= zvh(|0Z=A46mRKyW^+enJUC^o?OQF9FGwxlGoS=2!PlEe@)78E!zpTvEXukG-m-CTL z3h90^2Fsn;!gaGVn0{{w=r;RS)9-$gW%7)SJJNG_tp(ej*qk?QkGl9~-o6%VRYtC} zRdVNe4oqIA`u3>R?gW$mD``pZm=5?J*}A7$jhjWK{969;sdu-Z$c*>qzH-5ib}kt2K93C!e$G`W#)v!tN-bm{G!a;CB35FHOaQX|0z86#8K>+-?hnI=cZi&{<9YhT2y@N!EK_g%M8#jRhrM0ZZT?7QP1_o<3A zuck%{M=lgux7u!!gT{jFs{BcxUfxrgFimswTRx|Shh1JD^|WGjOq_Fc+MI3MPy9dR zxo63%zmmbGx2Ea6t6ZgaSJG|yFRhJn0n6U4^t-tF*C+KQOBF&_EnlxcpRut@rNGZ} znGG|umh6kliQgjpf~K-gJQ^U~bk6S3TK3vUy8fD1*9Awa-;r%`=hmC{u}$Go#KkKw zmF~^TtUrHJ=()}kk^1|0T_b!OQ`YZNF}J+3)c@Uv7tR6BUsN*Ryoi0@=*>1WKxD}k zl|LC~-+bO*Pw>8_om;Zvk%v|Ox{z~avHOCT9Gdf1HO*s|@{UZg!(kH>{1t;-oBy$# z`7>c!-<67&A@@3ZGQPFU-R7|R)xS?}A`X@}0wvgd_AK6-Kf|f5V2<+&7skA%^|rN} zk2`JAQsQ7;wr|Vq>^Y}?*sky^IKT0m3j3DGxiv>_-502?_q=gU%6G#8W4^qAl50x5 zoBy1aId^l}0wso8gHld zEN?izRN7}a&UxDQtpCbSl@A*3tu0#wuT0tQXZKB&nml3lt4EWwv(h%22+wvnTLGjhL=)@dM01F5aY7`hP0pm?ps-DY??}$ zFYDhrWymSot}lOn!cJCs@0)j0FN#fGy>Go5lRmegCTc%pP*|?#GFzqP%R*v|_xqaO zPc1pUOLI?($B*EuXMemGsC|lOERxIT(hE1q<(6c>CKbG`&DDqZqREq&QtxE?r%C89 zJy-6N{4)Q`JeBLuLvqTC*e5fGYQJ*Ooo=&mSz2DTW?kO&G_##Imog|jwbkcW@~Rx) z^31$T&++AzwZfZEt9bvszhu*5He-8}ogX_*i-P_HmoT--E-y}c{^>>L#-B$t_ndS} z6+A!7%sQ#_mgwv&&T(OfIP>_Q%|nAbUQbBqxONQ;NLH{x}{$Um2ml;C-OYK+O#Vr&3j2m__Qr69lw1#;rqSf z;xuLfku$QEifZO}nKOjh+9T%*q|D>zU-?BMJnG)5gd3NVn_mhSdHY@8aZpa8VAhA+ zMXi7L+vb>acpsm&-%2fAujpuxPQxoEp@LHimdmf4=@xwKy6bpduT$wcA!ZHz6vkQ4 zUaR{}y6kmxf&InubM47a9nTEXHLp0T9aA@K^>ynK`M9&$sb!J)B!?rSf4*mx)bh$| zHj8U*mrnmT%gC{Z;k2Rss}&|6*VNB^u6AX@RPI;2JQ+uq%a@CtTH43DVy1e&~ zQ-u$w-8`S*tg|!jN#2>|3nyr>m?iGoBqcX(^7bX0#5lcwF`FHqJWKRXxkt)zuD42$ zrZan*+!H>#&*F8N?jvjMq~JyN&ZY+?4IR%kKPb6%FYph?6Xkm~uX5$>g}Abfrnp}B z_`5uvNiE~2sr31`HZ>Yc&TvW}2+cZpyRi1&*7XHX1D`c-;Px2_~J#;QS*!`Dw~7++;=JNtL44lQKEl#vO0T7S?7~iD|OdjFV8P* zPW(T2b-$Hs?Y8?{?oBuA|MqF~o5P2`e4l<;t7aE3Pj$%3O*Ow?AD2-(WWBw9|Gz(K z{K>g(%PY3AdR?mTQ8o40{3WAj`NqW`=KYy9$9q9=fZdaq)FC}|7ZWN{qpC{S^YonUh1d6eC7AfZq@#M_P<~H zocpi%Y~24Q{@+eK3qtqTLl=bB7eN<< zI{yMK2)*|D(yhO@UuH%vNKOgfs@whFJ;=hPCa?f^c?SPzqoJ79%|Ctzm|LND(;KV zxVF#DnLYdOXXcP)drC_Rr`_ALG&J#l@vapu99x3xPQKND^{M~%;`%s&^LfG_#b;WH z^DeGayXko9eogTA^EFYz+~qs2y^smKbFU)o`?-IqN=L5ho!dPjb;5c{iJSw^-picu z+Y&H2^ysXAzJFeMHg8qj@0lBQAWTZux6wXC&Nx@D=DzmzO@Ytu_I*nEmhniW<=+2u zd)9aUV*ke7-*)oQ&a|?gg5US~%zT`95PI&1d!v+owIN$c6vy+N~Ug343#Tfbd8 zxt4r7S9sDZB%q`3sEYfooGt&Czq?@_k+x?iZ}F+JkH=4+^cAxf4%Yp)M|HD2+my4b zTypeRsaQ+TI&U;@scC1~QuX!I6IblHpHs9YhGS9R-EvuSgUnfxGNV%s8+I4V35hitoVWgd{@$Md3Ey9zUoSU*@6V@x^Y;E! z{CnSe{@(8Tcl)>hzI^ld_wxDqkLB%~?2V${C~E#z`*Zl};x{SDUfyD2w`S^k9at5`JXDz6rEb5Ovb=ez+KGG8 z9!Vtz>Y34Ew=WjG(3?9^l5sy1SJKCoCo^W8)lbvwP0yZ}Ui?`uQba&|(pJ&i46b`` zb+t)MQMl+jeZf_M){QP||%bZ@poZq@S5v3zIK&eqP}bIG#*#{AFy zj7d5_(^KZ@@b6pEZLiwK5VYjkmigwlB?Ubfs#wZ@lMiE9a`uj_H;k^sJnViNa#Db)*w@eT8wptw4 zl~Fg{6v?2A@fH)a$DpOjYNSb28wzOq$n$q|*er?RCOGEGe9{cKwOAvOQl z%p+3EBUNIq1=oImdHEucteFTha>CE;&5k?49_na=-5K;HZ?llQL>} zZl|UwFOia+5ooV?OJLsHsas+%?z5O=#4vfvTEXKp#0rn4UCjC!WPIht-W6XXx0+@d z=)B&&Ptee%TYIgc_0t)5PP}eC?K*$4m}6nzoRfiPV$7uNzg!NTo*Kw%D&qXtB;;%0 z&rLRZx4!vxoesI`zWc=PmHdykZHYbcUMZz2{jkMs>vIQmcKP)jUi0s6&heDUqkYE9 z`piBYdTaW7-`2eSj=K}jN)&A?6*DkWQed92>YCN+)_}C7vwoLdniROCtugRHz)#ap z-fjDjTngd;=XJo$Cur4LiTn+d`eh$vU#hsJw=SypO02}rfat%LS0_8@Y1%jPDL@!uy)I0KTn=$TfJJn^7lELJLiPlVo@{>eQfs8XtJ8L+`*&E zi`RTmw+YgIKS8{T|5-`7-_MpgGB2*RWh)$QSn|Z*Gluuj;|CSFXTw&XPG1vMy7o@P z-t0Lw465fJzBks<-`hLu`;3)4V|Jf8P_pIdxhnT8JICpjj<@clvIQ((Z1P$+aF*2B z`9j{e4h4UcpXj1g=gD%RON$0$lb$(M{D(JMC9$Bea`!Hi^_}x9<=Qz$$ z(w`R5X8G~cu8*SJZ9H64jaR*{m^1Og-qcRXvg4OpTe)-Rh*hj#{@^X&BFb$n~sl^ZQ?CPdoTozBp=heX?eZ_US2k zrgJ?{?~l0Qzjl&`mR zMk)reEx9b9?kV@#sY7z|XUUqZtZL2U_dH%2`&2GD;^V|L@qp-OZ5;t8d7Y&vU$Dr| ziBkQW$>&$S@ahyb7T(@OX@_1R9_@H359=k)o&u`8OfNP1WtV>2aw1UaV9MmbLTQ2< zGdlB&r>~Xye${Nrv(f_Fj{PSYHw#UAlFa((TdbTxv%wGLZ43Q=s-~a0qWUFo;&%7L zQ3ZAiKV925mxqS&9A8m+VR?~gXi(3?5Z;5A4s|x1US>W2uwRH+-m`yKeuVAu$$j2( zy7;=QoP_+Xk6cxXvu6opoUGnr?zH%8_{6f)3#S-OH;tNm{pwD8xs&YAYBrvE)w%xK z$xNq& zlaBo$$Z_}F-COKw&)-{HJpHq0?^kC3i^pfa%eo!DxTiV=Jih`9&PCG8^p1wX9) zcsSLAHU#`r07Ar{rPKKu69=3Eeo3%#=ameQ&Wngz$d9eZHdX_l3(A?si+A> zG04nIYuw7bU~;kDE0YE&C#z%i*XQdmFn7(BXiK>e;_$laLg2>I9cR}pxFUY;{*i}!#XPM& zV#;sYOt?33d9w5?)?B57H`US~9?MhBnC$t$=4_<<;=cjHEAmu(&96nwiuSv3IO5s% zi=Aa_Q@yzi4Kxyp|E)ZxB_aJjulCHUL>9NaxqmlDRcKm;gtw`Mn7LdpZf#Lao*gOS z+p2T^%&9w8EJ;r{{hYLePx`p&fC|;@C;t zCzicRa$v})<*q(9MR~8&saIiMceCcJ8gMog&HWbnF7-s=?;go-`D>R&@lN`#KI80_ z8Jr@!uh+at?FkcS-?CEU-jUh4%T_0?xPIh7u82{#!`Jz9Ed3uJSsR?sxpwxQ75qWm z=askkbj{@zxw_GlO)H}}SYm}#9q;nXom1ZEdcC`)XPf^<=lJwY;9j-t$y}jJ=63yNejkjU zEbnGMYwHoXp!>z9gqI)BM*ryyo6Ml>yujJsb@kEI$19Fre%evRHz#?msN9pKK@M-V zB|2AYsJ-PgIQ}}}Wu^mzeC&}v0Yjsbz*P(MuP^Fw)?{&sO~<>wt4gA{MI}uz4WG)=uXoJXmr1ym8R|#k0d^WlFR$F1#W0?CDM+H!+31ijVBI8gpkKo!xkp|7=Wd!}Zrz zyA8CgtzU`keEMdhsMh+_2W4F)+c#zUpLkXi=)Eesf5YE|wfgpuX29i#xK=BiKVGX?1XctXVlLB z)}DNiJ{+!WSp3~`Vp#Uq!yb3+Qqv!PpCtU8?cIwTYkPn89+L*mZD3(H?QuMTTCf8*TA85{1d47@A)RBYOg+eN2$daj<^wTMrrrs2e* zUgM&<8Nc+y#P63cyS7E{uynNWh3L=Xum5d2C-bgv|0~J)U7rQ5GxXfB{x-H`2_k9x=w=6swsPu&GhRtt3W+%J3kFVU5o2z{I z$mK|8M?3Z6bp8)B{KQ@tuYLY`jcL`q=QG(J=H0rxC34#-%i3ADau)B-a({}WDtxlPlYp}`{=FgAq&b`&0_d!w9#jWMy|I_Z%Q|*E`zd!SA z{ohZ2y8Ad5mz{a+A(7+!OWVjp!fCaoLgn?dY#YsvWSIQCcjwpELY0Ft(-jjm%@XQ2 zFBXkn{!WzfpuxYO={jeh=Usfur^mQS{a0LD?m7D)2ALy=3vG6uG<*NA;q(X3f3iJG zCr+CE<#^-w%j!Q)%@Y3k-Hm5z$h>ziKKDMl|2SVwQQTAY|Fe@So8$tX97{jze0$cX zKP4G^U$5PN(=n^KB*pxX)+FhlTGQ9r^Ll8XT>YG7LDrAh2aL`8d_KOcW~!R>YgSHC31Z;J7|V)CW1?0> z?v06_EaN`)-t$KJi}|;GFD%^?UvcdW9i+3-29(7INRN&Jhxrzh(BL$q^<2A zmio=7|7we}&C+#y=GjbtAG7J+yCW*)P5);9zqe;s)u*lZ_x|~(^>^3g-S_qV@5k=l zJL$9ikvmo2PnueJ?C%Z+Er{zIyfl+pB^t!5xQY{WLtX z;(yiOc$1DRXEpBm9!gm7`uU6RFCS{C3Aar9eV)H6C`e=Te^Xn|_mBViw<||=KREnv z*S0@v{{8y;aK+SlO_9%d>+EIw?j=7z_O8Bs!sLD{lesqn-h9-w)ly!v^|$_X(La2` z8PM!$~Ycu+~% z5uJRrvVOPDd-gvs3Sz7_$xna#^Q~LPqFokMMQN7~ZkSf7AY7<&Uv|ozrs=cF^ZSpy zJb6j4vvSJC$=aWa-Sus6n0@j!Qo0sv);`6o^SF7olEA}vVxGU!D(~KXyt?_&5tT(dpY~IPO^5@jDU%L z7n&!pvDr6?O>VF>!Tu~9d@;Kz0<8mckKbBd#^H0|FT*|ur&dZYh zZTc-+ky)E3ub6V|+!WIQ7Pd8|Az4LUUVf*n>fU~-x@deu_Z!p85M?KAc{P)lt9MT4 z=6ts+s?ED*VX0i~O^%?Xw;2mUPg|X0Em-qB)#89jA{?xE4~(c@@UNpE}?uU zmZ=`C*3Uh8H9U6lOp|@J`QF01@bvVkW#@iQG80<1K=%2Tbq)Pn3NJZFEHd7dp%i7J z(|(Ylw6?oyA>aJi_}bF1Wy_6^S9M3-3dFlJ6A;4Z269cse3JNPPICA@Jh7f zp5I+xmUEZ4_%L|=jaYkaySAxqKKtngM}|MEjY^MyEm7+=sg3xQI89C>A+%+=cV9|b zgM{e&vn`X~bh%8nd-!5)(T3=(Y{`!J%l%OtHy4J-r9EopiRk}a)W5-0kz;0fui~90 zTOVmW-j;M}mlj*d{V#&8Wm%i%-9GR2dr!@BU-r1f^_+zq3%nnE^PjoWicx>^iZ4&! zS04KsS>I7Mx%d3G@8o6r0D zeLeqoecxrkVe+Q!+pKFmm$jA@MyG1D%-?3U-Hm%)zVXv3u<3C#bH(jrGZC>zovhdaX`o6%m0kVcdP~KlGvF!)*S4Nt@&WPH+*vcM&<+Qi-THbuMqUCT;cxM zg)g(W^{KqHc0(^`OiACh-U$`Om4}24HoP-=Xk4eWWWP^>QlQ7{Yrjt{e;KWj^gzW@ zbbDXq2kAnu_G5jYV&CP>O*z#Sp?JVK?9CEmJpn#HhpW-jU)?XRF1^w`uS0Q4L$$2= zm8jO0QmLsbYz&;Mz3Z+=lq~+UWN~imu7+#;SL7euV7Zt5z|&}J#*$W%meU9P)`)Q( z|C*@&zSv||&DVv0G?H2l^iSHk@J!lfwyPmw?~(qW zVTh$r3`^EFXBo@>HxnA1^)`fR>Seb-xWgcA@#p2r!;j3?^@}o@MeQ)MV`bFaThO&` zJNJ8cvHL2$iG^{dcHd6leEs>CP6mVTulE*0^Y?7-uTVL7tp4=GmK$q!&1%|pt$thM zwI`R0rUw6QWIEe@t3sm7pkc+kPtl=jt~;#ml&h`ETJV1I`i1w)882JP7HM(*le?gy z^Z7{$Ph|HWvr_SM6WAwls%tV%mYeI(#?r!kr`xz=`@DXxx6{~Wi~d}HLZWg_kWiNi z%l}Zf^FJp}jB3>^2>i~eeOthG<mwlQSKg+AA}5xx5WeNobusWqbAKhNV)u z&lUCdgiOA)qGqM}l&wA!o|qkNXj1ZE@?GM4$gM&7gB8bY2BRY{cvv014lgY>zq~^E zsm0a2N(jahttP z>seF7c`x=JtoOgn-gU$5frPc1`RSg7X;&p2<}o{lhE<7n9_ayBR|B}G_(z|9dJBch> z@6omJROzN*{f;S8brDtP*L5#?95LbAVWZ3H&h4q+UKaEy%nPs5iDcU`zbWReCC8S6 z+bl;kr?2q+y3s(h`^IY-$&QFFli&N_h~Im+GtKwLX)cAD9h0{1Iuus*|LFvF)q=v} z1BUF+uUzY06nt*IuGPjbB96ZjmPIWza6ho{vfBE)W>F@a{T9VWd^Wgvu5IFjb9bvZ z>T>0sR$cnfM*FJ9d*0lwZiQ3oODBsJiR4vIH-9aYoUzEOBt+1_%izqbHQT2z{={&3 z>gxR}LRtRKf6U*s1@hT^XBA!S@~G?S%I%ITtPY!51SToVo2{Q(>9|tZVZ{r#bz8bD zch>P0^qo{~;M%p~+!Q$<&&@qs(@t>*<@zr+)_gC0($phLaMko<_gw6w`gd^FtzdX( zdAdhpmD>&*&nccOFHJU?xp}E^s2_LC(}!}qnOwQ#|Nh*Rp3UoH&lu^NK4q!*>-VBc zJXcy6-z<8hbJ1fOP;zR5ZOut`t&M-H-z7bs zG_&#U>l?3DxlX?|dxFjUDOVOdM=V`sEvnOd=&F=<|kvl!(aMUpVK(X_1e+!bPrC z*{OVRoY(r~)E&{2KgCX})~@(kIjj9ZcjA}4({hzM?F-JH-dfjZ>A99^=j+!`npEDr z4Ewc`mwoE0h-anu&PFDlUClYo%JY6!XGo=_w8VM7IiD_nnC!`K<0Rl6+myKU@S0-N zzu8--#hL5ODZ1VLLM*pM{(On6@2dMZ8sBO16rYR`&r!c)&(&4_c;ZwE&8q>iCC4ru znR2UYm6<$O$SUcJvma*$8}Aiy*6hvLu{~buqrf}A-8VLT-%<8per)`VkM|B8+vaWk ztRer9w29E=1QTu78(W_-WCS`!UUA@>R$8%tiu@O)O}<=)H;;s@yrIcB>uR{q)00Q- z|Maa{y?ocwyj1_c8-3pvEBudjBq^#;YxIkq#V*YN4CHG0bnGxO~v zKQ0y7`BX|P#<=Q*O5UjzH(#IH{Ml&I44EiH#VsmqIXhQ2%(&dZ`S?cNiq$K3pJvVe zaPqF$#%X6OSUOp3zQUE6rVlM6&tE)x{>5?5lz+f1ZsINqV!u z=C!0RONvOlRrS0V_0xA7@3&o2Ez*~F(c{vIi)X{rm$cM>jO?2juwzm9&l=;P`K=xz zz0BVj+a8t8*unB@eeb=9lgi!O&#ud`(3nvv^m6Vz;cc73pI1*m&E_HW+UnFx1mn3b<7n9j@GIoyMN!{e_raQM9EW7og_uu-krMg>hKS?an zThIH!O?QhT|L>_$miJRnZ*%KR+OxGQXXy{A+0(l|J^CQ$t0`3NkXcfhlbfb@(TL}t zLEEcaCrd>?ub9;}F_ZUu^qG>&I>z}o>RM#iio5=)vYwr1|5G*3)#4!cwS-TqaAL>+hjZa-Uw)8U%uS)ajQh`RR-Tph}SgSIm_^TJOfBX=7D9oAP{cqu;jMO!OuKauRm<*<03pLTy^f2tRS|a@L zDo4!9r@P$!CtjR+{&vg!WfBWNstdJs`8=rMD_PoDY3XxD{N}kD&X9KzkNU6P7rRs~ zcSA1Z(Rvf-&bhfvS$Csuo@#Q{jk3JIe8sn^2CmhL)2A%tx&7v*M%wwbn3AQo-d}cB znTTY5_u<~LD$Cu*Q_t?s>RZR}ueV$fbhIz&&9RkBxL@{3lsx<@9)5lQ0(}jJC(J@Y z`g0qqmQ3|n6*c9F)q@>6Z)`ZZ_zouHi4lsNuuJbjv5?&$Gv`nz=k!|M0Hk+ENAiGEh$ET0Xc2qhlO+A0X zs9}BZlo|V&9;|rcet>ytgr0`}3$ZeTed+2`4yI{%PRcYcxhrh!T%N<_z9etU^<$y2 z3-4|#NI5s}PPzDBM~+>c$}8(c7WiE$-}~xAr1}j3bGLcN^7nk-?Rt8$?xd0_%r+k% zT*!I-v|Q)YvW&^G!B>2Jc5C~kM^0Xns>!rY+~Q#S`Q}%}iyq&)UDC}j_rvvaPL->l_T-|Z1| zDvo1=>583kmg^qfaewY(wqlLvfv4ZT89sb4YkpmVjYP;SHgnO6mdeP>23s9C7BNcb z7+h4^P_j`u!>_CE;A4fA5pm@YkA40b*Us1b-{OD8ye}_QOh4?@)3NO<@?P@uz2Lke zw&(YbS@~ClY3R(D;{H(bwB!sCn>wS)3EGx#wCpB%^_B#O2J(7d*L`tsZ=Rn;dfsfq z+4`%V7>QKAQ_Z((y(gQm7Hw|(=idbbZ?BNxY5(uZR9{a#;gq8JW20tZ7IV$n*N-NZ zdGnmx$un)O*izZ@*{lCId;4pe%lTSzyxo2O%g=?+-iLo|oGJ5NJ*dcgo_|g<)A7oO zw&IKRIz?N{FIV##8r~IYYkd1Du;KTGyT0d{6XiKx6o>eAtty?`vyE@v{Mbg$EUi11 zE6a@TGQJ9UaeCRUt-h}W(yx1OE!Ig~x#SYRV}zIB_sM7FC3!DxY%9+Dm38Xb%G1J= zV?3Mez6VcEZ+>|@u42!BCUsX)r#oy#D;}Qb6YG;~__RPKVM?vPylusY*u%e~-@j&w zJaJMw{O+b72aj*xHoLMQud&{&XXh#YKmV>=tJey&weL{;b46O)b-r#qPdD?gl8WlD zraifJ3q$6dc=&X3&|9OPS81iUVlG}~6MAxMmQh8U(G%8;mSu2f2F`<*d+L&bC9=%3!nee7a{!W_kGj>5U5>sHn_{ND@qC+-9ipqw%1^k6&|M-M-vk z{oG5#E9Ioz_ma@-kFTtJRcY?AknN=X&-XX4K6^1!UhjVXrB@5u;!j<^Kf7Fd>i>zA z-#d&;VAuqK) zZkT?7P2Xwv*Xx;KPOm+x{&1H4SkWw1pKd+%V_Hp{>Dw*ubx)OftUY$z_3|}d;YUB% z=lLi||F`-(llj^0ip;gH1{^nER&oY&)LpsVpqaWoNXju(Dau>NG=1Ytn-I^aB}*?D zRtXFEmnmzsD!kXJGS{kD8PVMOdb8NMNo9}!x*V!}@>EF4&1+NQo>@GLyzKhKb!0f# z#rw~)Fv|O5aMn#jd#>bton7l!Pm^SGu=h zKeP92%B~(BhZqwTMAuA6{9t79kV*OL!H>^g{5bjH;k$oH#b0UyW-mVe=k>wM?LUhD zJpOR@*~O0qMFLxEEyOPf9Tc#0y&$%&H~dX;f!Xhz2?svze)_h$;;GVtCC8TkiK<@t zr^5WK3Wp(w?}u{|2?wRcSAF{aA$}28NbIhanmh6qZSI~Id6T0%T~wkzi@W*xfrKqf z&it@aJTJk^T%a@2Ol@hymJbaUw{@3z&b)F+;<>1wo@?cFIZv-`rJA>1FS+b>m~&Z% z%a;@H*My49Io&^**F*c&d)Lq}+dS@zzvP}~STM=zX+(%eq58fxk3Mo8R4BT|U=kVJ zETyZR7LxLz^`L8K!+-G^FP-BJn7?+hi7PqnTCnVwbJ&d)9f^xox4qaQUMhc9C~MO$ z&WktAGDS-6W%}mCnZG>wa;wO(_m&YYXQy0JvQ1xXx%pK6?4*-RZ^(q??qAUzZ9eDo zTIte_t6Zw)TnIY)QS|`hou;m6*Ycbg0l_21!7JX0zP?j*sPbaS+Z{U6ucLTnte44H zgg-wVXxHngy)kXi887y8QW*lPrXPBlYxcrjko99y(@`#-UF~nLoLdzr`jodUUM%?D zwuz<}M0mfJrq2;Gn-OM{e(Z#vr*H4IrX3H9Qo3&&n5}vhShKHi!+rDa^|w#?>{EVJ zEx~ahh_~+R-h=rc_1>+~n{{o&4&J_p6~+gxR3?=fBsQd-*v zQgd%CkHhq+T~|1tD=^m)H-%>EBfp7G6cc?{8qLt8|@9x=E6rjipcKDUY2DTs0A zWFy|Y>qD~JjdGW6IJKq1*DrvjzQkJll);or!6|kuXO{&34!yiTq<;3?yDw+V@epxZ zYk9aLEH$Qi5}TE5*9;LRjn~H8gY|o&R9E#2C!R^z@y6n$ti)=4?#@ket69`GI&Vw; zXu}_LyNAQDn01Lwo~yQ~dEAUAjLQ3MUgfr#`fF#(Y>aWJ%iX~+JLtCsBkF7+%)Jfldc%tlD z#Hogx#~Cg!*ivGYHq8M7(-#Qo(~oZ7R;{|k3! z!VHH!-!@E=IyHUO%A2?R?Nxr-eHAU8|Lm{H_6tF;Sno~!_Bwc(rmT=g<(`6C*++d7 zEjAtgXXK_b&*S@vV_UiYU1j{Qd;b^DiH@>M{j-^(XSSPc`t2+wqi5ZFS5f4wxxK%( zv;OtpXQY%Ale&%AuEr%N2$;;YP2W1fcwgfD+d{u?Z}r@L@Xftywy?=Rw|XviOzw?5 z>+8zU-z*e*d)uPTS-+}8W1n`i9-bZTRdO=@({_38$v(D|7V|_sy&}g{b!3L$v-{^t zy#-t%&&14oqdOzd{&k7@jS!oC4hFZZzR2ugaXY^~D28dP%l;q#^%}WSMG85ecs$pS z^X-56;P4XFrD?Y=dU2=oi3BOvZ@w*c_0*4>-~y@ z92GovU3}j!yW=wpd{%#JmF{McJl(K{2dH3pO8#jxN z2fbChcCXrGwEs`h%F4Zh&38C{t^ZT|<bGjNd}G?JO3svXIE`Cy50X`@&~)T{rBD$Zs)Med4JtH z|N83hWz}oH2=r(Ma~#ZXzk9EG&7B)>pIcl0SmFFxpjz~IMY|nn((CqqU*jJ#%o)}X zLhFyO_Stag!NLZ`jq_|Sn>?@HoxmiH=CbY^>%Wm`1bW`2lsi-pK|2VJm2ztM=u|<(BJN_ z&bjx-N=MD*zF~}Of4KAcq@t@-N=! zPY<%*8R+GunISq|NM+H&_d%K`7=Pza<(kkN=FD?3@4xfyyxb33B75_ftUsf0GUL>u z_P`oj#5TH5m7EIqaTexr?Vfl^-lBS-BeCY}*t8gJixi~ajUtU5vQ@IMuW%DE-$ ze3J5cG@H}3J{W25Dc|>I(RRM%sdJzHR=TlH<6(w*%op)nQ}?~ox=|&Uc4z9UcKz~G zd}gNtm1||T>YJ@^+GHqcbK~vP1&c54Q#a6I`z}>hys>4vr^2aYZy)zK$YmYee@=dADAY0k|L)t)2V2FqX;s`j zqOnwWwvV{H|NI+|FQ1d%ws3uh%7d0|KC*IGd22)F*N3`$OIIg?&a%ZZ@LTbwR!bCX2Q$&)!&NG zo$OqC;?)(7-wb!pHr3s5^w4^BLs;X<&Evgq+b?sUa@9RK`Q6m!$s6katT5ThUBN9m zN6A*exnRPl4CzH19dt8;m+}4)J}Wb+`0rVJ29Q0u+P%3 zKEGe~TszB9`d8lUcPuhbB3HJFMM(%nABw%8x^`;df`$)UgSgMf_WN`gSk2Gq47}jC z+cDN@;jNXv=h%Camj%R6Tr%~@yZrqs27*qWoawI)39wkav_EOk^YvZ{V}P26-1R?q z`+l$8`(>I=g;T=Osoxo*yslcbmVcQc?)Pflyt4|$&E}7#*Azaz`Y)y4`10mWe~$=j zuh+;BZ&|hCvZ>vz8(xy{o&GLqQ=Pd)j?c$_jiGR}G-s~Qo(V-~T#U5XJ4DL35Br>I zeBgTMX*YpG+U=_u#xEu|!;IC0hzY30X>XPP(m z^OqU%7%}wK9du?gF=s7%>}-F*p=lGx{#MCS-D5W%K5zKkQZI z3q8CK$qDPEuKS8lIcpVaD|7EeMM=2rypQeA0wd3a z_;Vj`-j+UB(7L2P>hS-$#-8b%bMqW#nlx>8nYm=2z=5xtldnzOq#=>Uw8QG`?Z+ms zx8_|sWI7?fHu3d~ZwYZvUPNzyQ8ml*Smocd11V@u}4hm z$<=)qjvu{tBU@El_@`P0WKYMh%tf}z znymBgh?3Gbq@GwbMt!Sb^hU!D1x5u)) zI-a`Lu|2(bOmb&}_sMYmZF?+JUC*0qQGDU1! zvLsAC@vhOXBZoD#K3I8A)l%pzzH~o^ZDJG0^O9g+PW!c$36oYdZ#=p2)?;3O$@O8? zOY~QHU!8Z_<^A2Pex9zl{zQfl-<|6EmyS$Xzck99B|dShT+_}?UqplFZs-(#w0%hu z=Yq7ztk%-1qk3h*=X*ZcEpO)uZT}T`@N3u1-t|mJlKbLbO*ma_#f_ z&Aa(-doJYg{&uHlZ$G!9rDNvO$2R){|9+HoJ1-a1l~~ZSIp^CRE8~6tJO$+r{Is%H z$qsaTaiIOwYW+AiABVti=}9cvF2y>F{8BGP&PjBU$WWL!>)z}szh7LBo*DnQ_1%%S zg9qev*i_#rceI-R4Drd4jNSEBxA#4p;L|rN3tO&l&H1!WSU_KX)5;l*fsUUJiCo#z z+MMUf^T_-|q>|p11hGO>$AkAO6Ba*j{jq#*^k$EmzqvaiWb#+sp$d z+z}l1Vvb)WUK|MB;wdDt#{XYNrpw~ApK&Z=6{nqq*PQ*cV2i`iop*&Vs_b4qX-ejs zl_H#}7i?6I=B>D8=zrkC>(6d($v>4vuWAsBnh~&a{+S z7WlU%g1>lX=(Y9LYKIu+FTMP$;rzSWeIJ_4<{aMV>sSCg;M@!ZGEsKt9F$?)w0&f2Sb$L1Xh zzSAjjRz*E-z}DH$#WB)eW$2U$u@1>gJa8V&fE?0^ZeJQ6wMj= zGW6D(WFNg_6>s%}lipuWQ_gs6!oy;EP5;!B6*Y+(*SRuw`JP%{!(nFrCz5;5+h;q! zi`BlYsylanE$Y3Bup3Ge=AsN*~8DZKH|?kJn|MzU;HjNUSMTq zMk({(Mm=-MR4-2n_4}{clv30s4jXLdJ@RClw8y!}lMm7Gkb;}6z1J2rti@O601 zmCmEGi>GbfFEnFL#=<38SGbgZU0wEUs<8GWt!o#gFUf4{OqS#bE4=eDo0G#_dv0U; zmT@YqX?EsBNa<_sZXoRJOKHPFCNpBtI=1xBV)~;wD|Xq&utML;Yg>h$N={up`${6`QqIliPO+*SW_)(_ z!tV6dJT(o^UAc;GuYGAZqsR1Mj>?4ec;gvyuMIU$X6elmdE9J$=y!iz0n_xnH&=C! zw5*BGc3rgO@tapaLl<4kUwth9ykwBnThFgrZ?eRCHY7`|_pa=5dbuL)=|Uly3x7FPx+&#&K~UE8qW3pCxGyf7>eb%YyeLrZ+Lnfsn!V3*zn?BVdM0J2 z=GFI_b6G9Q6xX=4<%*~}oSX7K=E^eZ<2JW0TC&f-*YVe5dFYI{|8IQ$segKIkz8cp zn)f%ZbZLLlOkB5EJ}JU<$ui^AFn8{CC#Oq#Oegshhy@aFZa znALK0OH!QnoOF)AE_)Y!`e5Rvzx(?n&)lY^i#^Pr75SeCalf=Y&}oW9w1C$hjpclE z&K?Vu3DDn_&$KA@#btlKU=3a~?sQk5`%5-)xNqNeqJ8q>r2g;mUYaix78oe=t-9dZ zae1!KeJTDu>}d}y>o`_V-m(kb#nKw-Foqf*hw7~SweYs6Go^dN@ zZ=D%fuf6ZM#mWBk9n^6RcHFzQsGN!vvQYwT9@?7Dx3Rc@r;s^ ziOO25JUcwrZCt%m_m#?{JsUhO9dwQBX#1J`{8*&3_|nM5QAS71JR;AoSeiB0wkfl7 z|Doi7a{uk(g--;Jm2a(jnB#fvyp&jh!NRDSmD?vAyiv2g;YW6I$mwQJo5$DX{xeMA z-pjdxWjS+Wj*-?w&38Rhe(4lGPk+gJXzADVpB~e>&nrGKlM?^U(kg9Tz2^D)srycD zS#ph`zw*?bmYmigP0bLyPi~zTQevn0=kC8S+1u3XjGEO)cE>L+>{(||vOHpS>?@e$ zH#Kg)L8$Z0Y4?*?smXqN8eHpSYj!Df702?=vqT;)d$i-jtOJvoWH)$bFz>WEvTj4| zDi1$ho6mFN&%~6^U-fk9e}#?ey&0c9b{ZN>a0mR`7-lDV;L0B_))~J_o=*FEYkl_{ z=MQ(=r6rX8uIQ_jc{hsAmJl$QAO2!-j8gPzt6xXwNLd@r$_~^Rb6PeNyAiXtoUxc*XHu*;RO}P^jeJ|Yb z}Lsx8^k_#)=hB z`@24<9GNHK*X^A4Rl@7g#?1%PI>Jt@bUyWrA>~c85Z~wX?Gxc_U$o)Y>cz5+eLDj*%OyQh zqO{L*s3<7=SlpWW`Q%?Oz4cQAwAlO4^Vdpf_(haO_TAj9!d`oAL4|tWhP|@S{&KC~ zk?di2r1e%;xcLt66XNb4yQeN?W?Hp>PNn6lc_}##M@}tUYO}Co19p*Ibm1jx*2!(1P1>*r7QR8gUs)58x#0-zU(YHop@?n^}=7Z zoH=#L^Os~x7rOD^EITFf=#9<0b?z6$LbpklO3$9M=FPdiukG7X7%rV#C3gSO&y1<% zf87pEPyQTxnBD)*q~uV$ZOYHXeqQVR_H|ad%-dbz7B4nEi!A2sTzK-ako9ue=p|9& zQ~sY|Tp!7#VQww=@1y{ilE$3x%MQ+&lrbeI^ZMl*t5*eaWz0+wzPXBHX5=z{ZJB=) zrYpTVvo}QST1wvDn7|N|is=5h8|-nnuVijnu626jiM*VOsp}@@ymXJ%wO^7RBCo+O z6E`uJv-8t;1*3B>>XaFIMeaPf6ZQB1ggM^5uOy@w>~KH6`38gO^jV*89Jn&^R@F0y z_JY5@zjs}dQ#F>_JS)_7eQ|d4#I1X-eSOw1{pRZxUCAilGgG@ip78v>JwC~@I)0gf z;Mt&%z_N=n+wO&Kxg@vDb=k@@JI~cmT(VSX#>un0x>u||(bD^Ay3!}@yRPS$l+0Ol z?tR_e&G4`2jh<49&AqrI_3TN0k9P#y9eF(Ec=5(~DT}GcJ8OQuKXh?HboP8JDWCMW zoH{eM`5K%(Y4vr*>{6RW<~QHk-^jmx@uzK4_V(BOx2`6K*ZYQMDEDZ~n{Mmq+c7nG z*_M@BE)QC4)~-`i`@Lk-r_F8WuI^LIn_40ld-nW4y@C^Z($mgvQhD$&Uc~>$(!G;c z8hy6jG~duB>ivC%?TLqYjY}G<`kYtkM;HBBAY1D0ey1#PZg3`lZQT2AkIA2NzA%TL z{njh4z4zMMb6<`HhAoV^c6O?CfsN+&$($RvEH5rt=&Q3ym^bys$#k0)u>z@<9h1f9 zG<}`rck|*CyIH6Fyr#7*sbJ$so*JuW{z`wsR2#O{cU0o^bBZmJ?!`=S)Aiiu@cdU$ z_L3YO_3#T1R`q>}ko~E-*=3RDd9}wqpDsOG5~JvuekGZAnxp#f+2^(fcHK>>e!pFb zue|9p|AbjAPgg5spHN*c^RYt3!|&A3+hX796wCxW^Vj`jpD8EZh&eO|9&iKAVVPJO z8N=tZOt8#nnSciI2+n8i1)U;ryl`5)`4{D9g=%XuuhqWjU6RQ?DYHrB(DFYU4op&L zI-=*mu&E{fz5eSLr(Ug-d&97q$CcysymznG*zB{>+8qBLycj+FU+uR~uQtE`^X}*D z)g`6s<@K}v|9biA>r|cpil^@G)}Qx)QS+;w-$l*zGXJ_Alb$jzFOS>px$Exa>EZu3 zqa7s>i*&ct|6dB~sauL+3(@OKEVyDsF5UXO|7`gD3!%bGu9p43`tXIC;_3BU{Hk}^ zeoXz}V)jGvL-hZz1yd$p3w-%^e*>R<>4e|;9e$a6Zq~PF-^#on9P&aS>fL{X^;5Pd zI^Fp%SwC|@&Y%10^(t+Z=k(Wp72%2a_9QJWn4>P=`0$b~U#@JtQx+oE&o%Y^zshG% zzPoH=vdpWmosc-m@YmmXelNd?E0XN@A6(bk81v|#ZieZx%ANlW12b9|T5mO(%oaTF zocQ|Lb6$M(bg=sBr+nq#y1)OJb>-Fa?>_r<%9rg;YWKFT7S&k+(-k^=k*QdK(7hmbHI$6H(Q^LLfrZ2bk zZZVxNJ7rcAFXR3u<)Wgx|DP6Y;4^&qdz(u2#kYI-J_cLe5tQ(>4{ObQwBh&tbLam| z5(_$Y?$H9%`*NGAGLK&MwzQU%U0oL|e@0~Ogd@c|kM_3Cn_^%3Y*(KFr^b)X&8=$g z_CZk{0j!FzSD7x|{MWK#{>&J?q&R!o&M zRJ;5A>g3h=>*L;+u&rG@^AKP3+@|f;;&W%mDBSt|=;GD%{(blM{(XA)d-(jn$Nl1J zzp?+?uP;~MSugkZ@;meJc-vdGyL%h!SQ;6#ob_jh96K;oPED74RTf)g^2D_QiYM=N zoz&Wy>BabE_JN*BH{Bn$pDVXAjZB|D?ahLy2OooPbj^}Un5=x1|AOe^MSXYniGQgy zw%pmP@-lth`ZF?pE+ruXxl6TvhziZOtBhCN&T{+emg~cM_=&^k*QqUfe`NES3MAxr7}YDSGmhP( zxPPJJytqc+Lw|F(C@xi*w#q%1kdCY+K&v>cD278fueRS(I#_eff8Tc-pe^ZQ_1&WH(LQvehv> zS=adQrr=LEoV~NnB2R3dt6aPNLEI*;Z8f(wG&f9Ti1rIguYYQrY@p0*G=XEr;Xt{f z1spnw?b|vOo8N!2e%Met!S!gPnB^X?1vw8FAIsk_7n^ds;;O^nyad^std`HOv$@;k zT+#}3eImz~xI$%7`kIR9MTzg3wmGb3Vg4t?YoMKdN26;(-7MyKhhm32T@u~wUr$$P zXNo^bwwczu={o1*5AuDt|H{T**`V<`(RTR)%an%0hbLc2Ucb9e`A_oaDZUSlG$xe4 zUv%nnAD1@MvN`We_1_=NTX8SwHs?+2fxya-!WRb{t(Q!RLbHv_L=Sz zwBua#6<3?`YW-<^GcHWrvu@ht3w^dn>h7Pobxc#t|MrPi$-QT`nQY?U`;uLw;YzZf z{an*2h8Y_kKe{)uQfepD@uW0)7WbliQF*P3Gkvyy{9{|gvME{qu+sDsbAFz``TE(D zxr-Wfk^}|T=>*p+FIcpci(#t6yZOzgrz%!i)p>ST@3F5_*uLkqD%(nP<_)`w`+leP zOW*A7n-ue(uhD+Tr-GZ@Ld~7`9<6+5a4!BwTzg*A8wC^n!nrr31n>3TX%X-&{@Qd=?0wczmEl$GX^8C_w=dNndvmZfOg8*e!Lcv8}_dk>#m ze6mVzn9^;tW>v{qImXNMg+w05^=j?P{;aCn2`)M9 zck;q(Z*g1dH!t8apKx_$$mPg@XP#%Tsw}A66uXOgcaMP9#NG&NhgWP?*(Y?Xv^JzD zNjOQKXh;;9rMY)}b_-j4*Ue`w@x94s^*Wh< zCT?ojTz7qI)wf{f1xsIPJ~|$48o!^(V#T|_xqB8Y%duo-mOGUvcGdsWbIW6`&F`Gv z{?b0pEK#_4!cy)l?v<(Mj~;2AcKLad-@=Kh8KJXpIcdknuxx$rzvRzfFYQqES9R?B zl>Nii?mX6M46S;wSnaV&_{F+Fe=j|A?kQY9XTM+cdVebKgoT^;KWmBSeZ;)1=jmLn zJh7Kkmnu&cB(s#rp^{vR^MGrW?Gbekjn*L9Q`Qoby-EUrR(+ZSHo1Hs%_qvFv!i+hW z!V1-=F{eCLn%#1KS?~9gPb^B-Zmmwgm3Va5HV@N|(r3HvS{E-`$m{LWeqC)E-`}&J z%L=FNIqB$k-+JNno$FMaC1+k}`{j8MYBpLO{ra4$NXeY?9FKp zJuDV|_%KB~Q~k1F9lwR9yUyXq%?}^*8nm4&DXe;sc)Gi0nqKQ>p|Hey(SH|jF0}Oj zpefK_`{~nmF8v4t%hJ8Uw`QJtBe`mn%8Q2=A3W)Z1aaJR&iuhu)bpO?JY5OV3~r*o^m_#3S}pQ*fI zW5~<}SL`&J@80zEw)(!XK340ABXg3~(`v)}-^^0y2XW5kIx<=Gg83&kkGQ!lf4ZM> zp6zr@J0$u@)wc7+@lz=seup*|JP3U0v#{vY^cn5vwDp3tqXo>1xmI*snNs}9Rd8ns zXYCvj&f?3i&tLZR7kR60@9g*cV|66>$hC|A+Ekvtu=D#^t&zhLrn1?28q3|QM_a^y zJyr`lru|5s>w8Cd_N(+oD?HD1epj}6Qu1Zi#=L1|MptWeKL?yY?rke+kbB&uovZ7f zzt!A-=c8((Pem=d>~d(vq6K#ZnDvW1-sgVGHah+C;TZ!C1J3sc>sIB3&fc~3owBRx zy0qBV%V8zmGtb;_TWz2$+bh4RuP-Lqdg>lMwz}Cnm7LfDm;60;T|E0nm0@;l*6k(d z)tVbcgH%Mqgx|I7uk>~G5Up9owPE>-@_daWt``KhzP^^%WRs0Zqz|q8B#pbHclMVl2~nUkiFBY|UYP$|o0i`an>Z?8U9WZwbn-yYNW*%NOgjjZHr- zY_spwP0kKFbj$B1dr@NC(%3!oYy-aq>9Kr!UH$5fP9T4{23PLoz_U7`Too&mPq41L zUA|e%L_XrJV(6~TZh-|UkDh#dR~BELyf=5r%Vbrib+f8pO?X}UVzS9Dk2__o_s=eH z@hD#S>CnjqEQ)54Ax+Mf-qouv-AhOi_u6B<cbuXU-L_;t1GdRbZDg=hVramZkY zkL0$!5hb2+57Kw^+?jUgu-*nSP`&!gn zmV`AsG@aXNq#_hHEqG!7r3w4xCSAXh=Im_3zP>x_WX{h29icB(0&i~XR5b12Ta?T9 zPu_2l$(82Ahj(fz2eS$)i0O;W$Xm%Xb<0cJ4&`�q0Ad9mk4zQ*&SQ)jN-pX@NN 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

hzbCAI5uLsw>JGFQ441^5FgB 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%0A@O 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%0Acw+yHnCSZ}Sc@3F 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 +BKpdjOm$p`BLnf%hlZCUN+8!TTjZ`f$0 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 +\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}} +\def\gap{\vspace{0.5ex}} +\makeindex +\begin{document} +\frontmatter +\pagestyle{empty} +\title{Multi--Precision Math} +\author{\mbox{ +%\begin{small} +\begin{tabular}{c} +Tom St Denis \\ +Algonquin College \\ +\\ +Mads Rasmussen \\ +Open Communications Security \\ +\\ +Greg Rose \\ +QUALCOMM Australia \\ +\end{tabular} +%\end{small} +} +} +\maketitle +This text has been placed in the public domain. This text corresponds to the v0.39 release of the +LibTomMath project. + +\begin{alltt} +Tom St Denis +111 Banning Rd +Ottawa, Ontario +K2L 1C3 +Canada + +Phone: 1-613-836-3160 +Email: tomstdenis@gmail.com +\end{alltt} + +This text is formatted to the international B5 paper size of 176mm wide by 250mm tall using the \LaTeX{} +{\em book} macro package and the Perl {\em booker} package. + +\tableofcontents +\listoffigures +\chapter*{Prefaces} +When I tell people about my LibTom projects and that I release them as public domain they are often puzzled. +They ask why I did it and especially why I continue to work on them for free. The best I can explain it is ``Because I can.'' +Which seems odd and perhaps too terse for adult conversation. I often qualify it with ``I am able, I am willing.'' which +perhaps explains it better. I am the first to admit there is not anything that special with what I have done. Perhaps +others can see that too and then we would have a society to be proud of. My LibTom projects are what I am doing to give +back to society in the form of tools and knowledge that can help others in their endeavours. + +I started writing this book because it was the most logical task to further my goal of open academia. The LibTomMath source +code itself was written to be easy to follow and learn from. There are times, however, where pure C source code does not +explain the algorithms properly. Hence this book. The book literally starts with the foundation of the library and works +itself outwards to the more complicated algorithms. The use of both pseudo--code and verbatim source code provides a duality +of ``theory'' and ``practice'' that the computer science students of the world shall appreciate. I never deviate too far +from relatively straightforward algebra and I hope that this book can be a valuable learning asset. + +This book and indeed much of the LibTom projects would not exist in their current form if it was not for a plethora +of kind people donating their time, resources and kind words to help support my work. Writing a text of significant +length (along with the source code) is a tiresome and lengthy process. Currently the LibTom project is four years old, +comprises of literally thousands of users and over 100,000 lines of source code, TeX and other material. People like Mads and Greg +were there at the beginning to encourage me to work well. It is amazing how timely validation from others can boost morale to +continue the project. Definitely my parents were there for me by providing room and board during the many months of work in 2003. + +To my many friends whom I have met through the years I thank you for the good times and the words of encouragement. I hope I +honour your kind gestures with this project. + +Open Source. Open Academia. Open Minds. + +\begin{flushright} Tom St Denis \end{flushright} + +\newpage +I found the opportunity to work with Tom appealing for several reasons, not only could I broaden my own horizons, but also +contribute to educate others facing the problem of having to handle big number mathematical calculations. + +This book is Tom's child and he has been caring and fostering the project ever since the beginning with a clear mind of +how he wanted the project to turn out. I have helped by proofreading the text and we have had several discussions about +the layout and language used. + +I hold a masters degree in cryptography from the University of Southern Denmark and have always been interested in the +practical aspects of cryptography. + +Having worked in the security consultancy business for several years in S\~{a}o Paulo, Brazil, I have been in touch with a +great deal of work in which multiple precision mathematics was needed. Understanding the possibilities for speeding up +multiple precision calculations is often very important since we deal with outdated machine architecture where modular +reductions, for example, become painfully slow. + +This text is for people who stop and wonder when first examining algorithms such as RSA for the first time and asks +themselves, ``You tell me this is only secure for large numbers, fine; but how do you implement these numbers?'' + +\begin{flushright} +Mads Rasmussen + +S\~{a}o Paulo - SP + +Brazil +\end{flushright} + +\newpage +It's all because I broke my leg. That just happened to be at about the same time that Tom asked for someone to review the section of the book about +Karatsuba multiplication. I was laid up, alone and immobile, and thought ``Why not?'' I vaguely knew what Karatsuba multiplication was, but not +really, so I thought I could help, learn, and stop myself from watching daytime cable TV, all at once. + +At the time of writing this, I've still not met Tom or Mads in meatspace. I've been following Tom's progress since his first splash on the +sci.crypt Usenet news group. I watched him go from a clueless newbie, to the cryptographic equivalent of a reformed smoker, to a real +contributor to the field, over a period of about two years. I've been impressed with his obvious intelligence, and astounded by his productivity. +Of course, he's young enough to be my own child, so he doesn't have my problems with staying awake. + +When I reviewed that single section of the book, in its very earliest form, I was very pleasantly surprised. So I decided to collaborate more fully, +and at least review all of it, and perhaps write some bits too. There's still a long way to go with it, and I have watched a number of close +friends go through the mill of publication, so I think that the way to go is longer than Tom thinks it is. Nevertheless, it's a good effort, +and I'm pleased to be involved with it. + +\begin{flushright} +Greg Rose, Sydney, Australia, June 2003. +\end{flushright} + +\mainmatter +\pagestyle{headings} +\chapter{Introduction} +\section{Multiple Precision Arithmetic} + +\subsection{What is Multiple Precision Arithmetic?} +When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively +raise or lower the precision of the numbers we are dealing with. For example, in decimal we almost immediate can +reason that $7$ times $6$ is $42$. However, $42$ has two digits of precision as opposed to one digit we started with. +Further multiplications of say $3$ result in a larger precision result $126$. In these few examples we have multiple +precisions for the numbers we are working with. Despite the various levels of precision a single subset\footnote{With the occasional optimization.} + of algorithms can be designed to accomodate them. + +By way of comparison a fixed or single precision operation would lose precision on various operations. For example, in +the decimal system with fixed precision $6 \cdot 7 = 2$. + +Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in +schools to manually add, subtract, multiply and divide. + +\subsection{The Need for Multiple Precision Arithmetic} +The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation +of public-key cryptography algorithms. Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require +integers of significant magnitude to resist known cryptanalytic attacks. For example, at the time of this writing a +typical RSA modulus would be at least greater than $10^{309}$. However, modern programming languages such as ISO C \cite{ISOC} and +Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision. + +\begin{figure}[!here] +\begin{center} +\begin{tabular}{|r|c|} +\hline \textbf{Data Type} & \textbf{Range} \\ +\hline char & $-128 \ldots 127$ \\ +\hline short & $-32768 \ldots 32767$ \\ +\hline long & $-2147483648 \ldots 2147483647$ \\ +\hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\ +\hline +\end{tabular} +\end{center} +\caption{Typical Data Types for the C Programming Language} +\label{fig:ISOC} +\end{figure} + +The largest data type guaranteed to be provided by the ISO C programming +language\footnote{As per the ISO C standard. However, each compiler vendor is allowed to augment the precision as they +see fit.} can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is +insufficient to accomodate the magnitude required for the problem at hand. An RSA modulus of magnitude $10^{19}$ could be +trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer, +rendering any protocol based on the algorithm insecure. Multiple precision algorithms solve this very problem by +extending the range of representable integers while using single precision data types. + +Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic +primitives. Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in +various cryptographic journals, can render algorithms such as RSA and Diffie-Hellman more efficient. In fact, several +major companies such as RSA Security, Certicom and Entrust have built entire product lines on the implementation and +deployment of efficient algorithms. + +However, cryptography is not the only field of study that can benefit from fast multiple precision integer routines. +Another auxiliary use of multiple precision integers is high precision floating point data types. +The basic IEEE \cite{IEEE} standard floating point type is made up of an integer mantissa $q$, an exponent $e$ and a sign bit $s$. +Numbers are given in the form $n = q \cdot b^e \cdot -1^s$ where $b = 2$ is the most common base for IEEE. Since IEEE +floating point is meant to be implemented in hardware the precision of the mantissa is often fairly small +(\textit{23, 48 and 64 bits}). The mantissa is merely an integer and a multiple precision integer could be used to create +a mantissa of much larger precision than hardware alone can efficiently support. This approach could be useful where +scientific applications must minimize the total output error over long calculations. + +Yet another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$). +In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}. + +\subsection{Benefits of Multiple Precision Arithmetic} +\index{precision} +The benefit of multiple precision representations over single or fixed precision representations is that +no precision is lost while representing the result of an operation which requires excess precision. For example, +the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully. A multiple +precision algorithm would augment the precision of the destination to accomodate the result while a single precision system +would truncate excess bits to maintain a fixed level of precision. + +It is possible to implement algorithms which require large integers with fixed precision algorithms. For example, elliptic +curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum +size the system will ever need. Such an approach can lead to vastly simpler algorithms which can accomodate the +integers required even if the host platform cannot natively accomodate them\footnote{For example, the average smartcard +processor has an 8 bit accumulator.}. However, as efficient as such an approach may be, the resulting source code is not +normally very flexible. It cannot, at runtime, accomodate inputs of higher magnitude than the designer anticipated. + +Multiple precision algorithms have the most overhead of any style of arithmetic. For the the most part the +overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved +platforms. However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the +inputs. That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input +without the designer's explicit forethought. This leads to lower cost of ownership for the code as it only has to +be written and tested once. + +\section{Purpose of This Text} +The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms. +That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping'' +elements that are neglected by authors of other texts on the subject. Several well reknowned texts \cite{TAOCPV2,HAC} +give considerably detailed explanations of the theoretical aspects of algorithms and often very little information +regarding the practical implementation aspects. + +In most cases how an algorithm is explained and how it is actually implemented are two very different concepts. For +example, the Handbook of Applied Cryptography (\textit{HAC}), algorithm 14.7 on page 594, gives a relatively simple +algorithm for performing multiple precision integer addition. However, the description lacks any discussion concerning +the fact that the two integer inputs may be of differing magnitudes. As a result the implementation is not as simple +as the text would lead people to believe. Similarly the division routine (\textit{algorithm 14.20, pp. 598}) does not +discuss how to handle sign or handle the dividend's decreasing magnitude in the main loop (\textit{step \#3}). + +Both texts also do not discuss several key optimal algorithms required such as ``Comba'' and Karatsuba multipliers +and fast modular inversion, which we consider practical oversights. These optimal algorithms are vital to achieve +any form of useful performance in non-trivial applications. + +To solve this problem the focus of this text is on the practical aspects of implementing a multiple precision integer +package. As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.com}} package is used +to demonstrate algorithms with real implementations\footnote{In the ISO C programming language.} that have been field +tested and work very well. The LibTomMath library is freely available on the Internet for all uses and this text +discusses a very large portion of the inner workings of the library. + +The algorithms that are presented will always include at least one ``pseudo-code'' description followed +by the actual C source code that implements the algorithm. The pseudo-code can be used to implement the same +algorithm in other programming languages as the reader sees fit. + +This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch. Showing +the reader how the algorithms fit together as well as where to start on various taskings. + +\section{Discussion and Notation} +\subsection{Notation} +A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1}, \ldots, x_1, x_0)_{ \beta }$ and represent +the integer $x \equiv \sum_{i=0}^{n-1} x_i\beta^i$. The elements of the array $x$ are said to be the radix $\beta$ digits +of the integer. For example, $x = (1,2,3)_{10}$ would represent the integer +$1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$. + +\index{mp\_int} +The term ``mp\_int'' shall refer to a composite structure which contains the digits of the integer it represents, as well +as auxilary data required to manipulate the data. These additional members are discussed further in section +\ref{sec:MPINT}. For the purposes of this text a ``multiple precision integer'' and an ``mp\_int'' are assumed to be +synonymous. When an algorithm is specified to accept an mp\_int variable it is assumed the various auxliary data members +are present as well. An expression of the type \textit{variablename.item} implies that it should evaluate to the +member named ``item'' of the variable. For example, a string of characters may have a member ``length'' which would +evaluate to the number of characters in the string. If the string $a$ equals ``hello'' then it follows that +$a.length = 5$. + +For certain discussions more generic algorithms are presented to help the reader understand the final algorithm used +to solve a given problem. When an algorithm is described as accepting an integer input it is assumed the input is +a plain integer with no additional multiple-precision members. That is, algorithms that use integers as opposed to +mp\_ints as inputs do not concern themselves with the housekeeping operations required such as memory management. These +algorithms will be used to establish the relevant theory which will subsequently be used to describe a multiple +precision algorithm to solve the same problem. + +\subsection{Precision Notation} +The variable $\beta$ represents the radix of a single digit of a multiple precision integer and +must be of the form $q^p$ for $q, p \in \Z^+$. A single precision variable must be able to represent integers in +the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range +$0 \le x < q \beta^2$. The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the +carry. Since all modern computers are binary, it is assumed that $q$ is two. + +\index{mp\_digit} \index{mp\_word} +Within the source code that will be presented for each algorithm, the data type \textbf{mp\_digit} will represent +a single precision integer type, while, the data type \textbf{mp\_word} will represent a double precision integer type. In +several algorithms (notably the Comba routines) temporary results will be stored in arrays of double precision mp\_words. +For the purposes of this text $x_j$ will refer to the $j$'th digit of a single precision array and $\hat x_j$ will refer to +the $j$'th digit of a double precision array. Whenever an expression is to be assigned to a double precision +variable it is assumed that all single precision variables are promoted to double precision during the evaluation. +Expressions that are assigned to a single precision variable are truncated to fit within the precision of a single +precision data type. + +For example, if $\beta = 10^2$ a single precision data type may represent a value in the +range $0 \le x < 10^3$, while a double precision data type may represent a value in the range $0 \le x < 10^5$. Let +$a = 23$ and $b = 49$ represent two single precision variables. The single precision product shall be written +as $c \leftarrow a \cdot b$ while the double precision product shall be written as $\hat c \leftarrow a \cdot b$. +In this particular case, $\hat c = 1127$ and $c = 127$. The most significant digit of the product would not fit +in a single precision data type and as a result $c \ne \hat c$. + +\subsection{Algorithm Inputs and Outputs} +Within the algorithm descriptions all variables are assumed to be scalars of either single or double precision +as indicated. The only exception to this rule is when variables have been indicated to be of type mp\_int. This +distinction is important as scalars are often used as array indicies and various other counters. + +\subsection{Mathematical Expressions} +The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an integer not greater than the expression +itself. For example, $\lfloor 5.7 \rfloor = 5$. Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression +rounded to an integer not less than the expression itself. For example, $\lceil 5.1 \rceil = 6$. Typically when +the $/$ division symbol is used the intention is to perform an integer division with truncation. For example, +$5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity. When an expression is written as a +fraction a real value division is implied, for example ${5 \over 2} = 2.5$. + +The norm of a multiple precision integer, for example $\vert \vert x \vert \vert$, will be used to represent the number of digits in the representation +of the integer. For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$. + +\subsection{Work Effort} +\index{big-Oh} +To measure the efficiency of the specified algorithms, a modified big-Oh notation is used. In this system all +single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}. +That is a single precision addition, multiplication and division are assumed to take the same time to +complete. While this is generally not true in practice, it will simplify the discussions considerably. + +Some algorithms have slight advantages over others which is why some constants will not be removed in +the notation. For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a +baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work. In standard big-Oh notation these +would both be said to be equivalent to $O(n^2)$. However, +in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small. As a +result small constant factors in the work effort will make an observable difference in algorithm efficiency. + +All of the algorithms presented in this text have a polynomial time work level. That is, of the form +$O(n^k)$ for $n, k \in \Z^{+}$. This will help make useful comparisons in terms of the speed of the algorithms and how +various optimizations will help pay off in the long run. + +\section{Exercises} +Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to +the discussion at hand. These exercises are not designed to be prize winning problems, but instead to be thought +provoking. Wherever possible the problems are forward minded, stating problems that will be answered in subsequent +chapters. The reader is encouraged to finish the exercises as they appear to get a better understanding of the +subject material. + +That being said, the problems are designed to affirm knowledge of a particular subject matter. Students in particular +are encouraged to verify they can answer the problems correctly before moving on. + +Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of +the problem. However, unlike \cite{TAOCPV2} the problems do not get nearly as hard. The scoring of these +exercises ranges from one (the easiest) to five (the hardest). The following table sumarizes the +scoring system used. + +\begin{figure}[here] +\begin{center} +\begin{small} +\begin{tabular}{|c|l|} +\hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\ + & minutes to solve. Usually does not involve much computer time \\ + & to solve. \\ +\hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\ + & time usage. Usually requires a program to be written to \\ + & solve the problem. \\ +\hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\ + & of work. Usually involves trivial research and development of \\ + & new theory from the perspective of a student. \\ +\hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\ + & of work and research, the solution to which will demonstrate \\ + & a higher mastery of the subject matter. \\ +\hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\ + & novice to solve. Solutions to these problems will demonstrate a \\ + & complete mastery of the given subject. \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Exercise Scoring System} +\end{figure} + +Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or +devising new theory. These problems are quick tests to see if the material is understood. Problems at the second level +are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer. These +two levels are essentially entry level questions. + +Problems at the third level are meant to be a bit more difficult than the first two levels. The answer is often +fairly obvious but arriving at an exacting solution requires some thought and skill. These problems will almost always +involve devising a new algorithm or implementing a variation of another algorithm previously presented. Readers who can +answer these questions will feel comfortable with the concepts behind the topic at hand. + +Problems at the fourth level are meant to be similar to those of the level three questions except they will require +additional research to be completed. The reader will most likely not know the answer right away, nor will the text provide +the exact details of the answer until a subsequent chapter. + +Problems at the fifth level are meant to be the hardest +problems relative to all the other problems in the chapter. People who can correctly answer fifth level problems have a +mastery of the subject matter at hand. + +Often problems will be tied together. The purpose of this is to start a chain of thought that will be discussed in future chapters. The reader +is encouraged to answer the follow-up problems and try to draw the relevance of problems. + +\section{Introduction to LibTomMath} + +\subsection{What is LibTomMath?} +LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C. By portable it +is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on +any given platform. + +The library has been successfully tested under numerous operating systems including Unix\footnote{All of these +trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux, PalmOS and on standalone hardware such +as the Gameboy Advance. The library is designed to contain enough functionality to be able to develop applications such +as public key cryptosystems and still maintain a relatively small footprint. + +\subsection{Goals of LibTomMath} + +Libraries which obtain the most efficiency are rarely written in a high level programming language such as C. However, +even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the +library. Specifically the code has been written to work well with the GNU C Compiler (\textit{GCC}) on both x86 and ARM +processors. Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window +exponentiation and Montgomery reduction have been provided to make the library more efficient. + +Even with the nearly optimal and specialized algorithms that have been included the Application Programing Interface +(\textit{API}) has been kept as simple as possible. Often generic place holder routines will make use of specialized +algorithms automatically without the developer's specific attention. One such example is the generic multiplication +algorithm \textbf{mp\_mul()} which will automatically use Toom--Cook, Karatsuba, Comba or baseline multiplication +based on the magnitude of the inputs and the configuration of the library. + +Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project. Ideally the library should +be source compatible with another popular library which makes it more attractive for developers to use. In this case the +MPI library was used as a API template for all the basic functions. MPI was chosen because it is another library that fits +in the same niche as LibTomMath. Even though LibTomMath uses MPI as the template for the function names and argument +passing conventions, it has been written from scratch by Tom St Denis. + +The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum'' +library exists which can be used to teach computer science students how to perform fast and reliable multiple precision +integer arithmetic. To this end the source code has been given quite a few comments and algorithm discussion points. + +\section{Choice of LibTomMath} +LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but +for more worthy reasons. Other libraries such as GMP \cite{GMP}, MPI \cite{MPI}, LIP \cite{LIP} and OpenSSL +\cite{OPENSSL} have multiple precision integer arithmetic routines but would not be ideal for this text for +reasons that will be explained in the following sub-sections. + +\subsection{Code Base} +The LibTomMath code base is all portable ISO C source code. This means that there are no platform dependent conditional +segments of code littered throughout the source. This clean and uncluttered approach to the library means that a +developer can more readily discern the true intent of a given section of source code without trying to keep track of +what conditional code will be used. + +The code base of LibTomMath is well organized. Each function is in its own separate source code file +which allows the reader to find a given function very quickly. On average there are $76$ lines of code per source +file which makes the source very easily to follow. By comparison MPI and LIP are single file projects making code tracing +very hard. GMP has many conditional code segments which also hinder tracing. + +When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $100$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.} + which is fairly small compared to GMP (over $250$KiB). LibTomMath is slightly larger than MPI (which compiles to about +$50$KiB) but LibTomMath is also much faster and more complete than MPI. + +\subsection{API Simplicity} +LibTomMath is designed after the MPI library and shares the API design. Quite often programs that use MPI will build +with LibTomMath without change. The function names correlate directly to the action they perform. Almost all of the +functions share the same parameter passing convention. The learning curve is fairly shallow with the API provided +which is an extremely valuable benefit for the student and developer alike. + +The LIP library is an example of a library with an API that is awkward to work with. LIP uses function names that are often ``compressed'' to +illegible short hand. LibTomMath does not share this characteristic. + +The GMP library also does not return error codes. Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors +are signaled to the host application. This happens to be the fastest approach but definitely not the most versatile. In +effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely +undersireable in many situations. + +\subsection{Optimizations} +While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does +feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring. GMP +and LIP also feature such optimizations while MPI only uses baseline algorithms with no optimizations. GMP lacks a few +of the additional modular reduction optimizations that LibTomMath features\footnote{At the time of this writing GMP +only had Barrett and Montgomery modular reduction algorithms.}. + +LibTomMath is almost always an order of magnitude faster than the MPI library at computationally expensive tasks such as modular +exponentiation. In the grand scheme of ``bignum'' libraries LibTomMath is faster than the average library and usually +slower than the best libraries such as GMP and OpenSSL by only a small factor. + +\subsection{Portability and Stability} +LibTomMath will build ``out of the box'' on any platform equipped with a modern version of the GNU C Compiler +(\textit{GCC}). This means that without changes the library will build without configuration or setting up any +variables. LIP and MPI will build ``out of the box'' as well but have numerous known bugs. Most notably the author of +MPI has recently stopped working on his library and LIP has long since been discontinued. + +GMP requires a configuration script to run and will not build out of the box. GMP and LibTomMath are still in active +development and are very stable across a variety of platforms. + +\subsection{Choice} +LibTomMath is a relatively compact, well documented, highly optimized and portable library which seems only natural for +the case study of this text. Various source files from the LibTomMath project will be included within the text. However, +the reader is encouraged to download their own copy of the library to actually be able to work with the library. + +\chapter{Getting Started} +\section{Library Basics} +The trick to writing any useful library of source code is to build a solid foundation and work outwards from it. First, +a problem along with allowable solution parameters should be identified and analyzed. In this particular case the +inability to accomodate multiple precision integers is the problem. Futhermore, the solution must be written +as portable source code that is reasonably efficient across several different computer platforms. + +After a foundation is formed the remainder of the library can be designed and implemented in a hierarchical fashion. +That is, to implement the lowest level dependencies first and work towards the most abstract functions last. For example, +before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm. +By building outwards from a base foundation instead of using a parallel design methodology the resulting project is +highly modular. Being highly modular is a desirable property of any project as it often means the resulting product +has a small footprint and updates are easy to perform. + +Usually when I start a project I will begin with the header files. I define the data types I think I will need and +prototype the initial functions that are not dependent on other functions (within the library). After I +implement these base functions I prototype more dependent functions and implement them. The process repeats until +I implement all of the functions I require. For example, in the case of LibTomMath I implemented functions such as +mp\_init() well before I implemented mp\_mul() and even further before I implemented mp\_exptmod(). As an example as to +why this design works note that the Karatsuba and Toom-Cook multipliers were written \textit{after} the +dependent function mp\_exptmod() was written. Adding the new multiplication algorithms did not require changes to the +mp\_exptmod() function itself and lowered the total cost of ownership (\textit{so to speak}) and of development +for new algorithms. This methodology allows new algorithms to be tested in a complete framework with relative ease. + +FIGU,design_process,Design Flow of the First Few Original LibTomMath Functions. + +Only after the majority of the functions were in place did I pursue a less hierarchical approach to auditing and optimizing +the source code. For example, one day I may audit the multipliers and the next day the polynomial basis functions. + +It only makes sense to begin the text with the preliminary data types and support algorithms required as well. +This chapter discusses the core algorithms of the library which are the dependents for every other algorithm. + +\section{What is a Multiple Precision Integer?} +Recall that most programming languages, in particular ISO C \cite{ISOC}, only have fixed precision data types that on their own cannot +be used to represent values larger than their precision will allow. The purpose of multiple precision algorithms is +to use fixed precision data types to create and manipulate multiple precision integers which may represent values +that are very large. + +As a well known analogy, school children are taught how to form numbers larger than nine by prepending more radix ten digits. In the decimal system +the largest single digit value is $9$. However, by concatenating digits together larger numbers may be represented. Newly prepended digits +(\textit{to the left}) are said to be in a different power of ten column. That is, the number $123$ can be described as having a $1$ in the hundreds +column, $2$ in the tens column and $3$ in the ones column. Or more formally $123 = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0$. Computer based +multiple precision arithmetic is essentially the same concept. Larger integers are represented by adjoining fixed +precision computer words with the exception that a different radix is used. + +What most people probably do not think about explicitly are the various other attributes that describe a multiple precision +integer. For example, the integer $154_{10}$ has two immediately obvious properties. First, the integer is positive, +that is the sign of this particular integer is positive as opposed to negative. Second, the integer has three digits in +its representation. There is an additional property that the integer posesses that does not concern pencil-and-paper +arithmetic. The third property is how many digits placeholders are available to hold the integer. + +The human analogy of this third property is ensuring there is enough space on the paper to write the integer. For example, +if one starts writing a large number too far to the right on a piece of paper they will have to erase it and move left. +Similarly, computer algorithms must maintain strict control over memory usage to ensure that the digits of an integer +will not exceed the allowed boundaries. These three properties make up what is known as a multiple precision +integer or mp\_int for short. + +\subsection{The mp\_int Structure} +\label{sec:MPINT} +The mp\_int structure is the ISO C based manifestation of what represents a multiple precision integer. The ISO C standard does not provide for +any such data type but it does provide for making composite data types known as structures. The following is the structure definition +used within LibTomMath. + +\index{mp\_int} +\begin{figure}[here] +\begin{center} +\begin{small} +%\begin{verbatim} +\begin{tabular}{|l|} +\hline +typedef struct \{ \\ +\hspace{3mm}int used, alloc, sign;\\ +\hspace{3mm}mp\_digit *dp;\\ +\} \textbf{mp\_int}; \\ +\hline +\end{tabular} +%\end{verbatim} +\end{small} +\caption{The mp\_int Structure} +\label{fig:mpint} +\end{center} +\end{figure} + +The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows. + +\begin{enumerate} +\item The \textbf{used} parameter denotes how many digits of the array \textbf{dp} contain the digits used to represent +a given integer. The \textbf{used} count must be positive (or zero) and may not exceed the \textbf{alloc} count. + +\item The \textbf{alloc} parameter denotes how +many digits are available in the array to use by functions before it has to increase in size. When the \textbf{used} count +of a result would exceed the \textbf{alloc} count all of the algorithms will automatically increase the size of the +array to accommodate the precision of the result. + +\item The pointer \textbf{dp} points to a dynamically allocated array of digits that represent the given multiple +precision integer. It is padded with $(\textbf{alloc} - \textbf{used})$ zero digits. The array is maintained in a least +significant digit order. As a pencil and paper analogy the array is organized such that the right most digits are stored +first starting at the location indexed by zero\footnote{In C all arrays begin at zero.} in the array. For example, +if \textbf{dp} contains $\lbrace a, b, c, \ldots \rbrace$ where \textbf{dp}$_0 = a$, \textbf{dp}$_1 = b$, \textbf{dp}$_2 = c$, $\ldots$ then +it would represent the integer $a + b\beta + c\beta^2 + \ldots$ + +\index{MP\_ZPOS} \index{MP\_NEG} +\item The \textbf{sign} parameter denotes the sign as either zero/positive (\textbf{MP\_ZPOS}) or negative (\textbf{MP\_NEG}). +\end{enumerate} + +\subsubsection{Valid mp\_int Structures} +Several rules are placed on the state of an mp\_int structure and are assumed to be followed for reasons of efficiency. +The only exceptions are when the structure is passed to initialization functions such as mp\_init() and mp\_init\_copy(). + +\begin{enumerate} +\item The value of \textbf{alloc} may not be less than one. That is \textbf{dp} always points to a previously allocated +array of digits. +\item The value of \textbf{used} may not exceed \textbf{alloc} and must be greater than or equal to zero. +\item The value of \textbf{used} implies the digit at index $(used - 1)$ of the \textbf{dp} array is non-zero. That is, +leading zero digits in the most significant positions must be trimmed. + \begin{enumerate} + \item Digits in the \textbf{dp} array at and above the \textbf{used} location must be zero. + \end{enumerate} +\item The value of \textbf{sign} must be \textbf{MP\_ZPOS} if \textbf{used} is zero; +this represents the mp\_int value of zero. +\end{enumerate} + +\section{Argument Passing} +A convention of argument passing must be adopted early on in the development of any library. Making the function +prototypes consistent will help eliminate many headaches in the future as the library grows to significant complexity. +In LibTomMath the multiple precision integer functions accept parameters from left to right as pointers to mp\_int +structures. That means that the source (input) operands are placed on the left and the destination (output) on the right. +Consider the following examples. + +\begin{verbatim} + mp_mul(&a, &b, &c); /* c = a * b */ + mp_add(&a, &b, &a); /* a = a + b */ + mp_sqr(&a, &b); /* b = a * a */ +\end{verbatim} + +The left to right order is a fairly natural way to implement the functions since it lets the developer read aloud the +functions and make sense of them. For example, the first function would read ``multiply a and b and store in c''. + +Certain libraries (\textit{LIP by Lenstra for instance}) accept parameters the other way around, to mimic the order +of assignment expressions. That is, the destination (output) is on the left and arguments (inputs) are on the right. In +truth, it is entirely a matter of preference. In the case of LibTomMath the convention from the MPI library has been +adopted. + +Another very useful design consideration, provided for in LibTomMath, is whether to allow argument sources to also be a +destination. For example, the second example (\textit{mp\_add}) adds $a$ to $b$ and stores in $a$. This is an important +feature to implement since it allows the calling functions to cut down on the number of variables it must maintain. +However, to implement this feature specific care has to be given to ensure the destination is not modified before the +source is fully read. + +\section{Return Values} +A well implemented application, no matter what its purpose, should trap as many runtime errors as possible and return them +to the caller. By catching runtime errors a library can be guaranteed to prevent undefined behaviour. However, the end +developer can still manage to cause a library to crash. For example, by passing an invalid pointer an application may +fault by dereferencing memory not owned by the application. + +In the case of LibTomMath the only errors that are checked for are related to inappropriate inputs (division by zero for +instance) and memory allocation errors. It will not check that the mp\_int passed to any function is valid nor +will it check pointers for validity. Any function that can cause a runtime error will return an error code as an +\textbf{int} data type with one of the following values (fig \ref{fig:errcodes}). + +\index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM} +\begin{figure}[here] +\begin{center} +\begin{tabular}{|l|l|} +\hline \textbf{Value} & \textbf{Meaning} \\ +\hline \textbf{MP\_OKAY} & The function was successful \\ +\hline \textbf{MP\_VAL} & One of the input value(s) was invalid \\ +\hline \textbf{MP\_MEM} & The function ran out of heap memory \\ +\hline +\end{tabular} +\end{center} +\caption{LibTomMath Error Codes} +\label{fig:errcodes} +\end{figure} + +When an error is detected within a function it should free any memory it allocated, often during the initialization of +temporary mp\_ints, and return as soon as possible. The goal is to leave the system in the same state it was when the +function was called. Error checking with this style of API is fairly simple. + +\begin{verbatim} + int err; + if ((err = mp_add(&a, &b, &c)) != MP_OKAY) { + printf("Error: %s\n", mp_error_to_string(err)); + exit(EXIT_FAILURE); + } +\end{verbatim} + +The GMP \cite{GMP} library uses C style \textit{signals} to flag errors which is of questionable use. Not all errors are fatal +and it was not deemed ideal by the author of LibTomMath to force developers to have signal handlers for such cases. + +\section{Initialization and Clearing} +The logical starting point when actually writing multiple precision integer functions is the initialization and +clearing of the mp\_int structures. These two algorithms will be used by the majority of the higher level algorithms. + +Given the basic mp\_int structure an initialization routine must first allocate memory to hold the digits of +the integer. Often it is optimal to allocate a sufficiently large pre-set number of digits even though +the initial integer will represent zero. If only a single digit were allocated quite a few subsequent re-allocations +would occur when operations are performed on the integers. There is a tradeoff between how many default digits to allocate +and how many re-allocations are tolerable. Obviously allocating an excessive amount of digits initially will waste +memory and become unmanageable. + +If the memory for the digits has been successfully allocated then the rest of the members of the structure must +be initialized. Since the initial state of an mp\_int is to represent the zero integer, the allocated digits must be set +to zero. The \textbf{used} count set to zero and \textbf{sign} set to \textbf{MP\_ZPOS}. + +\subsection{Initializing an mp\_int} +An mp\_int is said to be initialized if it is set to a valid, preferably default, state such that all of the members of the +structure are set to valid values. The mp\_init algorithm will perform such an action. + +\index{mp\_init} +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_init}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. Allocate memory and initialize $a$ to a known valid mp\_int state. \\ +\hline \\ +1. Allocate memory for \textbf{MP\_PREC} digits. \\ +2. If the allocation failed return(\textit{MP\_MEM}) \\ +3. for $n$ from $0$ to $MP\_PREC - 1$ do \\ +\hspace{3mm}3.1 $a_n \leftarrow 0$\\ +4. $a.sign \leftarrow MP\_ZPOS$\\ +5. $a.used \leftarrow 0$\\ +6. $a.alloc \leftarrow MP\_PREC$\\ +7. Return(\textit{MP\_OKAY})\\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_init} +\end{figure} + +\textbf{Algorithm mp\_init.} +The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly +manipulte it. It is assumed that the input may not have had any of its members previously initialized which is certainly +a valid assumption if the input resides on the stack. + +Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for +the digits is allocated. If this fails the function returns before setting any of the other members. The \textbf{MP\_PREC} +name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.} +used to dictate the minimum precision of newly initialized mp\_int integers. Ideally, it is at least equal to the smallest +precision number you'll be working with. + +Allocating a block of digits at first instead of a single digit has the benefit of lowering the number of usually slow +heap operations later functions will have to perform in the future. If \textbf{MP\_PREC} is set correctly the slack +memory and the number of heap operations will be trivial. + +Once the allocation has been made the digits have to be set to zero as well as the \textbf{used}, \textbf{sign} and +\textbf{alloc} members initialized. This ensures that the mp\_int will always represent the default state of zero regardless +of the original condition of the input. + +\textbf{Remark.} +This function introduces the idiosyncrasy that all iterative loops, commonly initiated with the ``for'' keyword, iterate incrementally +when the ``to'' keyword is placed between two expressions. For example, ``for $a$ from $b$ to $c$ do'' means that +a subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$. In each +iteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$. If $b > c$ occured +the loop would not iterate. By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate +decrementally. + +EXAM,bn_mp_init.c + +One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure. It +is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack. The +call to mp\_init() is used only to initialize the members of the structure to a known default state. + +Here we see (line @23,XMALLOC@) the memory allocation is performed first. This allows us to exit cleanly and quickly +if there is an error. If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there +was a memory error. The function XMALLOC is what actually allocates the memory. Technically XMALLOC is not a function +but a macro defined in ``tommath.h``. By default, XMALLOC will evaluate to malloc() which is the C library's built--in +memory allocation routine. + +In order to assure the mp\_int is in a known state the digits must be set to zero. On most platforms this could have been +accomplished by using calloc() instead of malloc(). However, to correctly initialize a integer type to a given value in a +portable fashion you have to actually assign the value. The for loop (line @28,for@) performs this required +operation. + +After the memory has been successfully initialized the remainder of the members are initialized +(lines @29,used@ through @31,sign@) to their respective default states. At this point the algorithm has succeeded and +a success code is returned to the calling function. If this function returns \textbf{MP\_OKAY} it is safe to assume the +mp\_int structure has been properly initialized and is safe to use with other functions within the library. + +\subsection{Clearing an mp\_int} +When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be +returned to the application's memory pool with the mp\_clear algorithm. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_clear}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. The memory for $a$ shall be deallocated. \\ +\hline \\ +1. If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\ +2. for $n$ from 0 to $a.used - 1$ do \\ +\hspace{3mm}2.1 $a_n \leftarrow 0$ \\ +3. Free the memory allocated for the digits of $a$. \\ +4. $a.used \leftarrow 0$ \\ +5. $a.alloc \leftarrow 0$ \\ +6. $a.sign \leftarrow MP\_ZPOS$ \\ +7. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_clear} +\end{figure} + +\textbf{Algorithm mp\_clear.} +This algorithm accomplishes two goals. First, it clears the digits and the other mp\_int members. This ensures that +if a developer accidentally re-uses a cleared structure it is less likely to cause problems. The second goal +is to free the allocated memory. + +The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this +algorithm will not try to free the memory multiple times. Cleared mp\_ints are detectable by having a pre-defined invalid +digit pointer \textbf{dp} setting. + +Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm +with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear. + +EXAM,bn_mp_clear.c + +The algorithm only operates on the mp\_int if it hasn't been previously cleared. The if statement (line @23,a->dp != NULL@) +checks to see if the \textbf{dp} member is not \textbf{NULL}. If the mp\_int is a valid mp\_int then \textbf{dp} cannot be +\textbf{NULL} in which case the if statement will evaluate to true. + +The digits of the mp\_int are cleared by the for loop (line @25,for@) which assigns a zero to every digit. Similar to mp\_init() +the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable. + +The digits are deallocated off the heap via the XFREE macro. Similar to XMALLOC the XFREE macro actually evaluates to +a standard C library function. In this case the free() function. Since free() only deallocates the memory the pointer +still has to be reset to \textbf{NULL} manually (line @33,NULL@). + +Now that the digits have been cleared and deallocated the other members are set to their final values (lines @34,= 0@ and @35,ZPOS@). + +\section{Maintenance Algorithms} + +The previous sections describes how to initialize and clear an mp\_int structure. To further support operations +that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be +able to augment the precision of an mp\_int and +initialize mp\_ints with differing initial conditions. + +These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level +algorithms such as addition, multiplication and modular exponentiation. + +\subsection{Augmenting an mp\_int's Precision} +When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire +result of an operation without loss of precision. Quite often the size of the array given by the \textbf{alloc} member +is large enough to simply increase the \textbf{used} digit count. However, when the size of the array is too small it +must be re-sized appropriately to accomodate the result. The mp\_grow algorithm will provide this functionality. + +\newpage\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_grow}. \\ +\textbf{Input}. An mp\_int $a$ and an integer $b$. \\ +\textbf{Output}. $a$ is expanded to accomodate $b$ digits. \\ +\hline \\ +1. if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\ +2. $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\ +3. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\ +4. Re-allocate the array of digits $a$ to size $v$ \\ +5. If the allocation failed then return(\textit{MP\_MEM}). \\ +6. for n from a.alloc to $v - 1$ do \\ +\hspace{+3mm}6.1 $a_n \leftarrow 0$ \\ +7. $a.alloc \leftarrow v$ \\ +8. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_grow} +\end{figure} + +\textbf{Algorithm mp\_grow.} +It is ideal to prevent re-allocations from being performed if they are not required (step one). This is useful to +prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow. + +The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three). +This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values. + +It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact. This is much +akin to how the \textit{realloc} function from the standard C library works. Since the newly allocated digits are +assumed to contain undefined values they are initially set to zero. + +EXAM,bn_mp_grow.c + +A quick optimization is to first determine if a memory re-allocation is required at all. The if statement (line @24,alloc@) checks +if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count. If the count is not larger than \textbf{alloc} +the function skips the re-allocation part thus saving time. + +When a re-allocation is performed it is turned into an optimal request to save time in the future. The requested digit count is +padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line @25, size@). The XREALLOC function is used +to re-allocate the memory. As per the other functions XREALLOC is actually a macro which evaluates to realloc by default. The realloc +function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before +the re-allocation. All that is left is to clear the newly allocated digits and return. + +Note that the re-allocation result is actually stored in a temporary pointer $tmp$. This is to allow this function to return +an error with a valid pointer. Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$. That would +result in a memory leak if XREALLOC ever failed. + +\subsection{Initializing Variable Precision mp\_ints} +Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size +of input mp\_ints to a given algorithm. The purpose of algorithm mp\_init\_size is similar to mp\_init except that it +will allocate \textit{at least} a specified number of digits. + +\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_init\_size}. \\ +\textbf{Input}. An mp\_int $a$ and the requested number of digits $b$. \\ +\textbf{Output}. $a$ is initialized to hold at least $b$ digits. \\ +\hline \\ +1. $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\ +2. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\ +3. Allocate $v$ digits. \\ +4. for $n$ from $0$ to $v - 1$ do \\ +\hspace{3mm}4.1 $a_n \leftarrow 0$ \\ +5. $a.sign \leftarrow MP\_ZPOS$\\ +6. $a.used \leftarrow 0$\\ +7. $a.alloc \leftarrow v$\\ +8. Return(\textit{MP\_OKAY})\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_init\_size} +\end{figure} + +\textbf{Algorithm mp\_init\_size.} +This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of +digits allocated can be controlled by the second input argument $b$. The input size is padded upwards so it is a +multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits. This padding is used to prevent trivial +allocations from becoming a bottleneck in the rest of the algorithms. + +Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero. This +particular algorithm is useful if it is known ahead of time the approximate size of the input. If the approximation is +correct no further memory re-allocations are required to work with the mp\_int. + +EXAM,bn_mp_init_size.c + +The number of digits $b$ requested is padded (line @22,MP_PREC@) by first augmenting it to the next multiple of +\textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result. If the memory can be successfully allocated the +mp\_int is placed in a default state representing the integer zero. Otherwise, the error code \textbf{MP\_MEM} will be +returned (line @27,return@). + +The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@). The +\textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set +to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines @29,used@, @30,alloc@ and @31,sign@). If the function +returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the +functions to work with. + +\subsection{Multiple Integer Initializations and Clearings} +Occasionally a function will require a series of mp\_int data types to be made available simultaneously. +The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single +statement. It is essentially a shortcut to multiple initializations. + +\newpage\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_init\_multi}. \\ +\textbf{Input}. Variable length array $V_k$ of mp\_int variables of length $k$. \\ +\textbf{Output}. The array is initialized such that each mp\_int of $V_k$ is ready to use. \\ +\hline \\ +1. for $n$ from 0 to $k - 1$ do \\ +\hspace{+3mm}1.1. Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\ +\hspace{+3mm}1.2. If initialization failed then do \\ +\hspace{+6mm}1.2.1. for $j$ from $0$ to $n$ do \\ +\hspace{+9mm}1.2.1.1. Free the mp\_int $V_j$ (\textit{mp\_clear}) \\ +\hspace{+6mm}1.2.2. Return(\textit{MP\_MEM}) \\ +2. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_init\_multi} +\end{figure} + +\textbf{Algorithm mp\_init\_multi.} +The algorithm will initialize the array of mp\_int variables one at a time. If a runtime error has been detected +(\textit{step 1.2}) all of the previously initialized variables are cleared. The goal is an ``all or nothing'' +initialization which allows for quick recovery from runtime errors. + +EXAM,bn_mp_init_multi.c + +This function intializes a variable length list of mp\_int structure pointers. However, instead of having the mp\_int +structures in an actual C array they are simply passed as arguments to the function. This function makes use of the +``...'' argument syntax of the C programming language. The list is terminated with a final \textbf{NULL} argument +appended on the right. + +The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function. A count +$n$ of succesfully initialized mp\_int structures is maintained (line @47,n++@) such that if a failure does occur, +the algorithm can backtrack and free the previously initialized structures (lines @27,if@ to @46,}@). + + +\subsection{Clamping Excess Digits} +When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of +the function instead of checking during the computation. For example, a multiplication of a $i$ digit number by a +$j$ digit produces a result of at most $i + j$ digits. It is entirely possible that the result is $i + j - 1$ +though, with no final carry into the last position. However, suppose the destination had to be first expanded +(\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry. +That would be a considerable waste of time since heap operations are relatively slow. + +The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function +terminates. This way a single heap operation (\textit{at most}) is required. However, if the result was not checked +there would be an excess high order zero digit. + +For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$. The leading zero digit +will not contribute to the precision of the result. In fact, through subsequent operations more leading zero digits would +accumulate to the point the size of the integer would be prohibitive. As a result even though the precision is very +low the representation is excessively large. + +The mp\_clamp algorithm is designed to solve this very problem. It will trim high-order zeros by decrementing the +\textbf{used} count until a non-zero most significant digit is found. Also in this system, zero is considered to be a +positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to +\textbf{MP\_ZPOS}. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_clamp}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. Any excess leading zero digits of $a$ are removed \\ +\hline \\ +1. while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\ +\hspace{+3mm}1.1 $a.used \leftarrow a.used - 1$ \\ +2. if $a.used = 0$ then do \\ +\hspace{+3mm}2.1 $a.sign \leftarrow MP\_ZPOS$ \\ +\hline \\ +\end{tabular} +\end{center} +\caption{Algorithm mp\_clamp} +\end{figure} + +\textbf{Algorithm mp\_clamp.} +As can be expected this algorithm is very simple. The loop on step one is expected to iterate only once or twice at +the most. For example, this will happen in cases where there is not a carry to fill the last position. Step two fixes the sign for +when all of the digits are zero to ensure that the mp\_int is valid at all times. + +EXAM,bn_mp_clamp.c + +Note on line @27,while@ how to test for the \textbf{used} count is made on the left of the \&\& operator. In the C programming +language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails. This is +important since if the \textbf{used} is zero the test on the right would fetch below the array. That is obviously +undesirable. The parenthesis on line @28,a->used@ is used to make sure the \textbf{used} count is decremented and not +the pointer ``a''. + +\section*{Exercises} +\begin{tabular}{cl} +$\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\ + & \\ +$\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations. \\ + & \\ +$\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\ + & encryption when $\beta = 2^{28}$. \\ + & \\ +$\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp. What does it prevent? \\ + & \\ +$\left [ 1 \right ]$ & Give an example of when the algorithm mp\_init\_copy might be useful. \\ + & \\ +\end{tabular} + + +%%% +% CHAPTER FOUR +%%% + +\chapter{Basic Operations} + +\section{Introduction} +In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining +mp\_int structures. This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low +level basis of the entire library. While these algorithm are relatively trivial it is important to understand how they +work before proceeding since these algorithms will be used almost intrinsically in the following chapters. + +The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of +mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures +represent. + +\section{Assigning Values to mp\_int Structures} +\subsection{Copying an mp\_int} +Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making +a copy for the purposes of this text. The copy of the mp\_int will be a separate entity that represents the same +value as the mp\_int it was copied from. The mp\_copy algorithm provides this functionality. + +\newpage\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_copy}. \\ +\textbf{Input}. An mp\_int $a$ and $b$. \\ +\textbf{Output}. Store a copy of $a$ in $b$. \\ +\hline \\ +1. If $b.alloc < a.used$ then grow $b$ to $a.used$ digits. (\textit{mp\_grow}) \\ +2. for $n$ from 0 to $a.used - 1$ do \\ +\hspace{3mm}2.1 $b_{n} \leftarrow a_{n}$ \\ +3. for $n$ from $a.used$ to $b.used - 1$ do \\ +\hspace{3mm}3.1 $b_{n} \leftarrow 0$ \\ +4. $b.used \leftarrow a.used$ \\ +5. $b.sign \leftarrow a.sign$ \\ +6. return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_copy} +\end{figure} + +\textbf{Algorithm mp\_copy.} +This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will +represent the same integer as the mp\_int $a$. The mp\_int $b$ shall be a complete and distinct copy of the +mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$. + +If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow +algorithm. The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two +and three). The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of +$b$. + +\textbf{Remark.} This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the +text. The error return codes of other algorithms are not explicitly checked in the pseudo-code presented. For example, in +step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded. Text space is +limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return +the error code itself. However, the C code presented will demonstrate all of the error handling logic required to +implement the pseudo-code. + +EXAM,bn_mp_copy.c + +Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output +mp\_int structures passed to a function are one and the same. For this case it is optimal to return immediately without +copying digits (line @24,a == b@). + +The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$. If $b.alloc$ is less than +$a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines @29,alloc@ to @33,}@). In order to +simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits +of the mp\_ints $a$ and $b$ respectively. These aliases (lines @42,tmpa@ and @45,tmpb@) allow the compiler to access the digits without first dereferencing the +mp\_int pointers and then subsequently the pointer to the digits. + +After the aliases are established the digits from $a$ are copied into $b$ (lines @48,for@ to @50,}@) and then the excess +digits of $b$ are set to zero (lines @53,for@ to @55,}@). Both ``for'' loops make use of the pointer aliases and in +fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits. This optimization +allows the alias to stay in a machine register fairly easy between the two loops. + +\textbf{Remarks.} The use of pointer aliases is an implementation methodology first introduced in this function that will +be used considerably in other functions. Technically, a pointer alias is simply a short hand alias used to lower the +number of pointer dereferencing operations required to access data. For example, a for loop may resemble + +\begin{alltt} +for (x = 0; x < 100; x++) \{ + a->num[4]->dp[x] = 0; +\} +\end{alltt} + +This could be re-written using aliases as + +\begin{alltt} +mp_digit *tmpa; +a = a->num[4]->dp; +for (x = 0; x < 100; x++) \{ + *a++ = 0; +\} +\end{alltt} + +In this case an alias is used to access the +array of digits within an mp\_int structure directly. It may seem that a pointer alias is strictly not required +as a compiler may optimize out the redundant pointer operations. However, there are two dominant reasons to use aliases. + +The first reason is that most compilers will not effectively optimize pointer arithmetic. For example, some optimizations +may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC). Also some optimizations may +work for GCC and not MSVC. As such it is ideal to find a common ground for as many compilers as possible. Pointer +aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code +stands a better chance of being faster. + +The second reason is that pointer aliases often can make an algorithm simpler to read. Consider the first ``for'' +loop of the function mp\_copy() re-written to not use pointer aliases. + +\begin{alltt} + /* copy all the digits */ + for (n = 0; n < a->used; n++) \{ + b->dp[n] = a->dp[n]; + \} +\end{alltt} + +Whether this code is harder to read depends strongly on the individual. However, it is quantifiably slightly more +complicated as there are four variables within the statement instead of just two. + +\subsubsection{Nested Statements} +Another commonly used technique in the source routines is that certain sections of code are nested. This is used in +particular with the pointer aliases to highlight code phases. For example, a Comba multiplier (discussed in chapter six) +will typically have three different phases. First the temporaries are initialized, then the columns calculated and +finally the carries are propagated. In this example the middle column production phase will typically be nested as it +uses temporary variables and aliases the most. + +The nesting also simplies the source code as variables that are nested are only valid for their scope. As a result +the various temporary variables required do not propagate into other sections of code. + + +\subsection{Creating a Clone} +Another common operation is to make a local temporary copy of an mp\_int argument. To initialize an mp\_int +and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone. This is +useful within functions that need to modify an argument but do not wish to actually modify the original copy. The +mp\_init\_copy algorithm has been designed to help perform this task. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_init\_copy}. \\ +\textbf{Input}. An mp\_int $a$ and $b$\\ +\textbf{Output}. $a$ is initialized to be a copy of $b$. \\ +\hline \\ +1. Init $a$. (\textit{mp\_init}) \\ +2. Copy $b$ to $a$. (\textit{mp\_copy}) \\ +3. Return the status of the copy operation. \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_init\_copy} +\end{figure} + +\textbf{Algorithm mp\_init\_copy.} +This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it. As +such this algorithm will perform two operations in one step. + +EXAM,bn_mp_init_copy.c + +This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}. Note that +\textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call +and \textbf{a} will be left intact. + +\section{Zeroing an Integer} +Reseting an mp\_int to the default state is a common step in many algorithms. The mp\_zero algorithm will be the algorithm used to +perform this task. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_zero}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. Zero the contents of $a$ \\ +\hline \\ +1. $a.used \leftarrow 0$ \\ +2. $a.sign \leftarrow$ MP\_ZPOS \\ +3. for $n$ from 0 to $a.alloc - 1$ do \\ +\hspace{3mm}3.1 $a_n \leftarrow 0$ \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_zero} +\end{figure} + +\textbf{Algorithm mp\_zero.} +This algorithm simply resets a mp\_int to the default state. + +EXAM,bn_mp_zero.c + +After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the +\textbf{sign} variable is set to \textbf{MP\_ZPOS}. + +\section{Sign Manipulation} +\subsection{Absolute Value} +With the mp\_int representation of an integer, calculating the absolute value is trivial. The mp\_abs algorithm will compute +the absolute value of an mp\_int. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_abs}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. Computes $b = \vert a \vert$ \\ +\hline \\ +1. Copy $a$ to $b$. (\textit{mp\_copy}) \\ +2. If the copy failed return(\textit{MP\_MEM}). \\ +3. $b.sign \leftarrow MP\_ZPOS$ \\ +4. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_abs} +\end{figure} + +\textbf{Algorithm mp\_abs.} +This algorithm computes the absolute of an mp\_int input. First it copies $a$ over $b$. This is an example of an +algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful. This allows, +for instance, the developer to pass the same mp\_int as the source and destination to this function without addition +logic to handle it. + +EXAM,bn_mp_abs.c + +This fairly trivial algorithm first eliminates non--required duplications (line @27,a != b@) and then sets the +\textbf{sign} flag to \textbf{MP\_ZPOS}. + +\subsection{Integer Negation} +With the mp\_int representation of an integer, calculating the negation is also trivial. The mp\_neg algorithm will compute +the negative of an mp\_int input. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_neg}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. Computes $b = -a$ \\ +\hline \\ +1. Copy $a$ to $b$. (\textit{mp\_copy}) \\ +2. If the copy failed return(\textit{MP\_MEM}). \\ +3. If $a.used = 0$ then return(\textit{MP\_OKAY}). \\ +4. If $a.sign = MP\_ZPOS$ then do \\ +\hspace{3mm}4.1 $b.sign = MP\_NEG$. \\ +5. else do \\ +\hspace{3mm}5.1 $b.sign = MP\_ZPOS$. \\ +6. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_neg} +\end{figure} + +\textbf{Algorithm mp\_neg.} +This algorithm computes the negation of an input. First it copies $a$ over $b$. If $a$ has no used digits then +the algorithm returns immediately. Otherwise it flips the sign flag and stores the result in $b$. Note that if +$a$ had no digits then it must be positive by definition. Had step three been omitted then the algorithm would return +zero as negative. + +EXAM,bn_mp_neg.c + +Like mp\_abs() this function avoids non--required duplications (line @21,a != b@) and then sets the sign. We +have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}. If the mp\_int is zero +than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}. + +\section{Small Constants} +\subsection{Setting Small Constants} +Often a mp\_int must be set to a relatively small value such as $1$ or $2$. For these cases the mp\_set algorithm is useful. + +\newpage\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_set}. \\ +\textbf{Input}. An mp\_int $a$ and a digit $b$ \\ +\textbf{Output}. Make $a$ equivalent to $b$ \\ +\hline \\ +1. Zero $a$ (\textit{mp\_zero}). \\ +2. $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\ +3. $a.used \leftarrow \left \lbrace \begin{array}{ll} + 1 & \mbox{if }a_0 > 0 \\ + 0 & \mbox{if }a_0 = 0 + \end{array} \right .$ \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_set} +\end{figure} + +\textbf{Algorithm mp\_set.} +This algorithm sets a mp\_int to a small single digit value. Step number 1 ensures that the integer is reset to the default state. The +single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly. + +EXAM,bn_mp_set.c + +First we zero (line @21,mp_zero@) the mp\_int to make sure that the other members are initialized for a +small positive constant. mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count +is zero. Next we set the digit and reduce it modulo $\beta$ (line @22,MP_MASK@). After this step we have to +check if the resulting digit is zero or not. If it is not then we set the \textbf{used} count to one, otherwise +to zero. + +We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with +$2^k - 1$ will perform the same operation. + +One important limitation of this function is that it will only set one digit. The size of a digit is not fixed, meaning source that uses +this function should take that into account. Only trivially small constants can be set using this function. + +\subsection{Setting Large Constants} +To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal. It accepts a ``long'' +data type as input and will always treat it as a 32-bit integer. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_set\_int}. \\ +\textbf{Input}. An mp\_int $a$ and a ``long'' integer $b$ \\ +\textbf{Output}. Make $a$ equivalent to $b$ \\ +\hline \\ +1. Zero $a$ (\textit{mp\_zero}) \\ +2. for $n$ from 0 to 7 do \\ +\hspace{3mm}2.1 $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\ +\hspace{3mm}2.2 $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\ +\hspace{3mm}2.3 $a_0 \leftarrow a_0 + u$ \\ +\hspace{3mm}2.4 $a.used \leftarrow a.used + 1$ \\ +3. Clamp excess used digits (\textit{mp\_clamp}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_set\_int} +\end{figure} + +\textbf{Algorithm mp\_set\_int.} +The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the +mp\_int. Step 2.1 will multiply the current result by sixteen making room for four more bits in the less significant positions. In step 2.2 the +next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is +incremented to reflect the addition. The \textbf{used} digit counter is incremented since if any of the leading digits were zero the mp\_int would have +zero digits used and the newly added four bits would be ignored. + +Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp. + +EXAM,bn_mp_set_int.c + +This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes. The weird +addition on line @38,a->used@ ensures that the newly added in bits are added to the number of digits. While it may not +seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line @27,mp_mul_2d@ +as well as the call to mp\_clamp() on line @40,mp_clamp@. Both functions will clamp excess leading digits which keeps +the number of used digits low. + +\section{Comparisons} +\subsection{Unsigned Comparisions} +Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers. For example, +to compare $1,234$ to $1,264$ the digits are extracted by their positions. That is we compare $1 \cdot 10^3 + 2 \cdot 10^2 + 3 \cdot 10^1 + 4 \cdot 10^0$ +to $1 \cdot 10^3 + 2 \cdot 10^2 + 6 \cdot 10^1 + 4 \cdot 10^0$ by comparing single digits at a time starting with the highest magnitude +positions. If any leading digit of one integer is greater than a digit in the same position of another integer then obviously it must be greater. + +The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two +mp\_int variables alone. It will ignore the sign of the two inputs. Such a function is useful when an absolute comparison is required or if the +signs are known to agree in advance. + +To facilitate working with the results of the comparison functions three constants are required. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{|r|l|} +\hline \textbf{Constant} & \textbf{Meaning} \\ +\hline \textbf{MP\_GT} & Greater Than \\ +\hline \textbf{MP\_EQ} & Equal To \\ +\hline \textbf{MP\_LT} & Less Than \\ +\hline +\end{tabular} +\end{center} +\caption{Comparison Return Codes} +\end{figure} + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_cmp\_mag}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$. \\ +\textbf{Output}. Unsigned comparison results ($a$ to the left of $b$). \\ +\hline \\ +1. If $a.used > b.used$ then return(\textit{MP\_GT}) \\ +2. If $a.used < b.used$ then return(\textit{MP\_LT}) \\ +3. for n from $a.used - 1$ to 0 do \\ +\hspace{+3mm}3.1 if $a_n > b_n$ then return(\textit{MP\_GT}) \\ +\hspace{+3mm}3.2 if $a_n < b_n$ then return(\textit{MP\_LT}) \\ +4. Return(\textit{MP\_EQ}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_cmp\_mag} +\end{figure} + +\textbf{Algorithm mp\_cmp\_mag.} +By saying ``$a$ to the left of $b$'' it is meant that the comparison is with respect to $a$, that is if $a$ is greater than $b$ it will return +\textbf{MP\_GT} and similar with respect to when $a = b$ and $a < b$. The first two steps compare the number of digits used in both $a$ and $b$. +Obviously if the digit counts differ there would be an imaginary zero digit in the smaller number where the leading digit of the larger number is. +If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit. + +By step three both inputs must have the same number of digits so its safe to start from either $a.used - 1$ or $b.used - 1$ and count down to +the zero'th digit. If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}. + +EXAM,bn_mp_cmp_mag.c + +The two if statements (lines @24,if@ and @28,if@) compare the number of digits in the two inputs. These two are +performed before all of the digits are compared since it is a very cheap test to perform and can potentially save +considerable time. The implementation given is also not valid without those two statements. $b.alloc$ may be +smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits. + + + +\subsection{Signed Comparisons} +Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}). Based on an unsigned magnitude +comparison a trivial signed comparison algorithm can be written. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_cmp}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$ \\ +\textbf{Output}. Signed Comparison Results ($a$ to the left of $b$) \\ +\hline \\ +1. if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\ +2. if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\ +3. if $a.sign = MP\_NEG$ then \\ +\hspace{+3mm}3.1 Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\ +4 Otherwise \\ +\hspace{+3mm}4.1 Return the unsigned comparison of $a$ and $b$ \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_cmp} +\end{figure} + +\textbf{Algorithm mp\_cmp.} +The first two steps compare the signs of the two inputs. If the signs do not agree then it can return right away with the appropriate +comparison code. When the signs are equal the digits of the inputs must be compared to determine the correct result. In step +three the unsigned comparision flips the order of the arguments since they are both negative. For instance, if $-a > -b$ then +$\vert a \vert < \vert b \vert$. Step number four will compare the two when they are both positive. + +EXAM,bn_mp_cmp.c + +The two if statements (lines @22,if@ and @26,if@) perform the initial sign comparison. If the signs are not the equal then which ever +has the positive sign is larger. The inputs are compared (line @30,if@) based on magnitudes. If the signs were both +negative then the unsigned comparison is performed in the opposite direction (line @31,mp_cmp_mag@). Otherwise, the signs are assumed to +be both positive and a forward direction unsigned comparison is performed. + +\section*{Exercises} +\begin{tabular}{cl} +$\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\ + & \\ +$\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits \\ + & of two random digits (of equal magnitude) before a difference is found. \\ + & \\ +$\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based \\ + & on the observations made in the previous problem. \\ + & +\end{tabular} + +\chapter{Basic Arithmetic} +\section{Introduction} +At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been +established. The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms. These +algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms. It is very important +that these algorithms are highly optimized. On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms +which easily places them at $O(n^2)$ or even $O(n^3)$ work levels. + +MARK,SHIFTS +All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right +logical shifts respectively. A logical shift is analogous to sliding the decimal point of radix-10 representations. For example, the real +number $0.9345$ is equivalent to $93.45\%$ which is found by sliding the the decimal two places to the right (\textit{multiplying by $\beta^2 = 10^2$}). +Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two. +For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$. + +One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed +from the number. For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$. However, with a logical shift the +result is $110_2$. + +\section{Addition and Subtraction} +In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus. For example, with 32-bit integers +$a - b\mbox{ (mod }2^{32}\mbox{)}$ is the same as $a + (2^{32} - b) \mbox{ (mod }2^{32}\mbox{)}$ since $2^{32} \equiv 0 \mbox{ (mod }2^{32}\mbox{)}$. +As a result subtraction can be performed with a trivial series of logical operations and an addition. + +However, in multiple precision arithmetic negative numbers are not represented in the same way. Instead a sign flag is used to keep track of the +sign of the integer. As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or +subtraction algorithms with the sign fixed up appropriately. + +The lower level algorithms will add or subtract integers without regard to the sign flag. That is they will add or subtract the magnitude of +the integers respectively. + +\subsection{Low Level Addition} +An unsigned addition of multiple precision integers is performed with the same long-hand algorithm used to add decimal numbers. That is to add the +trailing digits first and propagate the resulting carry upwards. Since this is a lower level algorithm the name will have a ``s\_'' prefix. +Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely. + +\newpage +\begin{figure}[!here] +\begin{center} +\begin{small} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_add}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$ \\ +\textbf{Output}. The unsigned addition $c = \vert a \vert + \vert b \vert$. \\ +\hline \\ +1. if $a.used > b.used$ then \\ +\hspace{+3mm}1.1 $min \leftarrow b.used$ \\ +\hspace{+3mm}1.2 $max \leftarrow a.used$ \\ +\hspace{+3mm}1.3 $x \leftarrow a$ \\ +2. else \\ +\hspace{+3mm}2.1 $min \leftarrow a.used$ \\ +\hspace{+3mm}2.2 $max \leftarrow b.used$ \\ +\hspace{+3mm}2.3 $x \leftarrow b$ \\ +3. If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\ +4. $oldused \leftarrow c.used$ \\ +5. $c.used \leftarrow max + 1$ \\ +6. $u \leftarrow 0$ \\ +7. for $n$ from $0$ to $min - 1$ do \\ +\hspace{+3mm}7.1 $c_n \leftarrow a_n + b_n + u$ \\ +\hspace{+3mm}7.2 $u \leftarrow c_n >> lg(\beta)$ \\ +\hspace{+3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ +8. if $min \ne max$ then do \\ +\hspace{+3mm}8.1 for $n$ from $min$ to $max - 1$ do \\ +\hspace{+6mm}8.1.1 $c_n \leftarrow x_n + u$ \\ +\hspace{+6mm}8.1.2 $u \leftarrow c_n >> lg(\beta)$ \\ +\hspace{+6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ +9. $c_{max} \leftarrow u$ \\ +10. if $olduse > max$ then \\ +\hspace{+3mm}10.1 for $n$ from $max + 1$ to $oldused - 1$ do \\ +\hspace{+6mm}10.1.1 $c_n \leftarrow 0$ \\ +11. Clamp excess digits in $c$. (\textit{mp\_clamp}) \\ +12. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Algorithm s\_mp\_add} +\end{figure} + +\textbf{Algorithm s\_mp\_add.} +This algorithm is loosely based on algorithm 14.7 of HAC \cite[pp. 594]{HAC} but has been extended to allow the inputs to have different magnitudes. +Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}. Even the +MIX pseudo machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes. + +The first thing that has to be accomplished is to sort out which of the two inputs is the largest. The addition logic +will simply add all of the smallest input to the largest input and store that first part of the result in the +destination. Then it will apply a simpler addition loop to excess digits of the larger input. + +The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two +inputs. The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the +same number of digits. After the inputs are sorted the destination $c$ is grown as required to accomodate the sum +of the two inputs. The original \textbf{used} count of $c$ is copied and set to the new used count. + +At this point the first addition loop will go through as many digit positions that both inputs have. The carry +variable $\mu$ is set to zero outside the loop. Inside the loop an ``addition'' step requires three statements to produce +one digit of the summand. First +two digits from $a$ and $b$ are added together along with the carry $\mu$. The carry of this step is extracted and stored +in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$. + +Now all of the digit positions that both inputs have in common have been exhausted. If $min \ne max$ then $x$ is an alias +for one of the inputs that has more digits. A simplified addition loop is then used to essentially copy the remaining digits +and the carry to the destination. + +The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition. + + +EXAM,bn_s_mp_add.c + +We first sort (lines @27,if@ to @35,}@) the inputs based on magnitude and determine the $min$ and $max$ variables. +Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias. Next we +grow the destination (@37,init@ to @42,}@) ensure that it can accomodate the result of the addition. + +Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style. The three aliases that are on +lines @56,tmpa@, @59,tmpb@ and @62,tmpc@ represent the two inputs and destination variables respectively. These aliases are used to ensure the +compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int. + +The initial carry $u$ will be cleared (line @65,u = 0@), note that $u$ is of type mp\_digit which ensures type +compatibility within the implementation. The initial addition (line @66,for@ to @75,}@) adds digits from +both inputs until the smallest input runs out of digits. Similarly the conditional addition loop +(line @81,for@ to @90,}@) adds the remaining digits from the larger of the two inputs. The addition is finished +with the final carry being stored in $tmpc$ (line @94,tmpc++@). Note the ``++'' operator within the same expression. +After line @94,tmpc++@, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$. This is useful +for the next loop (line @97,for@ to @99,}@) which set any old upper digits to zero. + +\subsection{Low Level Subtraction} +The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm. The principle difference is that the +unsigned subtraction algorithm requires the result to be positive. That is when computing $a - b$ the condition $\vert a \vert \ge \vert b\vert$ must +be met for this algorithm to function properly. Keep in mind this low level algorithm is not meant to be used in higher level algorithms directly. +This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms. + +MARK,GAMMA + +For this algorithm a new variable is required to make the description simpler. Recall from section 1.3.1 that a mp\_digit must be able to represent +the range $0 \le x < 2\beta$ for the algorithms to work correctly. However, it is allowable that a mp\_digit represent a larger range of values. For +this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a +mp\_digit (\textit{this implies $2^{\gamma} > \beta$}). + +For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$. In ISO C an ``unsigned long'' +data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$. + +\newpage\begin{figure}[!here] +\begin{center} +\begin{small} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_sub}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\ +\textbf{Output}. The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\ +\hline \\ +1. $min \leftarrow b.used$ \\ +2. $max \leftarrow a.used$ \\ +3. If $c.alloc < max$ then grow $c$ to hold at least $max$ digits. (\textit{mp\_grow}) \\ +4. $oldused \leftarrow c.used$ \\ +5. $c.used \leftarrow max$ \\ +6. $u \leftarrow 0$ \\ +7. for $n$ from $0$ to $min - 1$ do \\ +\hspace{3mm}7.1 $c_n \leftarrow a_n - b_n - u$ \\ +\hspace{3mm}7.2 $u \leftarrow c_n >> (\gamma - 1)$ \\ +\hspace{3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ +8. if $min < max$ then do \\ +\hspace{3mm}8.1 for $n$ from $min$ to $max - 1$ do \\ +\hspace{6mm}8.1.1 $c_n \leftarrow a_n - u$ \\ +\hspace{6mm}8.1.2 $u \leftarrow c_n >> (\gamma - 1)$ \\ +\hspace{6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ +9. if $oldused > max$ then do \\ +\hspace{3mm}9.1 for $n$ from $max$ to $oldused - 1$ do \\ +\hspace{6mm}9.1.1 $c_n \leftarrow 0$ \\ +10. Clamp excess digits of $c$. (\textit{mp\_clamp}). \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Algorithm s\_mp\_sub} +\end{figure} + +\textbf{Algorithm s\_mp\_sub.} +This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive. That is when +passing variables $a$ and $b$ the condition that $\vert a \vert \ge \vert b \vert$ must be met for the algorithm to function correctly. This +algorithm is loosely based on algorithm 14.9 \cite[pp. 595]{HAC} and is similar to algorithm S in \cite[pp. 267]{TAOCPV2} as well. As was the case +of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude. + +The initial sorting of the inputs is trivial in this algorithm since $a$ is guaranteed to have at least the same magnitude of $b$. Steps 1 and 2 +set the $min$ and $max$ variables. Unlike the addition routine there is guaranteed to be no carry which means that the final result can be at +most $max$ digits in length as opposed to $max + 1$. Similar to the addition algorithm the \textbf{used} count of $c$ is copied locally and +set to the maximal count for the operation. + +The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision +subtraction is used instead. Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction +loops. Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry. + +For example, consider subtracting $0101_2$ from $0100_2$ where $\gamma = 4$ and $\beta = 2$. The least significant bit will force a carry upwards to +the third bit which will be set to zero after the borrow. After the very first bit has been subtracted $4 - 1 \equiv 0011_2$ will remain, When the +third bit of $0101_2$ is subtracted from the result it will cause another carry. In this case though the carry will be forced to propagate all the +way to the most significant bit. + +Recall that $\beta < 2^{\gamma}$. This means that if a carry does occur just before the $lg(\beta)$'th bit it will propagate all the way to the most +significant bit. Thus, the high order bits of the mp\_digit that are not part of the actual digit will either be all zero, or all one. All that +is needed is a single zero or one bit for the carry. Therefore a single logical shift right by $\gamma - 1$ positions is sufficient to extract the +carry. This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed. + +If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and copy operation to propagate through the larger input $a$ into $c$. Step +10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed. + +EXAM,bn_s_mp_sub.c + +Like low level addition we ``sort'' the inputs. Except in this case the sorting is hardcoded +(lines @24,min@ and @25,max@). In reality the $min$ and $max$ variables are only aliases and are only +used to make the source code easier to read. Again the pointer alias optimization is used +within this algorithm. The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized +(lines @42,tmpa@, @43,tmpb@ and @44,tmpc@) for $a$, $b$ and $c$ respectively. + +The first subtraction loop (lines @47,u = 0@ through @61,}@) subtract digits from both inputs until the smaller of +the two inputs has been exhausted. As remarked earlier there is an implementation reason for using the ``awkward'' +method of extracting the carry (line @57, >>@). The traditional method for extracting the carry would be to shift +by $lg(\beta)$ positions and logically AND the least significant bit. The AND operation is required because all of +the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction. This carry +extraction requires two relatively cheap operations to extract the carry. The other method is to simply shift the +most significant bit to the least significant bit thus extracting the carry with a single cheap operation. This +optimization only works on twos compliment machines which is a safe assumption to make. + +If $a$ has a larger magnitude than $b$ an additional loop (lines @64,for@ through @73,}@) is required to propagate +the carry through $a$ and copy the result to $c$. + +\subsection{High Level Addition} +Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be +established. This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data +types. + +Recall from section 5.2 that an mp\_int represents an integer with an unsigned mantissa (\textit{the array of digits}) and a \textbf{sign} +flag. A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases. + +\begin{figure}[!here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_add}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$ \\ +\textbf{Output}. The signed addition $c = a + b$. \\ +\hline \\ +1. if $a.sign = b.sign$ then do \\ +\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\ +\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\ +2. else do \\ +\hspace{3mm}2.1 if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\ +\hspace{6mm}2.1.1 $c.sign \leftarrow b.sign$ \\ +\hspace{6mm}2.1.2 $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\ +\hspace{3mm}2.2 else do \\ +\hspace{6mm}2.2.1 $c.sign \leftarrow a.sign$ \\ +\hspace{6mm}2.2.2 $c \leftarrow \vert a \vert - \vert b \vert$ \\ +3. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_add} +\end{figure} + +\textbf{Algorithm mp\_add.} +This algorithm performs the signed addition of two mp\_int variables. There is no reference algorithm to draw upon from +either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations. The algorithm is fairly +straightforward but restricted since subtraction can only produce positive results. + +\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{|c|c|c|c|c|} +\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\ +\hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\ +\hline $+$ & $+$ & No & $c = a + b$ & $a.sign$ \\ +\hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\ +\hline $-$ & $-$ & No & $c = a + b$ & $a.sign$ \\ +\hline &&&&\\ + +\hline $+$ & $-$ & No & $c = b - a$ & $b.sign$ \\ +\hline $-$ & $+$ & No & $c = b - a$ & $b.sign$ \\ + +\hline &&&&\\ + +\hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\ +\hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\ + +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Addition Guide Chart} +\label{fig:AddChart} +\end{figure} + +Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three +specific cases need to be handled. The return code of the unsigned operations at step 1.2, 2.1.2 and 2.2.2 are +forwarded to step three to check for errors. This simplifies the description of the algorithm considerably and best +follows how the implementation actually was achieved. + +Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed. Recall from the descriptions of algorithms +s\_mp\_add and s\_mp\_sub that the mp\_clamp function is used at the end to trim excess digits. The mp\_clamp algorithm will set the \textbf{sign} +to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero. + +For example, consider performing $-a + a$ with algorithm mp\_add. By the description of the algorithm the sign is set to \textbf{MP\_NEG} which would +produce a result of $-0$. However, since the sign is set first then the unsigned addition is performed the subsequent usage of algorithm mp\_clamp +within algorithm s\_mp\_add will force $-0$ to become $0$. + +EXAM,bn_mp_add.c + +The source code follows the algorithm fairly closely. The most notable new source code addition is the usage of the $res$ integer variable which +is used to pass result of the unsigned operations forward. Unlike in the algorithm, the variable $res$ is merely returned as is without +explicitly checking it and returning the constant \textbf{MP\_OKAY}. The observation is this algorithm will succeed or fail only if the lower +level functions do so. Returning their return code is sufficient. + +\subsection{High Level Subtraction} +The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm. + +\newpage\begin{figure}[!here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_sub}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$ \\ +\textbf{Output}. The signed subtraction $c = a - b$. \\ +\hline \\ +1. if $a.sign \ne b.sign$ then do \\ +\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\ +\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\ +2. else do \\ +\hspace{3mm}2.1 if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\ +\hspace{6mm}2.1.1 $c.sign \leftarrow a.sign$ \\ +\hspace{6mm}2.1.2 $c \leftarrow \vert a \vert - \vert b \vert$ (\textit{s\_mp\_sub}) \\ +\hspace{3mm}2.2 else do \\ +\hspace{6mm}2.2.1 $c.sign \leftarrow \left \lbrace \begin{array}{ll} + MP\_ZPOS & \mbox{if }a.sign = MP\_NEG \\ + MP\_NEG & \mbox{otherwise} \\ + \end{array} \right .$ \\ +\hspace{6mm}2.2.2 $c \leftarrow \vert b \vert - \vert a \vert$ \\ +3. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_sub} +\end{figure} + +\textbf{Algorithm mp\_sub.} +This algorithm performs the signed subtraction of two inputs. Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or +\cite{HAC}. Also this algorithm is restricted by algorithm s\_mp\_sub. Chart \ref{fig:SubChart} lists the eight possible inputs and +the operations required. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{|c|c|c|c|c|} +\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\ +\hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\ +\hline $+$ & $-$ & No & $c = a + b$ & $a.sign$ \\ +\hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\ +\hline $-$ & $+$ & No & $c = a + b$ & $a.sign$ \\ +\hline &&&& \\ +\hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\ +\hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\ +\hline &&&& \\ +\hline $+$ & $+$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\ +\hline $-$ & $-$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Subtraction Guide Chart} +\label{fig:SubChart} +\end{figure} + +Similar to the case of algorithm mp\_add the \textbf{sign} is set first before the unsigned addition or subtraction. That is to prevent the +algorithm from producing $-a - -a = -0$ as a result. + +EXAM,bn_mp_sub.c + +Much like the implementation of algorithm mp\_add the variable $res$ is used to catch the return code of the unsigned addition or subtraction operations +and forward it to the end of the function. On line @38, != MP_LT@ the ``not equal to'' \textbf{MP\_LT} expression is used to emulate a +``greater than or equal to'' comparison. + +\section{Bit and Digit Shifting} +MARK,POLY +It is quite common to think of a multiple precision integer as a polynomial in $x$, that is $y = f(\beta)$ where $f(x) = \sum_{i=0}^{n-1} a_i x^i$. +This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring. + +In order to facilitate operations on polynomials in $x$ as above a series of simple ``digit'' algorithms have to be established. That is to shift +the digits left or right as well to shift individual bits of the digits left and right. It is important to note that not all ``shift'' operations +are on radix-$\beta$ digits. + +\subsection{Multiplication by Two} + +In a binary system where the radix is a power of two multiplication by two not only arises often in other algorithms it is a fairly efficient +operation to perform. A single precision logical shift left is sufficient to multiply a single digit by two. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_mul\_2}. \\ +\textbf{Input}. One mp\_int $a$ \\ +\textbf{Output}. $b = 2a$. \\ +\hline \\ +1. If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits. (\textit{mp\_grow}) \\ +2. $oldused \leftarrow b.used$ \\ +3. $b.used \leftarrow a.used$ \\ +4. $r \leftarrow 0$ \\ +5. for $n$ from 0 to $a.used - 1$ do \\ +\hspace{3mm}5.1 $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\ +\hspace{3mm}5.2 $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}5.3 $r \leftarrow rr$ \\ +6. If $r \ne 0$ then do \\ +\hspace{3mm}6.1 $b_{n + 1} \leftarrow r$ \\ +\hspace{3mm}6.2 $b.used \leftarrow b.used + 1$ \\ +7. If $b.used < oldused - 1$ then do \\ +\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\ +\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\ +8. $b.sign \leftarrow a.sign$ \\ +9. Return(\textit{MP\_OKAY}).\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_mul\_2} +\end{figure} + +\textbf{Algorithm mp\_mul\_2.} +This algorithm will quickly multiply a mp\_int by two provided $\beta$ is a power of two. Neither \cite{TAOCPV2} nor \cite{HAC} describe such +an algorithm despite the fact it arises often in other algorithms. The algorithm is setup much like the lower level algorithm s\_mp\_add since +it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$. + +Step 1 and 2 grow the input as required to accomodate the maximum number of \textbf{used} digits in the result. The initial \textbf{used} count +is set to $a.used$ at step 4. Only if there is a final carry will the \textbf{used} count require adjustment. + +Step 6 is an optimization implementation of the addition loop for this specific case. That is since the two values being added together +are the same there is no need to perform two reads from the digits of $a$. Step 6.1 performs a single precision shift on the current digit $a_n$ to +obtain what will be the carry for the next iteration. Step 6.2 calculates the $n$'th digit of the result as single precision shift of $a_n$ plus +the previous carry. Recall from ~SHIFTS~ that $a_n << 1$ is equivalent to $a_n \cdot 2$. An iteration of the addition loop is finished with +forwarding the carry to the next iteration. + +Step 7 takes care of any final carry by setting the $a.used$'th digit of the result to the carry and augmenting the \textbf{used} count of $b$. +Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$. + +EXAM,bn_mp_mul_2.c + +This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input. The only noteworthy difference +is the use of the logical shift operator on line @52,<<@ to perform a single precision doubling. + +\subsection{Division by Two} +A division by two can just as easily be accomplished with a logical shift right as multiplication by two can be with a logical shift left. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_div\_2}. \\ +\textbf{Input}. One mp\_int $a$ \\ +\textbf{Output}. $b = a/2$. \\ +\hline \\ +1. If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits. (\textit{mp\_grow}) \\ +2. If the reallocation failed return(\textit{MP\_MEM}). \\ +3. $oldused \leftarrow b.used$ \\ +4. $b.used \leftarrow a.used$ \\ +5. $r \leftarrow 0$ \\ +6. for $n$ from $b.used - 1$ to $0$ do \\ +\hspace{3mm}6.1 $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\ +\hspace{3mm}6.2 $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}6.3 $r \leftarrow rr$ \\ +7. If $b.used < oldused - 1$ then do \\ +\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\ +\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\ +8. $b.sign \leftarrow a.sign$ \\ +9. Clamp excess digits of $b$. (\textit{mp\_clamp}) \\ +10. Return(\textit{MP\_OKAY}).\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_div\_2} +\end{figure} + +\textbf{Algorithm mp\_div\_2.} +This algorithm will divide an mp\_int by two using logical shifts to the right. Like mp\_mul\_2 it uses a modified low level addition +core as the basis of the algorithm. Unlike mp\_mul\_2 the shift operations work from the leading digit to the trailing digit. The algorithm +could be written to work from the trailing digit to the leading digit however, it would have to stop one short of $a.used - 1$ digits to prevent +reading past the end of the array of digits. + +Essentially the loop at step 6 is similar to that of mp\_mul\_2 except the logical shifts go in the opposite direction and the carry is at the +least significant bit not the most significant bit. + +EXAM,bn_mp_div_2.c + +\section{Polynomial Basis Operations} +Recall from ~POLY~ that any integer can be represented as a polynomial in $x$ as $y = f(\beta)$. Such a representation is also known as +the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single +place. The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer +division and Karatsuba multiplication. + +Converting from an array of digits to polynomial basis is very simple. Consider the integer $y \equiv (a_2, a_1, a_0)_{\beta}$ and recall that +$y = \sum_{i=0}^{2} a_i \beta^i$. Simply replace $\beta$ with $x$ and the expression is in polynomial basis. For example, $f(x) = 8x + 9$ is the +polynomial basis representation for $89$ using radix ten. That is, $f(10) = 8(10) + 9 = 89$. + +\subsection{Multiplication by $x$} + +Given a polynomial in $x$ such as $f(x) = a_n x^n + a_{n-1} x^{n-1} + ... + a_0$ multiplying by $x$ amounts to shifting the coefficients up one +degree. In this case $f(x) \cdot x = a_n x^{n+1} + a_{n-1} x^n + ... + a_0 x$. From a scalar basis point of view multiplying by $x$ is equivalent to +multiplying by the integer $\beta$. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_lshd}. \\ +\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ +\textbf{Output}. $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\ +\hline \\ +1. If $b \le 0$ then return(\textit{MP\_OKAY}). \\ +2. If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits. (\textit{mp\_grow}). \\ +3. If the reallocation failed return(\textit{MP\_MEM}). \\ +4. $a.used \leftarrow a.used + b$ \\ +5. $i \leftarrow a.used - 1$ \\ +6. $j \leftarrow a.used - 1 - b$ \\ +7. for $n$ from $a.used - 1$ to $b$ do \\ +\hspace{3mm}7.1 $a_{i} \leftarrow a_{j}$ \\ +\hspace{3mm}7.2 $i \leftarrow i - 1$ \\ +\hspace{3mm}7.3 $j \leftarrow j - 1$ \\ +8. for $n$ from 0 to $b - 1$ do \\ +\hspace{3mm}8.1 $a_n \leftarrow 0$ \\ +9. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_lshd} +\end{figure} + +\textbf{Algorithm mp\_lshd.} +This algorithm multiplies an mp\_int by the $b$'th power of $x$. This is equivalent to multiplying by $\beta^b$. The algorithm differs +from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location. The +motivation behind this change is due to the way this function is typically used. Algorithms such as mp\_add store the result in an optionally +different third mp\_int because the original inputs are often still required. Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is +typically used on values where the original value is no longer required. The algorithm will return success immediately if +$b \le 0$ since the rest of algorithm is only valid when $b > 0$. + +First the destination $a$ is grown as required to accomodate the result. The counters $i$ and $j$ are used to form a \textit{sliding window} over +the digits of $a$ of length $b$. The head of the sliding window is at $i$ (\textit{the leading digit}) and the tail at $j$ (\textit{the trailing digit}). +The loop on step 7 copies the digit from the tail to the head. In each iteration the window is moved down one digit. The last loop on +step 8 sets the lower $b$ digits to zero. + +\newpage +FIGU,sliding_window,Sliding Window Movement + +EXAM,bn_mp_lshd.c + +The if statement (line @24,if@) ensures that the $b$ variable is greater than zero since we do not interpret negative +shift counts properly. The \textbf{used} count is incremented by $b$ before the copy loop begins. This elminates +the need for an additional variable in the for loop. The variable $top$ (line @42,top@) is an alias +for the leading digit while $bottom$ (line @45,bottom@) is an alias for the trailing edge. The aliases form a +window of exactly $b$ digits over the input. + +\subsection{Division by $x$} + +Division by powers of $x$ is easily achieved by shifting the digits right and removing any that will end up to the right of the zero'th digit. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_rshd}. \\ +\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ +\textbf{Output}. $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\ +\hline \\ +1. If $b \le 0$ then return. \\ +2. If $a.used \le b$ then do \\ +\hspace{3mm}2.1 Zero $a$. (\textit{mp\_zero}). \\ +\hspace{3mm}2.2 Return. \\ +3. $i \leftarrow 0$ \\ +4. $j \leftarrow b$ \\ +5. for $n$ from 0 to $a.used - b - 1$ do \\ +\hspace{3mm}5.1 $a_i \leftarrow a_j$ \\ +\hspace{3mm}5.2 $i \leftarrow i + 1$ \\ +\hspace{3mm}5.3 $j \leftarrow j + 1$ \\ +6. for $n$ from $a.used - b$ to $a.used - 1$ do \\ +\hspace{3mm}6.1 $a_n \leftarrow 0$ \\ +7. $a.used \leftarrow a.used - b$ \\ +8. Return. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_rshd} +\end{figure} + +\textbf{Algorithm mp\_rshd.} +This algorithm divides the input in place by the $b$'th power of $x$. It is analogous to dividing by a $\beta^b$ but much quicker since +it does not require single precision division. This algorithm does not actually return an error code as it cannot fail. + +If the input $b$ is less than one the algorithm quickly returns without performing any work. If the \textbf{used} count is less than or equal +to the shift count $b$ then it will simply zero the input and return. + +After the trivial cases of inputs have been handled the sliding window is setup. Much like the case of algorithm mp\_lshd a sliding window that +is $b$ digits wide is used to copy the digits. Unlike mp\_lshd the window slides in the opposite direction from the trailing to the leading digit. +Also the digits are copied from the leading to the trailing edge. + +Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented. + +EXAM,bn_mp_rshd.c + +The only noteworthy element of this routine is the lack of a return type since it cannot fail. Like mp\_lshd() we +form a sliding window except we copy in the other direction. After the window (line @59,for (;@) we then zero +the upper digits of the input to make sure the result is correct. + +\section{Powers of Two} + +Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required. For +example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful. Instead of performing single +shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed. + +\subsection{Multiplication by Power of Two} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_mul\_2d}. \\ +\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ +\textbf{Output}. $c \leftarrow a \cdot 2^b$. \\ +\hline \\ +1. $c \leftarrow a$. (\textit{mp\_copy}) \\ +2. If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\ +3. If the reallocation failed return(\textit{MP\_MEM}). \\ +4. If $b \ge lg(\beta)$ then \\ +\hspace{3mm}4.1 $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\ +\hspace{3mm}4.2 If step 4.1 failed return(\textit{MP\_MEM}). \\ +5. $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ +6. If $d \ne 0$ then do \\ +\hspace{3mm}6.1 $mask \leftarrow 2^d$ \\ +\hspace{3mm}6.2 $r \leftarrow 0$ \\ +\hspace{3mm}6.3 for $n$ from $0$ to $c.used - 1$ do \\ +\hspace{6mm}6.3.1 $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\ +\hspace{6mm}6.3.2 $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{6mm}6.3.3 $r \leftarrow rr$ \\ +\hspace{3mm}6.4 If $r > 0$ then do \\ +\hspace{6mm}6.4.1 $c_{c.used} \leftarrow r$ \\ +\hspace{6mm}6.4.2 $c.used \leftarrow c.used + 1$ \\ +7. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_mul\_2d} +\end{figure} + +\textbf{Algorithm mp\_mul\_2d.} +This algorithm multiplies $a$ by $2^b$ and stores the result in $c$. The algorithm uses algorithm mp\_lshd and a derivative of algorithm mp\_mul\_2 to +quickly compute the product. + +First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than +$\beta$. For example, if $b = 37$ and $\beta = 2^{28}$ then this step will multiply by $x$ leaving a multiplication by $2^{37 - 28} = 2^{9}$ +left. + +After the digits have been shifted appropriately at most $lg(\beta) - 1$ shifts are left to perform. Step 5 calculates the number of remaining shifts +required. If it is non-zero a modified shift loop is used to calculate the remaining product. +Essentially the loop is a generic version of algorithm mp\_mul\_2 designed to handle any shift count in the range $1 \le x < lg(\beta)$. The $mask$ +variable is used to extract the upper $d$ bits to form the carry for the next iteration. + +This algorithm is loosely measured as a $O(2n)$ algorithm which means that if the input is $n$-digits that it takes $2n$ ``time'' to +complete. It is possible to optimize this algorithm down to a $O(n)$ algorithm at a cost of making the algorithm slightly harder to follow. + +EXAM,bn_mp_mul_2d.c + +The shifting is performed in--place which means the first step (line @24,a != c@) is to copy the input to the +destination. We avoid calling mp\_copy() by making sure the mp\_ints are different. The destination then +has to be grown (line @31,grow@) to accomodate the result. + +If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples +of $lg(\beta)$. Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left. Inside the actual shift +loop (lines @45,if@ to @76,}@) we make use of pre--computed values $shift$ and $mask$. These are used to +extract the carry bit(s) to pass into the next iteration of the loop. The $r$ and $rr$ variables form a +chain between consecutive iterations to propagate the carry. + +\subsection{Division by Power of Two} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_div\_2d}. \\ +\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ +\textbf{Output}. $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\ +\hline \\ +1. If $b \le 0$ then do \\ +\hspace{3mm}1.1 $c \leftarrow a$ (\textit{mp\_copy}) \\ +\hspace{3mm}1.2 $d \leftarrow 0$ (\textit{mp\_zero}) \\ +\hspace{3mm}1.3 Return(\textit{MP\_OKAY}). \\ +2. $c \leftarrow a$ \\ +3. $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\ +4. If $b \ge lg(\beta)$ then do \\ +\hspace{3mm}4.1 $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\ +5. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ +6. If $k \ne 0$ then do \\ +\hspace{3mm}6.1 $mask \leftarrow 2^k$ \\ +\hspace{3mm}6.2 $r \leftarrow 0$ \\ +\hspace{3mm}6.3 for $n$ from $c.used - 1$ to $0$ do \\ +\hspace{6mm}6.3.1 $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\ +\hspace{6mm}6.3.2 $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\ +\hspace{6mm}6.3.3 $r \leftarrow rr$ \\ +7. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\ +8. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_div\_2d} +\end{figure} + +\textbf{Algorithm mp\_div\_2d.} +This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder. The algorithm is designed much like algorithm +mp\_mul\_2d by first using whole digit shifts then single precision shifts. This algorithm will also produce the remainder of the division +by using algorithm mp\_mod\_2d. + +EXAM,bn_mp_div_2d.c + +The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies. The remainder $d$ may be optionally +ignored by passing \textbf{NULL} as the pointer to the mp\_int variable. The temporary mp\_int variable $t$ is used to hold the +result of the remainder operation until the end. This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before +the quotient is obtained. + +The remainder of the source code is essentially the same as the source code for mp\_mul\_2d. The only significant difference is +the direction of the shifts. + +\subsection{Remainder of Division by Power of Two} + +The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$. This +algorithm benefits from the fact that in twos complement arithmetic $a \mbox{ (mod }2^b\mbox{)}$ is the same as $a$ AND $2^b - 1$. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_mod\_2d}. \\ +\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ +\textbf{Output}. $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\ +\hline \\ +1. If $b \le 0$ then do \\ +\hspace{3mm}1.1 $c \leftarrow 0$ (\textit{mp\_zero}) \\ +\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ +2. If $b > a.used \cdot lg(\beta)$ then do \\ +\hspace{3mm}2.1 $c \leftarrow a$ (\textit{mp\_copy}) \\ +\hspace{3mm}2.2 Return the result of step 2.1. \\ +3. $c \leftarrow a$ \\ +4. If step 3 failed return(\textit{MP\_MEM}). \\ +5. for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\ +\hspace{3mm}5.1 $c_n \leftarrow 0$ \\ +6. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ +7. $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\ +8. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\ +9. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_mod\_2d} +\end{figure} + +\textbf{Algorithm mp\_mod\_2d.} +This algorithm will quickly calculate the value of $a \mbox{ (mod }2^b\mbox{)}$. First if $b$ is less than or equal to zero the +result is set to zero. If $b$ is greater than the number of bits in $a$ then it simply copies $a$ to $c$ and returns. Otherwise, $a$ +is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count. + +EXAM,bn_mp_mod_2d.c + +We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases. Next if $2^b$ is larger +than the input we just mp\_copy() the input and return right away. After this point we know we must actually +perform some work to produce the remainder. + +Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce +the number. First we zero any digits above the last digit in $2^b$ (line @41,for@). Next we reduce the +leading digit of both (line @45,&=@) and then mp\_clamp(). + +\section*{Exercises} +\begin{tabular}{cl} +$\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\ + & in $O(n)$ time. \\ + &\\ +$\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming \\ + & weight values such as $3$, $5$ and $9$. Extend it to handle all values \\ + & upto $64$ with a hamming weight less than three. \\ + &\\ +$\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\ + & $2^k - 1$ as well. \\ + &\\ +$\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\ + & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\ + & any $n$-bit input. Note that the time of addition is ignored in the \\ + & calculation. \\ + & \\ +$\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\ + & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$. Again ignore \\ + & the cost of addition. \\ + & \\ +$\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\ + & for $n = 64 \ldots 1024$ in steps of $64$. \\ + & \\ +$\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\ + & calculating the result of a signed comparison. \\ + & +\end{tabular} + +\chapter{Multiplication and Squaring} +\section{The Multipliers} +For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of +algorithms of any multiple precision integer package. The set of multiplier algorithms include integer multiplication, squaring and modular reduction +where in each of the algorithms single precision multiplication is the dominant operation performed. This chapter will discuss integer multiplication +and squaring, leaving modular reductions for the subsequent chapter. + +The importance of the multiplier algorithms is for the most part driven by the fact that certain popular public key algorithms are based on modular +exponentiation, that is computing $d \equiv a^b \mbox{ (mod }c\mbox{)}$ for some arbitrary choice of $a$, $b$, $c$ and $d$. During a modular +exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions, +35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision +multiplications. + +For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied +against every digit of the other multiplicand. Traditional long-hand multiplication is based on this process; while the techniques can differ the +overall algorithm used is essentially the same. Only ``recently'' have faster algorithms been studied. First Karatsuba multiplication was discovered in +1962. This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach. +This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions. + +\section{Multiplication} +\subsection{The Baseline Multiplication} +\label{sec:basemult} +\index{baseline multiplication} +Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication +algorithm that school children are taught. The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision +multiplications are required. More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required. To +simplify most discussions, it will be assumed that the inputs have comparable number of digits. + +The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be +used. This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible. One important +facet of this algorithm, is that it has been modified to only produce a certain amount of output digits as resolution. The importance of this +modification will become evident during the discussion of Barrett modular reduction. Recall that for a $n$ and $m$ digit input the product +will be at most $n + m$ digits. Therefore, this algorithm can be reduced to a full multiplier by having it produce $n + m$ digits of the product. + +Recall from ~GAMMA~ the definition of $\gamma$ as the number of bits in the type \textbf{mp\_digit}. We shall now extend the variable set to +include $\alpha$ which shall represent the number of bits in the type \textbf{mp\_word}. This implies that $2^{\alpha} > 2 \cdot \beta^2$. The +constant $\delta = 2^{\alpha - 2lg(\beta)}$ will represent the maximal weight of any column in a product (\textit{see ~COMBA~ for more information}). + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_mul\_digs}. \\ +\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\ +\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\ +\hline \\ +1. If min$(a.used, b.used) < \delta$ then do \\ +\hspace{3mm}1.1 Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}). \\ +\hspace{3mm}1.2 Return the result of step 1.1 \\ +\\ +Allocate and initialize a temporary mp\_int. \\ +2. Init $t$ to be of size $digs$ \\ +3. If step 2 failed return(\textit{MP\_MEM}). \\ +4. $t.used \leftarrow digs$ \\ +\\ +Compute the product. \\ +5. for $ix$ from $0$ to $a.used - 1$ do \\ +\hspace{3mm}5.1 $u \leftarrow 0$ \\ +\hspace{3mm}5.2 $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\ +\hspace{3mm}5.3 If $pb < 1$ then goto step 6. \\ +\hspace{3mm}5.4 for $iy$ from $0$ to $pb - 1$ do \\ +\hspace{6mm}5.4.1 $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\ +\hspace{6mm}5.4.2 $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{6mm}5.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +\hspace{3mm}5.5 if $ix + pb < digs$ then do \\ +\hspace{6mm}5.5.1 $t_{ix + pb} \leftarrow u$ \\ +6. Clamp excess digits of $t$. \\ +7. Swap $c$ with $t$ \\ +8. Clear $t$ \\ +9. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm s\_mp\_mul\_digs} +\end{figure} + +\textbf{Algorithm s\_mp\_mul\_digs.} +This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits. While it may seem +a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent +algorithm. The algorithm is loosely based on algorithm 14.12 from \cite[pp. 595]{HAC} and is similar to Algorithm M of Knuth \cite[pp. 268]{TAOCPV2}. +Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the +inputs. + +The first thing this algorithm checks for is whether a Comba multiplier can be used instead. If the minimum digit count of either +input is less than $\delta$, then the Comba method may be used instead. After the Comba method is ruled out, the baseline algorithm begins. A +temporary mp\_int variable $t$ is used to hold the intermediate result of the product. This allows the algorithm to be used to +compute products when either $a = c$ or $b = c$ without overwriting the inputs. + +All of step 5 is the infamous $O(n^2)$ multiplication loop slightly modified to only produce upto $digs$ digits of output. The $pb$ variable +is given the count of digits to read from $b$ inside the nested loop. If $pb \le 1$ then no more output digits can be produced and the algorithm +will exit the loop. The best way to think of the loops are as a series of $pb \times 1$ multiplications. That is, in each pass of the +innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$. + +For example, consider multiplying $576$ by $241$. That is equivalent to computing $10^0(1)(576) + 10^1(4)(576) + 10^2(2)(576)$ which is best +visualized in the following table. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{|c|c|c|c|c|c|l|} +\hline && & 5 & 7 & 6 & \\ +\hline $\times$&& & 2 & 4 & 1 & \\ +\hline &&&&&&\\ + && & 5 & 7 & 6 & $10^0(1)(576)$ \\ + &2 & 3 & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\ + 1 & 3 & 8 & 8 & 1 & 6 & $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\ +\hline +\end{tabular} +\end{center} +\caption{Long-Hand Multiplication Diagram} +\end{figure} + +Each row of the product is added to the result after being shifted to the left (\textit{multiplied by a power of the radix}) by the appropriate +count. That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult. + +Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable. The multiplication on that step +is assumed to be a double wide output single precision multiplication. That is, two single precision variables are multiplied to produce a +double precision result. The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step +5.4.1 is propagated through the nested loop. If the carry was not propagated immediately it would overflow the single precision digit +$t_{ix+iy}$ and the result would be lost. + +At step 5.5 the nested loop is finished and any carry that was left over should be forwarded. The carry does not have to be added to the $ix+pb$'th +digit since that digit is assumed to be zero at this point. However, if $ix + pb \ge digs$ the carry is not set as it would make the result +exceed the precision requested. + +EXAM,bn_s_mp_mul_digs.c + +First we determine (line @30,if@) if the Comba method can be used first since it's faster. The conditions for +sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than +\textbf{MP\_WARRAY}. This new constant is used to control the stack usage in the Comba routines. By default it is +set to $\delta$ but can be reduced when memory is at a premium. + +If we cannot use the Comba method we proceed to setup the baseline routine. We allocate the the destination mp\_int +$t$ (line @36,init@) to the exact size of the output to avoid further re--allocations. At this point we now +begin the $O(n^2)$ loop. + +This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of +digits as output. In each iteration of the outer loop the $pb$ variable is set (line @48,MIN@) to the maximum +number of inner loop iterations. + +Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the +carry from the previous iteration. A particularly important observation is that most modern optimizing +C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that +is required for the product. In x86 terms for example, this means using the MUL instruction. + +Each digit of the product is stored in turn (line @68,tmpt@) and the carry propagated (line @71,>>@) to the +next iteration. + +\subsection{Faster Multiplication by the ``Comba'' Method} +MARK,COMBA + +One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be +computed and propagated upwards. This makes the nested loop very sequential and hard to unroll and implement +in parallel. The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G. +Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations. As an +interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written +five years before. + +At the heart of the Comba technique is once again the long-hand algorithm. Except in this case a slight +twist is placed on how the columns of the result are produced. In the standard long-hand algorithm rows of products +are produced then added together to form the final result. In the baseline algorithm the columns are added together +after each iteration to get the result instantaneously. + +In the Comba algorithm the columns of the result are produced entirely independently of each other. That is at +the $O(n^2)$ level a simple multiplication and addition step is performed. The carries of the columns are propagated +after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute +the product vector $\vec x$ as follows. + +\begin{equation} +\vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace +\end{equation} + +Where $\vec x_n$ is the $n'th$ column of the output vector. Consider the following example which computes the vector $\vec x$ for the multiplication +of $576$ and $241$. + +\newpage\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{|c|c|c|c|c|c|} + \hline & & 5 & 7 & 6 & First Input\\ + \hline $\times$ & & 2 & 4 & 1 & Second Input\\ +\hline & & $1 \cdot 5 = 5$ & $1 \cdot 7 = 7$ & $1 \cdot 6 = 6$ & First pass \\ + & $4 \cdot 5 = 20$ & $4 \cdot 7+5=33$ & $4 \cdot 6+7=31$ & 6 & Second pass \\ + $2 \cdot 5 = 10$ & $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31 & 6 & Third pass \\ +\hline 10 & 34 & 45 & 31 & 6 & Final Result \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Comba Multiplication Diagram} +\end{figure} + +At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler. +Now the columns must be fixed by propagating the carry upwards. The resultant vector will have one extra dimension over the input vector which is +congruent to adding a leading zero digit. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Comba Fixup}. \\ +\textbf{Input}. Vector $\vec x$ of dimension $k$ \\ +\textbf{Output}. Vector $\vec x$ such that the carries have been propagated. \\ +\hline \\ +1. for $n$ from $0$ to $k - 1$ do \\ +\hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\ +\hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\ +2. Return($\vec x$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Comba Fixup} +\end{figure} + +With that algorithm and $k = 5$ and $\beta = 10$ the following vector is produced $\vec x= \left < 1, 3, 8, 8, 1, 6 \right >$. In this case +$241 \cdot 576$ is in fact $138816$ and the procedure succeeded. If the algorithm is correct and as will be demonstrated shortly more +efficient than the baseline algorithm why not simply always use this algorithm? + +\subsubsection{Column Weight.} +At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output +independently. A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix +the carries. For example, in the multiplication of two three-digit numbers the third column of output will be the sum of +three single precision multiplications. If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then +an overflow can occur and the carry information will be lost. For any $m$ and $n$ digit inputs the maximum weight of any column is +min$(m, n)$ which is fairly obvious. + +The maximum number of terms in any column of a product is known as the ``column weight'' and strictly governs when the algorithm can be used. Recall +from earlier that a double precision type has $\alpha$ bits of resolution and a single precision digit has $lg(\beta)$ bits of precision. Given these +two quantities we must not violate the following + +\begin{equation} +k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha} +\end{equation} + +Which reduces to + +\begin{equation} +k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha} +\end{equation} + +Let $\rho = lg(\beta)$ represent the number of bits in a single precision digit. By further re-arrangement of the equation the final solution is +found. + +\begin{equation} +k < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}} +\end{equation} + +The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$. In this configuration +the smaller input may not have more than $256$ digits if the Comba method is to be used. This is quite satisfactory for most applications since +$256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, is much larger than most public key cryptographic algorithms require. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\ +\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\ +\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\ +\hline \\ +Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\ +1. If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\ +2. If step 1 failed return(\textit{MP\_MEM}).\\ +\\ +3. $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\ +\\ +4. $\_ \hat W \leftarrow 0$ \\ +5. for $ix$ from 0 to $pa - 1$ do \\ +\hspace{3mm}5.1 $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\ +\hspace{3mm}5.2 $tx \leftarrow ix - ty$ \\ +\hspace{3mm}5.3 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\ +\hspace{3mm}5.4 for $iz$ from 0 to $iy - 1$ do \\ +\hspace{6mm}5.4.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\ +\hspace{3mm}5.5 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\ +\hspace{3mm}5.6 $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\ +\\ +6. $oldused \leftarrow c.used$ \\ +7. $c.used \leftarrow digs$ \\ +8. for $ix$ from $0$ to $pa$ do \\ +\hspace{3mm}8.1 $c_{ix} \leftarrow W_{ix}$ \\ +9. for $ix$ from $pa + 1$ to $oldused - 1$ do \\ +\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\ +\\ +10. Clamp $c$. \\ +11. Return MP\_OKAY. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm fast\_s\_mp\_mul\_digs} +\label{fig:COMBAMULT} +\end{figure} + +\textbf{Algorithm fast\_s\_mp\_mul\_digs.} +This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision. + +The outer loop of this algorithm is more complicated than that of the baseline multiplier. This is because on the inside of the +loop we want to produce one column per pass. This allows the accumulator $\_ \hat W$ to be placed in CPU registers and +reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration. + +The $ty$ variable is set to the minimum count of $ix$ or the number of digits in $b$. That way if $a$ has more digits than +$b$ this will be limited to $b.used - 1$. The $tx$ variable is set to the to the distance past $b.used$ the variable +$ix$ is. This is used for the immediately subsequent statement where we find $iy$. + +The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out. Computing one column at a time +means we have to scan one integer upwards and the other downwards. $a$ starts at $tx$ and $b$ starts at $ty$. In each +pass we are producing the $ix$'th output column and we note that $tx + ty = ix$. As we move $tx$ upwards we have to +move $ty$ downards so the equality remains valid. The $iy$ variable is the number of iterations until +$tx \ge a.used$ or $ty < 0$ occurs. + +After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator +into the next round by dividing $\_ \hat W$ by $\beta$. + +To measure the benefits of the Comba method over the baseline method consider the number of operations that are required. If the +cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require +$O \left ((p + q)n^2 \right )$ time to multiply two $n$-digit numbers. The Comba method requires only $O(pn^2 + qn)$ time, however in practice, +the speed increase is actually much more. With $O(n)$ space the algorithm can be reduced to $O(pn + qn)$ time by implementing the $n$ multiply +and addition operations in the nested loop in parallel. + +EXAM,bn_fast_s_mp_mul_digs.c + +As per the pseudo--code we first calculate $pa$ (line @47,MIN@) as the number of digits to output. Next we begin the outer loop +to produce the individual columns of the product. We use the two aliases $tmpx$ and $tmpy$ (lines @61,tmpx@, @62,tmpy@) to point +inside the two multiplicands quickly. + +The inner loop (lines @70,for@ to @72,}@) of this implementation is where the tradeoff come into play. Originally this comba +implementation was ``row--major'' which means it adds to each of the columns in each pass. After the outer loop it would then fix +the carries. This was very fast except it had an annoying drawback. You had to read a mp\_word and two mp\_digits and write +one mp\_word per iteration. On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth +is very high and it can keep the ALU fed with data. It did, however, matter on older and embedded cpus where cache is often +slower and also often doesn't exist. This new algorithm only performs two reads per iteration under the assumption that the +compiler has aliased $\_ \hat W$ to a CPU register. + +After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines @75,W[ix]@, @78,>>@) to forward it as +a carry for the next pass. After the outer loop we use the final carry (line @82,W[ix]@) as the last digit of the product. + +\subsection{Polynomial Basis Multiplication} +To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication. In the following algorithms +the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and +$g(x) = \sum_{i=0}^{n} b_i x^i$ respectively, is required. In this system both $f(x)$ and $g(x)$ have $n + 1$ terms and are of the $n$'th degree. + +The product $a \cdot b \equiv f(x)g(x)$ is the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$. The coefficients $w_i$ will +directly yield the desired product when $\beta$ is substituted for $x$. The direct solution to solve for the $2n + 1$ coefficients +requires $O(n^2)$ time and would in practice be slower than the Comba technique. + +However, numerical analysis theory indicates that only $2n + 1$ distinct points in $W(x)$ are required to determine the values of the $2n + 1$ unknown +coefficients. This means by finding $\zeta_y = W(y)$ for $2n + 1$ small values of $y$ the coefficients of $W(x)$ can be found with +Gaussian elimination. This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in +effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$. + +The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible. However, since +$W(x) = f(x)g(x)$ the equivalent $\zeta_y = f(y) g(y)$ can be used in its place. The benefit of this technique stems from the +fact that $f(y)$ and $g(y)$ are much smaller than either $a$ or $b$ respectively. As a result finding the $2n + 1$ relations required +by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs. + +When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$. The $\zeta_0$ term +is simply the product $W(0) = w_0 = a_0 \cdot b_0$. The $\zeta_1$ term is the product +$W(1) = \left (\sum_{i = 0}^{n} a_i \right ) \left (\sum_{i = 0}^{n} b_i \right )$. The third point $\zeta_{\infty}$ is less obvious but rather +simple to explain. The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication. +The point at $\infty$ is used symbolically to represent the most significant column, that is $W(\infty) = w_{2n} = a_nb_n$. Note that the +points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly. + +If more points are required they should be of small values and powers of two such as $2^q$ and the related \textit{mirror points} +$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ for small values of $q$. The term ``mirror point'' stems from the fact that +$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$. For +example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror. + +\begin{eqnarray} +\zeta_{2} = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\ +16 \cdot \zeta_{1 \over 2} = 4f({1\over 2}) \cdot 4g({1 \over 2}) = (a_2 + 2a_1 + 4a_0)(b_2 + 2b_1 + 4b_0) +\end{eqnarray} + +Using such points will allow the values of $f(y)$ and $g(y)$ to be independently calculated using only left shifts. For example, when $n = 2$ the +polynomial $f(2^q)$ is equal to $2^q((2^qa_2) + a_1) + a_0$. This technique of polynomial representation is known as Horner's method. + +As a general rule of the algorithm when the inputs are split into $n$ parts each there are $2n - 1$ multiplications. Each multiplication is of +multiplicands that have $n$ times fewer digits than the inputs. The asymptotic running time of this algorithm is +$O \left ( k^{lg_n(2n - 1)} \right )$ for $k$ digit inputs (\textit{assuming they have the same number of digits}). Figure~\ref{fig:exponent} +summarizes the exponents for various values of $n$. + +\begin{figure} +\begin{center} +\begin{tabular}{|c|c|c|} +\hline \textbf{Split into $n$ Parts} & \textbf{Exponent} & \textbf{Notes}\\ +\hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\ +\hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\ +\hline $4$ & $1.403677461$ &\\ +\hline $5$ & $1.365212389$ &\\ +\hline $10$ & $1.278753601$ &\\ +\hline $100$ & $1.149426538$ &\\ +\hline $1000$ & $1.100270931$ &\\ +\hline $10000$ & $1.075252070$ &\\ +\hline +\end{tabular} +\end{center} +\caption{Asymptotic Running Time of Polynomial Basis Multiplication} +\label{fig:exponent} +\end{figure} + +At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$. However, the overhead +of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large +numbers. + +\subsubsection{Cutoff Point} +The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach. However, +the algorithms incur an overhead (\textit{at the $O(n)$ work level}) since they require a system of equations to be solved. This makes the +polynomial basis approach more costly to use with small inputs. + +Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}). There exists a +point $y$ such that when $m < y$ the polynomial basis algorithms are more costly than Comba, when $m = y$ they are roughly the same cost and +when $m > y$ the Comba methods are slower than the polynomial basis algorithms. + +The exact location of $y$ depends on several key architectural elements of the computer platform in question. + +\begin{enumerate} +\item The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc. For example +on the AMD Athlon the ratio is roughly $17 : 1$ while on the Intel P4 it is $29 : 1$. The higher the ratio in favour of multiplication the lower +the cutoff point $y$ will be. + +\item The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is. Generally speaking as the number of splits +grows the complexity grows substantially. Ideally solving the system will only involve addition, subtraction and shifting of integers. This +directly reflects on the ratio previous mentioned. + +\item To a lesser extent memory bandwidth and function call overheads. Provided the values are in the processor cache this is less of an +influence over the cutoff point. + +\end{enumerate} + +A clean cutoff point separation occurs when a point $y$ is found such that all of the cutoff point conditions are met. For example, if the point +is too low then there will be values of $m$ such that $m > y$ and the Comba method is still faster. Finding the cutoff points is fairly simple when +a high resolution timer is available. + +\subsection{Karatsuba Multiplication} +Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for +general purpose multiplication. Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with +light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent. + +\begin{equation} +f(x) \cdot g(x) = acx^2 + ((a + b)(c + d) - (ac + bd))x + bd +\end{equation} + +Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product. Applying +this algorithm recursively, the work factor becomes $O(n^{lg(3)})$ which is substantially better than the work factor $O(n^2)$ of the Comba technique. It turns +out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points +$\zeta_0$, $\zeta_{\infty}$ and $\zeta_{1}$. Consider the resultant system of equations. + +\begin{center} +\begin{tabular}{rcrcrcrc} +$\zeta_{0}$ & $=$ & & & & & $w_0$ \\ +$\zeta_{1}$ & $=$ & $w_2$ & $+$ & $w_1$ & $+$ & $w_0$ \\ +$\zeta_{\infty}$ & $=$ & $w_2$ & & & & \\ +\end{tabular} +\end{center} + +By adding the first and last equation to the equation in the middle the term $w_1$ can be isolated and all three coefficients solved for. The simplicity +of this system of equations has made Karatsuba fairly popular. In fact the cutoff point is often fairly low\footnote{With LibTomMath 0.18 it is 70 and 109 digits for the Intel P4 and AMD Athlon respectively.} +making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_karatsuba\_mul}. \\ +\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ +\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\ +\hline \\ +1. Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\ +2. If step 2 failed then return(\textit{MP\_MEM}). \\ +\\ +Split the input. e.g. $a = x1 \cdot \beta^B + x0$ \\ +3. $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\ +4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\ +5. $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\ +6. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\ +7. $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\ +\\ +Calculate the three products. \\ +8. $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\ +9. $x1y1 \leftarrow x1 \cdot y1$ \\ +10. $t1 \leftarrow x1 + x0$ (\textit{mp\_add}) \\ +11. $x0 \leftarrow y1 + y0$ \\ +12. $t1 \leftarrow t1 \cdot x0$ \\ +\\ +Calculate the middle term. \\ +13. $x0 \leftarrow x0y0 + x1y1$ \\ +14. $t1 \leftarrow t1 - x0$ (\textit{s\_mp\_sub}) \\ +\\ +Calculate the final product. \\ +15. $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\ +16. $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\ +17. $t1 \leftarrow x0y0 + t1$ \\ +18. $c \leftarrow t1 + x1y1$ \\ +19. Clear all of the temporary variables. \\ +20. Return(\textit{MP\_OKAY}).\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_karatsuba\_mul} +\end{figure} + +\textbf{Algorithm mp\_karatsuba\_mul.} +This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm. It is loosely based on the description +from Knuth \cite[pp. 294-295]{TAOCPV2}. + +\index{radix point} +In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen. The radix point chosen must +be used for both of the inputs meaning that it must be smaller than the smallest input. Step 3 chooses the radix point $B$ as half of the +smallest input \textbf{used} count. After the radix point is chosen the inputs are split into lower and upper halves. Step 4 and 5 +compute the lower halves. Step 6 and 7 computer the upper halves. + +After the halves have been computed the three intermediate half-size products must be computed. Step 8 and 9 compute the trivial products +$x0 \cdot y0$ and $x1 \cdot y1$. The mp\_int $x0$ is used as a temporary variable after $x1 + x0$ has been computed. By using $x0$ instead +of an additional temporary variable, the algorithm can avoid an addition memory allocation operation. + +The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations. + +EXAM,bn_mp_karatsuba_mul.c + +The new coding element in this routine, not seen in previous routines, is the usage of goto statements. The conventional +wisdom is that goto statements should be avoided. This is generally true, however when every single function call can fail, it makes sense +to handle error recovery with a single piece of code. Lines @61,if@ to @75,if@ handle initializing all of the temporary variables +required. Note how each of the if statements goes to a different label in case of failure. This allows the routine to correctly free only +the temporaries that have been successfully allocated so far. + +The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large. This saves the +additional reallocation that would have been necessary. Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective +number of digits for the next section of code. + +The first algebraic portion of the algorithm is to split the two inputs into their halves. However, instead of using mp\_mod\_2d and mp\_rshd +to extract the halves, the respective code has been placed inline within the body of the function. To initialize the halves, the \textbf{used} and +\textbf{sign} members are copied first. The first for loop on line @98,for@ copies the lower halves. Since they are both the same magnitude it +is simpler to calculate both lower halves in a single loop. The for loop on lines @104,for@ and @109,for@ calculate the upper halves $x1$ and +$y1$ respectively. + +By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs. + +When line @152,err@ is reached, the algorithm has completed succesfully. The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that +the same code that handles errors can be used to clear the temporary variables and return. + +\subsection{Toom-Cook $3$-Way Multiplication} +Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points are +chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce. Here, the points $\zeta_{0}$, +$16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients +of the $W(x)$. + +With the five relations that Toom-Cook specifies, the following system of equations is formed. + +\begin{center} +\begin{tabular}{rcrcrcrcrcr} +$\zeta_0$ & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$ \\ +$16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$ \\ +$\zeta_1$ & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$ \\ +$\zeta_2$ & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$ \\ +$\zeta_{\infty}$ & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$ \\ +\end{tabular} +\end{center} + +A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power +of two, two divisions by three and one multiplication by three. All of these $19$ sub-operations require less than quadratic time, meaning that +the algorithm can be faster than a baseline multiplication. However, the greater complexity of this algorithm places the cutoff point +(\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_toom\_mul}. \\ +\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ +\textbf{Output}. $c \leftarrow a \cdot b $ \\ +\hline \\ +Split $a$ and $b$ into three pieces. E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\ +1. $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\ +2. $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +3. $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +4. $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +5. $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +6. $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +7. $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +\\ +Find the five equations for $w_0, w_1, ..., w_4$. \\ +8. $w_0 \leftarrow a_0 \cdot b_0$ \\ +9. $w_4 \leftarrow a_2 \cdot b_2$ \\ +10. $tmp_1 \leftarrow 2 \cdot a_0$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_2$ \\ +11. $tmp_2 \leftarrow 2 \cdot b_0$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_2$ \\ +12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\ +13. $tmp_1 \leftarrow 2 \cdot a_2$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_0$ \\ +14. $tmp_2 \leftarrow 2 \cdot b_2$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_0$ \\ +15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\ +16. $tmp_1 \leftarrow a_0 + a_1$, $tmp_1 \leftarrow tmp_1 + a_2$, $tmp_2 \leftarrow b_0 + b_1$, $tmp_2 \leftarrow tmp_2 + b_2$ \\ +17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\ +\\ +Continued on the next page.\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_toom\_mul} +\end{figure} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_toom\_mul} (continued). \\ +\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ +\textbf{Output}. $c \leftarrow a \cdot b $ \\ +\hline \\ +Now solve the system of equations. \\ +18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\ +19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\ +20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\ +21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\ +22. $tmp_1 \leftarrow 8 \cdot w_0$, $w_1 \leftarrow w_1 - tmp_1$, $tmp_1 \leftarrow 8 \cdot w_4$, $w_3 \leftarrow w_3 - tmp_1$ \\ +23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\ +24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\ +25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\ +\\ +Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\ +26. for $n$ from $1$ to $4$ do \\ +\hspace{3mm}26.1 $w_n \leftarrow w_n \cdot \beta^{nk}$ \\ +27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\ +28. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_toom\_mul (continued)} +\end{figure} + +\textbf{Algorithm mp\_toom\_mul.} +This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach. Compared to the Karatsuba multiplication, this +algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead. In this +description, several statements have been compounded to save space. The intention is that the statements are executed from left to right across +any given step. + +The two inputs $a$ and $b$ are first split into three $k$-digit integers $a_0, a_1, a_2$ and $b_0, b_1, b_2$ respectively. From these smaller +integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required. + +The first two relations $w_0$ and $w_4$ are the points $\zeta_{0}$ and $\zeta_{\infty}$ respectively. The relation $w_1, w_2$ and $w_3$ correspond +to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively. These are found using logical shifts to independently find +$f(y)$ and $g(y)$ which significantly speeds up the algorithm. + +After the five relations $w_0, w_1, \ldots, w_4$ have been computed, the system they represent must be solved in order for the unknown coefficients +$w_1, w_2$ and $w_3$ to be isolated. The steps 18 through 25 perform the system reduction required as previously described. Each step of +the reduction represents the comparable matrix operation that would be performed had this been performed by pencil. For example, step 18 indicates +that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$. + +Once the coeffients have been isolated, the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$ is known. By substituting $\beta^{k}$ for $x$, the integer +result $a \cdot b$ is produced. + +EXAM,bn_mp_toom_mul.c + +The first obvious thing to note is that this algorithm is complicated. The complexity is worth it if you are multiplying very +large numbers. For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with +Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$). For most ``crypto'' sized numbers this +algorithm is not practical as Karatsuba has a much lower cutoff point. + +First we split $a$ and $b$ into three roughly equal portions. This has been accomplished (lines @40,mod@ to @69,rshd@) with +combinations of mp\_rshd() and mp\_mod\_2d() function calls. At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly +for $b$. + +Next we compute the five points $w0, w1, w2, w3$ and $w4$. Recall that $w0$ and $w4$ can be computed directly from the portions so +we get those out of the way first (lines @72,mul@ and @77,mul@). Next we compute $w1, w2$ and $w3$ using Horners method. + +After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively +straight forward. + +\subsection{Signed Multiplication} +Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required. So far all +of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_mul}. \\ +\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ +\textbf{Output}. $c \leftarrow a \cdot b$ \\ +\hline \\ +1. If $a.sign = b.sign$ then \\ +\hspace{3mm}1.1 $sign = MP\_ZPOS$ \\ +2. else \\ +\hspace{3mm}2.1 $sign = MP\_ZNEG$ \\ +3. If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then \\ +\hspace{3mm}3.1 $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\ +4. else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\ +\hspace{3mm}4.1 $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\ +5. else \\ +\hspace{3mm}5.1 $digs \leftarrow a.used + b.used + 1$ \\ +\hspace{3mm}5.2 If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\ +\hspace{6mm}5.2.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs. \\ +\hspace{3mm}5.3 else \\ +\hspace{6mm}5.3.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs. \\ +6. $c.sign \leftarrow sign$ \\ +7. Return the result of the unsigned multiplication performed. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_mul} +\end{figure} + +\textbf{Algorithm mp\_mul.} +This algorithm performs the signed multiplication of two inputs. It will make use of any of the three unsigned multiplication algorithms +available when the input is of appropriate size. The \textbf{sign} of the result is not set until the end of the algorithm since algorithm +s\_mp\_mul\_digs will clear it. + +EXAM,bn_mp_mul.c + +The implementation is rather simplistic and is not particularly noteworthy. Line @22,?@ computes the sign of the result using the ``?'' +operator from the C programming language. Line @37,<<@ computes $\delta$ using the fact that $1 << k$ is equal to $2^k$. + +\section{Squaring} +\label{sec:basesquare} + +Squaring is a special case of multiplication where both multiplicands are equal. At first it may seem like there is no significant optimization +available but in fact there is. Consider the multiplication of $576$ against $241$. In total there will be nine single precision multiplications +performed which are $1\cdot 6$, $1 \cdot 7$, $1 \cdot 5$, $4 \cdot 6$, $4 \cdot 7$, $4 \cdot 5$, $2 \cdot 6$, $2 \cdot 7$ and $2 \cdot 5$. Now consider +the multiplication of $123$ against $123$. The nine products are $3 \cdot 3$, $3 \cdot 2$, $3 \cdot 1$, $2 \cdot 3$, $2 \cdot 2$, $2 \cdot 1$, +$1 \cdot 3$, $1 \cdot 2$ and $1 \cdot 1$. On closer inspection some of the products are equivalent. For example, $3 \cdot 2 = 2 \cdot 3$ +and $3 \cdot 1 = 1 \cdot 3$. + +For any $n$-digit input, there are ${{\left (n^2 + n \right)}\over 2}$ possible unique single precision multiplications required compared to the $n^2$ +required for multiplication. The following diagram gives an example of the operations required. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{ccccc|c} +&&1&2&3&\\ +$\times$ &&1&2&3&\\ +\hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\ + & $2 \cdot 1$ & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\ + $1 \cdot 1$ & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\ +\end{tabular} +\end{center} +\caption{Squaring Optimization Diagram} +\end{figure} + +MARK,SQUARE +Starting from zero and numbering the columns from right to left a very simple pattern becomes obvious. For the purposes of this discussion let $x$ +represent the number being squared. The first observation is that in row $k$ the $2k$'th column of the product has a $\left (x_k \right)^2$ term in it. + +The second observation is that every column $j$ in row $k$ where $j \ne 2k$ is part of a double product. Every non-square term of a column will +appear twice hence the name ``double product''. Every odd column is made up entirely of double products. In fact every column is made up of double +products and at most one square (\textit{see the exercise section}). + +The third and final observation is that for row $k$ the first unique non-square term, that is, one that hasn't already appeared in an earlier row, +occurs at column $2k + 1$. For example, on row $1$ of the previous squaring, column one is part of the double product with column one from row zero. +Column two of row one is a square and column three is the first unique column. + +\subsection{The Baseline Squaring Algorithm} +The baseline squaring algorithm is meant to be a catch-all squaring algorithm. It will handle any of the input sizes that the faster routines +will not handle. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_sqr}. \\ +\textbf{Input}. mp\_int $a$ \\ +\textbf{Output}. $b \leftarrow a^2$ \\ +\hline \\ +1. Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits. (\textit{mp\_init\_size}) \\ +2. If step 1 failed return(\textit{MP\_MEM}) \\ +3. $t.used \leftarrow 2 \cdot a.used + 1$ \\ +4. For $ix$ from 0 to $a.used - 1$ do \\ +\hspace{3mm}Calculate the square. \\ +\hspace{3mm}4.1 $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\ +\hspace{3mm}4.2 $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}Calculate the double products after the square. \\ +\hspace{3mm}4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +\hspace{3mm}4.4 For $iy$ from $ix + 1$ to $a.used - 1$ do \\ +\hspace{6mm}4.4.1 $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\ +\hspace{6mm}4.4.2 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{6mm}4.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +\hspace{3mm}Set the last carry. \\ +\hspace{3mm}4.5 While $u > 0$ do \\ +\hspace{6mm}4.5.1 $iy \leftarrow iy + 1$ \\ +\hspace{6mm}4.5.2 $\hat r \leftarrow t_{ix + iy} + u$ \\ +\hspace{6mm}4.5.3 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{6mm}4.5.4 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +5. Clamp excess digits of $t$. (\textit{mp\_clamp}) \\ +6. Exchange $b$ and $t$. \\ +7. Clear $t$ (\textit{mp\_clear}) \\ +8. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm s\_mp\_sqr} +\end{figure} + +\textbf{Algorithm s\_mp\_sqr.} +This algorithm computes the square of an input using the three observations on squaring. It is based fairly faithfully on algorithm 14.16 of HAC +\cite[pp.596-597]{HAC}. Similar to algorithm s\_mp\_mul\_digs, a temporary mp\_int is allocated to hold the result of the squaring. This allows the +destination mp\_int to be the same as the source mp\_int. + +The outer loop of this algorithm begins on step 4. It is best to think of the outer loop as walking down the rows of the partial results, while +the inner loop computes the columns of the partial result. Step 4.1 and 4.2 compute the square term for each row, and step 4.3 and 4.4 propagate +the carry and compute the double products. + +The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this +very algorithm. The product $a_{ix}a_{iy}$ will lie in the range $0 \le x \le \beta^2 - 2\beta + 1$ which is obviously less than $\beta^2$ meaning that +when it is multiplied by two, it can be properly represented by a mp\_word. + +Similar to algorithm s\_mp\_mul\_digs, after every pass of the inner loop, the destination is correctly set to the sum of all of the partial +results calculated so far. This involves expensive carry propagation which will be eliminated in the next algorithm. + +EXAM,bn_s_mp_sqr.c + +Inside the outer loop (line @32,for@) the square term is calculated on line @35,r =@. The carry (line @42,>>@) has been +extracted from the mp\_word accumulator using a right shift. Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized +(lines @45,tmpx@ and @48,tmpt@) to simplify the inner loop. The doubling is performed using two +additions (line @57,r + r@) since it is usually faster than shifting, if not at least as fast. + +The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication. As such the inner loops +get progressively shorter as the algorithm proceeds. This is what leads to the savings compared to using a multiplication to +square a number. + +\subsection{Faster Squaring by the ``Comba'' Method} +A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop. Squaring has an additional +drawback that it must double the product inside the inner loop as well. As for multiplication, the Comba technique can be used to eliminate these +performance hazards. + +The first obvious solution is to make an array of mp\_words which will hold all of the columns. This will indeed eliminate all of the carry +propagation operations from the inner loop. However, the inner product must still be doubled $O(n^2)$ times. The solution stems from the simple fact +that $2a + 2b + 2c = 2(a + b + c)$. That is the sum of all of the double products is equal to double the sum of all the products. For example, +$ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$. + +However, we cannot simply double all of the columns, since the squares appear only once per row. The most practical solution is to have two +mp\_word arrays. One array will hold the squares and the other array will hold the double products. With both arrays the doubling and +carry propagation can be moved to a $O(n)$ work level outside the $O(n^2)$ level. In this case, we have an even simpler solution in mind. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\ +\textbf{Input}. mp\_int $a$ \\ +\textbf{Output}. $b \leftarrow a^2$ \\ +\hline \\ +Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\ +1. If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits. (\textit{mp\_grow}). \\ +2. If step 1 failed return(\textit{MP\_MEM}). \\ +\\ +3. $pa \leftarrow 2 \cdot a.used$ \\ +4. $\hat W1 \leftarrow 0$ \\ +5. for $ix$ from $0$ to $pa - 1$ do \\ +\hspace{3mm}5.1 $\_ \hat W \leftarrow 0$ \\ +\hspace{3mm}5.2 $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\ +\hspace{3mm}5.3 $tx \leftarrow ix - ty$ \\ +\hspace{3mm}5.4 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\ +\hspace{3mm}5.5 $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\ +\hspace{3mm}5.6 for $iz$ from $0$ to $iz - 1$ do \\ +\hspace{6mm}5.6.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\ +\hspace{3mm}5.7 $\_ \hat W \leftarrow 2 \cdot \_ \hat W + \hat W1$ \\ +\hspace{3mm}5.8 if $ix$ is even then \\ +\hspace{6mm}5.8.1 $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\ +\hspace{3mm}5.9 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\ +\hspace{3mm}5.10 $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\ +\\ +6. $oldused \leftarrow b.used$ \\ +7. $b.used \leftarrow 2 \cdot a.used$ \\ +8. for $ix$ from $0$ to $pa - 1$ do \\ +\hspace{3mm}8.1 $b_{ix} \leftarrow W_{ix}$ \\ +9. for $ix$ from $pa$ to $oldused - 1$ do \\ +\hspace{3mm}9.1 $b_{ix} \leftarrow 0$ \\ +10. Clamp excess digits from $b$. (\textit{mp\_clamp}) \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm fast\_s\_mp\_sqr} +\end{figure} + +\textbf{Algorithm fast\_s\_mp\_sqr.} +This algorithm computes the square of an input using the Comba technique. It is designed to be a replacement for algorithm +s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$. +This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of. + +First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively. This is because the inner loop +products are to be doubled. If we had added the previous carry in we would be doubling too much. Next we perform an +addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits. For example, $a_3 \cdot a_5$ is equal +$a_5 \cdot a_3$. Whereas in the multiplication case we would have $5 < a.used$ and $3 \ge 0$ is maintained since we double the sum +of the products just outside the inner loop we have to avoid doing this. This is also a good thing since we perform +fewer multiplications and the routine ends up being faster. + +Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8). We add in the square +only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position. + +EXAM,bn_fast_s_mp_sqr.c + +This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for +the special case of squaring. + +\subsection{Polynomial Basis Squaring} +The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring. The minor exception +is that $\zeta_y = f(y)g(y)$ is actually equivalent to $\zeta_y = f(y)^2$ since $f(y) = g(y)$. Instead of performing $2n + 1$ +multiplications to find the $\zeta$ relations, squaring operations are performed instead. + +\subsection{Karatsuba Squaring} +Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square. +Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial. The Karatsuba equation can be modified to square a +number with the following equation. + +\begin{equation} +h(x) = a^2x^2 + \left ((a + b)^2 - (a^2 + b^2) \right )x + b^2 +\end{equation} + +Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a + b)^2$. As in +Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of +$O \left ( n^{lg(3)} \right )$. + +If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm +instead? The answer to this arises from the cutoff point for squaring. As in multiplication there exists a cutoff point, at which the +time required for a Comba based squaring and a Karatsuba based squaring meet. Due to the overhead inherent in the Karatsuba method, the cutoff +point is fairly high. For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits. + +Consider squaring a 200 digit number with this technique. It will be split into two 100 digit halves which are subsequently squared. +The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm. If Karatsuba multiplication +were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\ +\textbf{Input}. mp\_int $a$ \\ +\textbf{Output}. $b \leftarrow a^2$ \\ +\hline \\ +1. Initialize the following temporary mp\_ints: $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\ +2. If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\ +\\ +Split the input. e.g. $a = x1\beta^B + x0$ \\ +3. $B \leftarrow \lfloor a.used / 2 \rfloor$ \\ +4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\ +5. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\ +\\ +Calculate the three squares. \\ +6. $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\ +7. $x1x1 \leftarrow x1^2$ \\ +8. $t1 \leftarrow x1 + x0$ (\textit{s\_mp\_add}) \\ +9. $t1 \leftarrow t1^2$ \\ +\\ +Compute the middle term. \\ +10. $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\ +11. $t1 \leftarrow t1 - t2$ \\ +\\ +Compute final product. \\ +12. $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\ +13. $x1x1 \leftarrow x1x1\beta^{2B}$ \\ +14. $t1 \leftarrow t1 + x0x0$ \\ +15. $b \leftarrow t1 + x1x1$ \\ +16. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_karatsuba\_sqr} +\end{figure} + +\textbf{Algorithm mp\_karatsuba\_sqr.} +This algorithm computes the square of an input $a$ using the Karatsuba technique. This algorithm is very similar to the Karatsuba based +multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings. + +The radix point for squaring is simply placed exactly in the middle of the digits when the input has an odd number of digits, otherwise it is +placed just below the middle. Step 3, 4 and 5 compute the two halves required using $B$ +as the radix point. The first two squares in steps 6 and 7 are rather straightforward while the last square is of a more compact form. + +By expanding $\left (x1 + x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $(x0 - x1)^2 - (x1^2 + x0^2) = 2 \cdot x0 \cdot x1$. +Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then +this method is faster. Assuming no further recursions occur, the difference can be estimated with the following inequality. + +Let $p$ represent the cost of a single precision addition and $q$ the cost of a single precision multiplication both in terms of time\footnote{Or +machine clock cycles.}. + +\begin{equation} +5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2 +\end{equation} + +For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$. This implies that the following inequality should hold. +\begin{center} +\begin{tabular}{rcl} +${5n \over 3} + 3n^2 + 3n$ & $<$ & ${n \over 3} + 6n^2$ \\ +${5 \over 3} + 3n + 3$ & $<$ & ${1 \over 3} + 6n$ \\ +${13 \over 9}$ & $<$ & $n$ \\ +\end{tabular} +\end{center} + +This results in a cutoff point around $n = 2$. As a consequence it is actually faster to compute the middle term the ``long way'' on processors +where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication. On +the Intel P4 processor this ratio is 1:29 making this method even more beneficial. The only common exception is the ARMv4 processor which has a +ratio of 1:7. } than simpler operations such as addition. + +EXAM,bn_mp_karatsuba_sqr.c + +This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul. It uses the same inline style to copy and +shift the input into the two halves. The loop from line @54,{@ to line @70,}@ has been modified since only one input exists. The \textbf{used} +count of both $x0$ and $x1$ is fixed up and $x0$ is clamped before the calculations begin. At this point $x1$ and $x0$ are valid equivalents +to the respective halves as if mp\_rshd and mp\_mod\_2d had been used. + +By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered. On the Athlon the cutoff point +is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}). On slower processors such as the Intel P4 +it is actually below the Comba limit (\textit{at 110 digits}). + +This routine uses the same error trap coding style as mp\_karatsuba\_sqr. As the temporary variables are initialized errors are +redirected to the error trap higher up. If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and +mp\_clears are executed normally. + +\subsection{Toom-Cook Squaring} +The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used +instead of multiplication to find the five relations. The reader is encouraged to read the description of the latter algorithm and try to +derive their own Toom-Cook squaring algorithm. + +\subsection{High Level Squaring} +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_sqr}. \\ +\textbf{Input}. mp\_int $a$ \\ +\textbf{Output}. $b \leftarrow a^2$ \\ +\hline \\ +1. If $a.used \ge TOOM\_SQR\_CUTOFF$ then \\ +\hspace{3mm}1.1 $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\ +2. else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\ +\hspace{3mm}2.1 $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\ +3. else \\ +\hspace{3mm}3.1 $digs \leftarrow a.used + b.used + 1$ \\ +\hspace{3mm}3.2 If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\ +\hspace{6mm}3.2.1 $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr. \\ +\hspace{3mm}3.3 else \\ +\hspace{6mm}3.3.1 $b \leftarrow a^2$ using algorithm s\_mp\_sqr. \\ +4. $b.sign \leftarrow MP\_ZPOS$ \\ +5. Return the result of the unsigned squaring performed. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_sqr} +\end{figure} + +\textbf{Algorithm mp\_sqr.} +This algorithm computes the square of the input using one of four different algorithms. If the input is very large and has at least +\textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used. If +neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used. + +EXAM,bn_mp_sqr.c + +\section*{Exercises} +\begin{tabular}{cl} +$\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\ + & that have different number of digits in Karatsuba multiplication. \\ + & \\ +$\left [ 2 \right ] $ & In ~SQUARE~ the fact that every column of a squaring is made up \\ + & of double products and at most one square is stated. Prove this statement. \\ + & \\ +$\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\ + & \\ +$\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\ + & \\ +$\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\ + & required for equation $6.7$ to be true. \\ + & \\ +$\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\ + & compute subsets of the columns in each thread. Determine a cutoff point where \\ + & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\ + &\\ +$\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook. You must \\ + & increase the throughput of mp\_exptmod() for random odd moduli in the range \\ + & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\ + & \\ +\end{tabular} + +\chapter{Modular Reduction} +MARK,REDUCTION +\section{Basics of Modular Reduction} +\index{modular residue} +Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms, +such as factoring. Modular reduction algorithms are the third class of algorithms of the ``multipliers'' set. A number $a$ is said to be \textit{reduced} +modulo another number $b$ by finding the remainder of the division $a/b$. Full integer division with remainder is a topic to be covered +in~\ref{sec:division}. + +Modular reduction is equivalent to solving for $r$ in the following equation. $a = bq + r$ where $q = \lfloor a/b \rfloor$. The result +$r$ is said to be ``congruent to $a$ modulo $b$'' which is also written as $r \equiv a \mbox{ (mod }b\mbox{)}$. In other vernacular $r$ is known as the +``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and +other forms of residues. + +Modular reductions are normally used to create either finite groups, rings or fields. The most common usage for performance driven modular reductions +is in modular exponentiation algorithms. That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible. This operation is used in the +RSA and Diffie-Hellman public key algorithms, for example. Modular multiplication and squaring also appears as a fundamental operation in +elliptic curve cryptographic algorithms. As will be discussed in the subsequent chapter there exist fast algorithms for computing modular +exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications. These algorithms will produce partial results in the +range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms. They have also been used to create redundancy check +algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems. + +\section{The Barrett Reduction} +The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate +division. Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to + +\begin{equation} +c = a - b \cdot \lfloor a/b \rfloor +\end{equation} + +Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper +targeted the DSP56K processor.} intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal. However, +DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types. +It would take another common optimization to optimize the algorithm. + +\subsection{Fixed Point Arithmetic} +The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers. Fixed +point arithmetic would become very popular as it greatly optimize the ``3d-shooter'' genre of games in the mid 1990s when floating point units were +fairly slow if not unavailable. The idea behind fixed point arithmetic is to take a normal $k$-bit integer data type and break it into $p$-bit +integer and a $q$-bit fraction part (\textit{where $p+q = k$}). + +In this system a $k$-bit integer $n$ would actually represent $n/2^q$. For example, with $q = 4$ the integer $n = 37$ would actually represent the +value $2.3125$. To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by +moving the implied decimal point back to where it should be. For example, with $q = 4$ to multiply the integers $9$ and $5$ they must be converted +to fixed point first by multiplying by $2^q$. Let $a = 9(2^q)$ represent the fixed point representation of $9$ and $b = 5(2^q)$ represent the +fixed point representation of $5$. The product $ab$ is equal to $45(2^{2q})$ which when normalized by dividing by $2^q$ produces $45(2^q)$. + +This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication +of two fixed point numbers. Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal. If $2^q$ is +equivalent to one than $2^q/b$ is equivalent to the fixed point approximation of $1/b$ using real arithmetic. Using this fact dividing an integer +$a$ by another integer $b$ can be achieved with the following expression. + +\begin{equation} +\lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor +\end{equation} + +The precision of the division is proportional to the value of $q$. If the divisor $b$ is used frequently as is the case with +modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift. Both operations +are considerably faster than division on most processors. + +Consider dividing $19$ by $5$. The correct result is $\lfloor 19/5 \rfloor = 3$. With $q = 3$ the reciprocal is $\lfloor 2^q/5 \rfloor = 1$ which +leads to a product of $19$ which when divided by $2^q$ produces $2$. However, with $q = 4$ the reciprocal is $\lfloor 2^q/5 \rfloor = 3$ and +the result of the emulated division is $\lfloor 3 \cdot 19 / 2^q \rfloor = 3$ which is correct. The value of $2^q$ must be close to or ideally +larger than the dividend. In effect if $a$ is the dividend then $q$ should allow $0 \le \lfloor a/2^q \rfloor \le 1$ in order for this approach +to work correctly. Plugging this form of divison into the original equation the following modular residue equation arises. + +\begin{equation} +c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor +\end{equation} + +Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol. Using the $\mu$ +variable also helps re-inforce the idea that it is meant to be computed once and re-used. + +\begin{equation} +c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor +\end{equation} + +Provided that $2^q \ge a$ this algorithm will produce a quotient that is either exactly correct or off by a value of one. In the context of Barrett +reduction the value of $a$ is bound by $0 \le a \le (b - 1)^2$ meaning that $2^q \ge b^2$ is sufficient to ensure the reciprocal will have enough +precision. + +Let $n$ represent the number of digits in $b$. This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and +another $n^2$ single precision multiplications to find the residue. In total $3n^2$ single precision multiplications are required to +reduce the number. + +For example, if $b = 1179677$ and $q = 41$ ($2^q > b^2$), then the reciprocal $\mu$ is equal to $\lfloor 2^q / b \rfloor = 1864089$. Consider reducing +$a = 180388626447$ modulo $b$ using the above reduction equation. The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$. +By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found. + +\subsection{Choosing a Radix Point} +Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications. If that were the best +that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$. +See~\ref{sec:division} for further details.} might as well be used in its place. The key to optimizing the reduction is to reduce the precision of +the initial multiplication that finds the quotient. + +Let $a$ represent the number of which the residue is sought. Let $b$ represent the modulus used to find the residue. Let $m$ represent +the number of digits in $b$. For the purposes of this discussion we will assume that the number of digits in $a$ is $2m$, which is generally true if +two $m$-digit numbers have been multiplied. Dividing $a$ by $b$ is the same as dividing a $2m$ digit integer by a $m$ digit integer. Digits below the +$m - 1$'th digit of $a$ will contribute at most a value of $1$ to the quotient because $\beta^k < b$ for any $0 \le k \le m - 1$. Another way to +express this is by re-writing $a$ as two parts. If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then +${a \over b} \equiv {{a' + a''} \over b}$ which is equivalent to ${a' \over b} + {a'' \over b}$. Since $a'$ is bound to be less than $b$ the quotient +is bound by $0 \le {a' \over b} < 1$. + +Since the digits of $a'$ do not contribute much to the quotient the observation is that they might as well be zero. However, if the digits +``might as well be zero'' they might as well not be there in the first place. Let $q_0 = \lfloor a/\beta^{m-1} \rfloor$ represent the input +with the irrelevant digits trimmed. Now the modular reduction is trimmed to the almost equivalent equation + +\begin{equation} +c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor +\end{equation} + +Note that the original divisor $2^q$ has been replaced with $\beta^{m+1}$ where in this case $q$ is a multiple of $lg(\beta)$. Also note that the +exponent on the divisor when added to the amount $q_0$ was shifted by equals $2m$. If the optimization had not been performed the divisor +would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient +$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ can be off from the true quotient by at most two. The original fixed point quotient can be off +by as much as one (\textit{provided the radix point is chosen suitably}) and now that the lower irrelevent digits have been trimmed the quotient +can be off by an additional value of one for a total of at most two. This implies that +$0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. By first subtracting $b$ times the quotient and then conditionally subtracting +$b$ once or twice the residue is found. + +The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single +precision multiplications, ignoring the subtractions required. In total $2m^2 + m$ single precision multiplications are required to find the residue. +This is considerably faster than the original attempt. + +For example, let $\beta = 10$ represent the radix of the digits. Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$ +represent the value of which the residue is desired. In this case $q = 8$ since $10^7 < 9999^2$ meaning that $\mu = \lfloor \beta^{q}/b \rfloor = 10001$. +With the new observation the multiplicand for the quotient is equal to $q_0 = \lfloor a / \beta^{m - 1} \rfloor = 99929$. The quotient is then +$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor = 9993$. Subtracting $9993b$ from $a$ and the correct residue $a \equiv 9871 \mbox{ (mod }b\mbox{)}$ +is found. + +\subsection{Trimming the Quotient} +So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications. As +it stands now the algorithm is already fairly fast compared to a full integer division algorithm. However, there is still room for +optimization. + +After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower +half of the product. It would be nice to be able to remove those digits from the product to effectively cut down the number of single precision +multiplications. If the number of digits in the modulus $m$ is far less than $\beta$ a full product is not required for the algorithm to work properly. +In fact the lower $m - 2$ digits will not affect the upper half of the product at all and do not need to be computed. + +The value of $\mu$ is a $m$-digit number and $q_0$ is a $m + 1$ digit number. Using a full multiplier $(m + 1)(m) = m^2 + m$ single precision +multiplications would be required. Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number +of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications. + +\subsection{Trimming the Residue} +After the quotient has been calculated it is used to reduce the input. As previously noted the algorithm is not exact and it can be off by a small +multiple of the modulus, that is $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. If $b$ is $m$ digits than the +result of reduction equation is a value of at most $m + 1$ digits (\textit{provided $3 < \beta$}) implying that the upper $m - 1$ digits are +implicitly zero. + +The next optimization arises from this very fact. Instead of computing $b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ using a full +$O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed. Similarly the value of $a$ can +be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well. A multiplication that produces +only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications. + +With both optimizations in place the algorithm is the algorithm Barrett proposed. It requires $m^2 + 2m - 1$ single precision multiplications which +is considerably faster than the straightforward $3m^2$ method. + +\subsection{The Barrett Algorithm} +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_reduce}. \\ +\textbf{Input}. mp\_int $a$, mp\_int $b$ and $\mu = \lfloor \beta^{2m}/b \rfloor, m = \lceil lg_{\beta}(b) \rceil, (0 \le a < b^2, b > 1)$ \\ +\textbf{Output}. $a \mbox{ (mod }b\mbox{)}$ \\ +\hline \\ +Let $m$ represent the number of digits in $b$. \\ +1. Make a copy of $a$ and store it in $q$. (\textit{mp\_init\_copy}) \\ +2. $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\ +\\ +Produce the quotient. \\ +3. $q \leftarrow q \cdot \mu$ (\textit{note: only produce digits at or above $m-1$}) \\ +4. $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\ +\\ +Subtract the multiple of modulus from the input. \\ +5. $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\ +6. $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\ +7. $a \leftarrow a - q$ (\textit{mp\_sub}) \\ +\\ +Add $\beta^{m+1}$ if a carry occured. \\ +8. If $a < 0$ then (\textit{mp\_cmp\_d}) \\ +\hspace{3mm}8.1 $q \leftarrow 1$ (\textit{mp\_set}) \\ +\hspace{3mm}8.2 $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\ +\hspace{3mm}8.3 $a \leftarrow a + q$ \\ +\\ +Now subtract the modulus if the residue is too large (e.g. quotient too small). \\ +9. While $a \ge b$ do (\textit{mp\_cmp}) \\ +\hspace{3mm}9.1 $c \leftarrow a - b$ \\ +10. Clear $q$. \\ +11. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_reduce} +\end{figure} + +\textbf{Algorithm mp\_reduce.} +This algorithm will reduce the input $a$ modulo $b$ in place using the Barrett algorithm. It is loosely based on algorithm 14.42 of HAC +\cite[pp. 602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}. The algorithm has several restrictions and assumptions which must +be adhered to for the algorithm to work. + +First the modulus $b$ is assumed to be positive and greater than one. If the modulus were less than or equal to one than subtracting +a multiple of it would either accomplish nothing or actually enlarge the input. The input $a$ must be in the range $0 \le a < b^2$ in order +for the quotient to have enough precision. If $a$ is the product of two numbers that were already reduced modulo $b$, this will not be a problem. +Technically the algorithm will still work if $a \ge b^2$ but it will take much longer to finish. The value of $\mu$ is passed as an argument to this +algorithm and is assumed to be calculated and stored before the algorithm is used. + +Recall that the multiplication for the quotient on step 3 must only produce digits at or above the $m-1$'th position. An algorithm called +$s\_mp\_mul\_high\_digs$ which has not been presented is used to accomplish this task. The algorithm is based on $s\_mp\_mul\_digs$ except that +instead of stopping at a given level of precision it starts at a given level of precision. This optimal algorithm can only be used if the number +of digits in $b$ is very much smaller than $\beta$. + +While it is known that +$a \ge b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ only the lower $m+1$ digits are being used to compute the residue, so an implied +``borrow'' from the higher digits might leave a negative result. After the multiple of the modulus has been subtracted from $a$ the residue must be +fixed up in case it is negative. The invariant $\beta^{m+1}$ must be added to the residue to make it positive again. + +The while loop at step 9 will subtract $b$ until the residue is less than $b$. If the algorithm is performed correctly this step is +performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should. + +EXAM,bn_mp_reduce.c + +The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up. This essentially halves +the number of single precision multiplications required. However, the optimization is only safe if $\beta$ is much larger than the number of digits +in the modulus. In the source code this is evaluated on lines @36,if@ to @44,}@ where algorithm s\_mp\_mul\_high\_digs is used when it is +safe to do so. + +\subsection{The Barrett Setup Algorithm} +In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance. Ideally this value should be computed once and stored for +future use so that the Barrett algorithm can be used without delay. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_reduce\_setup}. \\ +\textbf{Input}. mp\_int $a$ ($a > 1$) \\ +\textbf{Output}. $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\ +\hline \\ +1. $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot m}$ (\textit{mp\_2expt}) \\ +2. $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\ +3. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_reduce\_setup} +\end{figure} + +\textbf{Algorithm mp\_reduce\_setup.} +This algorithm computes the reciprocal $\mu$ required for Barrett reduction. First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot m}$ which +is equivalent and much faster. The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$. + +EXAM,bn_mp_reduce_setup.c + +This simple routine calculates the reciprocal $\mu$ required by Barrett reduction. Note the extended usage of algorithm mp\_div where the variable +which would received the remainder is passed as NULL. As will be discussed in~\ref{sec:division} the division routine allows both the quotient and the +remainder to be passed as NULL meaning to ignore the value. + +\section{The Montgomery Reduction} +Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting +form of reduction in common use. It computes a modular residue which is not actually equal to the residue of the input yet instead equal to a +residue times a constant. However, as perplexing as this may sound the algorithm is relatively simple and very efficient. + +Throughout this entire section the variable $n$ will represent the modulus used to form the residue. As will be discussed shortly the value of +$n$ must be odd. The variable $x$ will represent the quantity of which the residue is sought. Similar to the Barrett algorithm the input +is restricted to $0 \le x < n^2$. To begin the description some simple number theory facts must be established. + +\textbf{Fact 1.} Adding $n$ to $x$ does not change the residue since in effect it adds one to the quotient $\lfloor x / n \rfloor$. Another way +to explain this is that $n$ is (\textit{or multiples of $n$ are}) congruent to zero modulo $n$. Adding zero will not change the value of the residue. + +\textbf{Fact 2.} If $x$ is even then performing a division by two in $\Z$ is congruent to $x \cdot 2^{-1} \mbox{ (mod }n\mbox{)}$. Actually +this is an application of the fact that if $x$ is evenly divisible by any $k \in \Z$ then division in $\Z$ will be congruent to +multiplication by $k^{-1}$ modulo $n$. + +From these two simple facts the following simple algorithm can be derived. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Montgomery Reduction}. \\ +\textbf{Input}. Integer $x$, $n$ and $k$ \\ +\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\ +\hline \\ +1. for $t$ from $1$ to $k$ do \\ +\hspace{3mm}1.1 If $x$ is odd then \\ +\hspace{6mm}1.1.1 $x \leftarrow x + n$ \\ +\hspace{3mm}1.2 $x \leftarrow x/2$ \\ +2. Return $x$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Montgomery Reduction} +\end{figure} + +The algorithm reduces the input one bit at a time using the two congruencies stated previously. Inside the loop $n$, which is odd, is +added to $x$ if $x$ is odd. This forces $x$ to be even which allows the division by two in $\Z$ to be congruent to a modular division by two. Since +$x$ is assumed to be initially much larger than $n$ the addition of $n$ will contribute an insignificant magnitude to $x$. Let $r$ represent the +final result of the Montgomery algorithm. If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to +$0 \le r < \lfloor x/2^k \rfloor + n$. As a result at most a single subtraction is required to get the residue desired. + +\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{|c|l|} +\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\ +\hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\ +\hline $2$ & $x/2 = 1453$ \\ +\hline $3$ & $x + n = 1710$, $x/2 = 855$ \\ +\hline $4$ & $x + n = 1112$, $x/2 = 556$ \\ +\hline $5$ & $x/2 = 278$ \\ +\hline $6$ & $x/2 = 139$ \\ +\hline $7$ & $x + n = 396$, $x/2 = 198$ \\ +\hline $8$ & $x/2 = 99$ \\ +\hline $9$ & $x + n = 356$, $x/2 = 178$ \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Example of Montgomery Reduction (I)} +\label{fig:MONT1} +\end{figure} + +Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 9$ (note $\beta^k = 512$ which is larger than $n$). The result of +the algorithm $r = 178$ is congruent to the value of $2^{-9} \cdot 5555 \mbox{ (mod }257\mbox{)}$. When $r$ is multiplied by $2^9$ modulo $257$ the correct residue +$r \equiv 158$ is produced. + +Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$. The current algorithm requires $2k^2$ single precision shifts +and $k^2$ single precision additions. At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful. +Fortunately there exists an alternative representation of the algorithm. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Montgomery Reduction} (modified I). \\ +\textbf{Input}. Integer $x$, $n$ and $k$ ($2^k > n$) \\ +\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\ +\hline \\ +1. for $t$ from $1$ to $k$ do \\ +\hspace{3mm}1.1 If the $t$'th bit of $x$ is one then \\ +\hspace{6mm}1.1.1 $x \leftarrow x + 2^tn$ \\ +2. Return $x/2^k$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Montgomery Reduction (modified I)} +\end{figure} + +This algorithm is equivalent since $2^tn$ is a multiple of $n$ and the lower $k$ bits of $x$ are zero by step 2. The number of single +precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement. + +\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{|c|l|r|} +\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\ +\hline -- & $5555$ & $1010110110011$ \\ +\hline $1$ & $x + 2^{0}n = 5812$ & $1011010110100$ \\ +\hline $2$ & $5812$ & $1011010110100$ \\ +\hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\ +\hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\ +\hline $5$ & $8896$ & $10001011000000$ \\ +\hline $6$ & $8896$ & $10001011000000$ \\ +\hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\ +\hline $8$ & $25344$ & $110001100000000$ \\ +\hline $9$ & $x + 2^{7}n = 91136$ & $10110010000000000$ \\ +\hline -- & $x/2^k = 178$ & \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Example of Montgomery Reduction (II)} +\label{fig:MONT2} +\end{figure} + +Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 9$. +With this algorithm a single shift right at the end is the only right shift required to reduce the input instead of $k$ right shifts inside the +loop. Note that for the iterations $t = 2, 5, 6$ and $8$ where the result $x$ is not changed. In those iterations the $t$'th bit of $x$ is +zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero. + +\subsection{Digit Based Montgomery Reduction} +Instead of computing the reduction on a bit-by-bit basis it is actually much faster to compute it on digit-by-digit basis. Consider the +previous algorithm re-written to compute the Montgomery reduction in this new fashion. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Montgomery Reduction} (modified II). \\ +\textbf{Input}. Integer $x$, $n$ and $k$ ($\beta^k > n$) \\ +\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ +\hline \\ +1. for $t$ from $0$ to $k - 1$ do \\ +\hspace{3mm}1.1 $x \leftarrow x + \mu n \beta^t$ \\ +2. Return $x/\beta^k$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Montgomery Reduction (modified II)} +\end{figure} + +The value $\mu n \beta^t$ is a multiple of the modulus $n$ meaning that it will not change the residue. If the first digit of +the value $\mu n \beta^t$ equals the negative (modulo $\beta$) of the $t$'th digit of $x$ then the addition will result in a zero digit. This +problem breaks down to solving the following congruency. + +\begin{center} +\begin{tabular}{rcl} +$x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\ +$\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\ +$\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\ +\end{tabular} +\end{center} + +In each iteration of the loop on step 1 a new value of $\mu$ must be calculated. The value of $-1/n_0 \mbox{ (mod }\beta\mbox{)}$ is used +extensively in this algorithm and should be precomputed. Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$. + +For example, let $\beta = 10$ represent the radix. Let $n = 17$ represent the modulus which implies $k = 2$ and $\rho \equiv 7$. Let $x = 33$ +represent the value to reduce. + +\newpage\begin{figure} +\begin{center} +\begin{tabular}{|c|c|c|} +\hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\ +\hline -- & $33$ & --\\ +\hline $0$ & $33 + \mu n = 50$ & $1$ \\ +\hline $1$ & $50 + \mu n \beta = 900$ & $5$ \\ +\hline +\end{tabular} +\end{center} +\caption{Example of Montgomery Reduction} +\end{figure} + +The final result $900$ is then divided by $\beta^k$ to produce the final result $9$. The first observation is that $9 \nequiv x \mbox{ (mod }n\mbox{)}$ +which implies the result is not the modular residue of $x$ modulo $n$. However, recall that the residue is actually multiplied by $\beta^{-k}$ in +the algorithm. To get the true residue the value must be multiplied by $\beta^k$. In this case $\beta^k \equiv 15 \mbox{ (mod }n\mbox{)}$ and +the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$. + +\subsection{Baseline Montgomery Reduction} +The baseline Montgomery reduction algorithm will produce the residue for any size input. It is designed to be a catch-all algororithm for +Montgomery reductions. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_montgomery\_reduce}. \\ +\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\ +\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\ +\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ +\hline \\ +1. $digs \leftarrow 2n.used + 1$ \\ +2. If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\ +\hspace{3mm}2.1 Use algorithm fast\_mp\_montgomery\_reduce instead. \\ +\\ +Setup $x$ for the reduction. \\ +3. If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\ +4. $x.used \leftarrow digs$ \\ +\\ +Eliminate the lower $k$ digits. \\ +5. For $ix$ from $0$ to $k - 1$ do \\ +\hspace{3mm}5.1 $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}5.2 $u \leftarrow 0$ \\ +\hspace{3mm}5.3 For $iy$ from $0$ to $k - 1$ do \\ +\hspace{6mm}5.3.1 $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\ +\hspace{6mm}5.3.2 $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{6mm}5.3.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +\hspace{3mm}5.4 While $u > 0$ do \\ +\hspace{6mm}5.4.1 $iy \leftarrow iy + 1$ \\ +\hspace{6mm}5.4.2 $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\ +\hspace{6mm}5.4.3 $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\ +\hspace{6mm}5.4.4 $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\ +\\ +Divide by $\beta^k$ and fix up as required. \\ +6. $x \leftarrow \lfloor x / \beta^k \rfloor$ \\ +7. If $x \ge n$ then \\ +\hspace{3mm}7.1 $x \leftarrow x - n$ \\ +8. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_montgomery\_reduce} +\end{figure} + +\textbf{Algorithm mp\_montgomery\_reduce.} +This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm. The algorithm is loosely based +on algorithm 14.32 of \cite[pp.601]{HAC} except it merges the multiplication of $\mu n \beta^t$ with the addition in the inner loop. The +restrictions on this algorithm are fairly easy to adapt to. First $0 \le x < n^2$ bounds the input to numbers in the same range as +for the Barrett algorithm. Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$. $\rho$ must be calculated in +advance of this algorithm. Finally the variable $k$ is fixed and a pseudonym for $n.used$. + +Step 2 decides whether a faster Montgomery algorithm can be used. It is based on the Comba technique meaning that there are limits on +the size of the input. This algorithm is discussed in ~COMBARED~. + +Step 5 is the main reduction loop of the algorithm. The value of $\mu$ is calculated once per iteration in the outer loop. The inner loop +calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits. Both the addition and +multiplication are performed in the same loop to save time and memory. Step 5.4 will handle any additional carries that escape the inner loop. + +Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications +in the inner loop. In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision +multiplications. + +EXAM,bn_mp_montgomery_reduce.c + +This is the baseline implementation of the Montgomery reduction algorithm. Lines @30,digs@ to @35,}@ determine if the Comba based +routine can be used instead. Line @47,mu@ computes the value of $\mu$ for that particular iteration of the outer loop. + +The multiplication $\mu n \beta^{ix}$ is performed in one step in the inner loop. The alias $tmpx$ refers to the $ix$'th digit of $x$ and +the alias $tmpn$ refers to the modulus $n$. + +\subsection{Faster ``Comba'' Montgomery Reduction} +MARK,COMBARED + +The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial +nature of the inner loop. The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba +technique. The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates +a $k \times 1$ product $k$ times. + +The biggest obstacle is that at the $ix$'th iteration of the outer loop the value of $x_{ix}$ is required to calculate $\mu$. This means the +carries from $0$ to $ix - 1$ must have been propagated upwards to form a valid $ix$'th digit. The solution as it turns out is very simple. +Perform a Comba like multiplier and inside the outer loop just after the inner loop fix up the $ix + 1$'th digit by forwarding the carry. + +With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases +the speed of the algorithm. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\ +\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\ +\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\ +\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ +\hline \\ +Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\ +1. if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\ +Copy the digits of $x$ into the array $\hat W$ \\ +2. For $ix$ from $0$ to $x.used - 1$ do \\ +\hspace{3mm}2.1 $\hat W_{ix} \leftarrow x_{ix}$ \\ +3. For $ix$ from $x.used$ to $2n.used - 1$ do \\ +\hspace{3mm}3.1 $\hat W_{ix} \leftarrow 0$ \\ +Elimiate the lower $k$ digits. \\ +4. for $ix$ from $0$ to $n.used - 1$ do \\ +\hspace{3mm}4.1 $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}4.2 For $iy$ from $0$ to $n.used - 1$ do \\ +\hspace{6mm}4.2.1 $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\ +\hspace{3mm}4.3 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\ +Propagate carries upwards. \\ +5. for $ix$ from $n.used$ to $2n.used + 1$ do \\ +\hspace{3mm}5.1 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\ +Shift right and reduce modulo $\beta$ simultaneously. \\ +6. for $ix$ from $0$ to $n.used + 1$ do \\ +\hspace{3mm}6.1 $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\ +Zero excess digits and fixup $x$. \\ +7. if $x.used > n.used + 1$ then do \\ +\hspace{3mm}7.1 for $ix$ from $n.used + 1$ to $x.used - 1$ do \\ +\hspace{6mm}7.1.1 $x_{ix} \leftarrow 0$ \\ +8. $x.used \leftarrow n.used + 1$ \\ +9. Clamp excessive digits of $x$. \\ +10. If $x \ge n$ then \\ +\hspace{3mm}10.1 $x \leftarrow x - n$ \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm fast\_mp\_montgomery\_reduce} +\end{figure} + +\textbf{Algorithm fast\_mp\_montgomery\_reduce.} +This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique. It is on most computer platforms significantly +faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}). The algorithm has the same restrictions +on the input as the baseline reduction algorithm. An additional two restrictions are imposed on this algorithm. The number of digits $k$ in the +the modulus $n$ must not violate $MP\_WARRAY > 2k +1$ and $n < \delta$. When $\beta = 2^{28}$ this algorithm can be used to reduce modulo +a modulus of at most $3,556$ bits in length. + +As in the other Comba reduction algorithms there is a $\hat W$ array which stores the columns of the product. It is initially filled with the +contents of $x$ with the excess digits zeroed. The reduction loop is very similar the to the baseline loop at heart. The multiplication on step +4.1 can be single precision only since $ab \mbox{ (mod }\beta\mbox{)} \equiv (a \mbox{ mod }\beta)(b \mbox{ mod }\beta)$. Some multipliers such +as those on the ARM processors take a variable length time to complete depending on the number of bytes of result it must produce. By performing +a single precision multiplication instead half the amount of time is spent. + +Also note that digit $\hat W_{ix}$ must have the carry from the $ix - 1$'th digit propagated upwards in order for this to work. That is what step +4.3 will do. In effect over the $n.used$ iterations of the outer loop the $n.used$'th lower columns all have the their carries propagated forwards. Note +how the upper bits of those same words are not reduced modulo $\beta$. This is because those values will be discarded shortly and there is no +point. + +Step 5 will propagate the remainder of the carries upwards. On step 6 the columns are reduced modulo $\beta$ and shifted simultaneously as they are +stored in the destination $x$. + +EXAM,bn_fast_mp_montgomery_reduce.c + +The $\hat W$ array is first filled with digits of $x$ on line @49,for@ then the rest of the digits are zeroed on line @54,for@. Both loops share +the same alias variables to make the code easier to read. + +The value of $\mu$ is calculated in an interesting fashion. First the value $\hat W_{ix}$ is reduced modulo $\beta$ and cast to a mp\_digit. This +forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision. Line @101,>>@ fixes the carry +for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$. + +The for loop on line @113,for@ propagates the rest of the carries upwards through the columns. The for loop on line @126,for@ reduces the columns +modulo $\beta$ and shifts them $k$ places at the same time. The alias $\_ \hat W$ actually refers to the array $\hat W$ starting at the $n.used$'th +digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$. + +\subsection{Montgomery Setup} +To calculate the variable $\rho$ a relatively simple algorithm will be required. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_montgomery\_setup}. \\ +\textbf{Input}. mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\ +\textbf{Output}. $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\ +\hline \\ +1. $b \leftarrow n_0$ \\ +2. If $b$ is even return(\textit{MP\_VAL}) \\ +3. $x \leftarrow (((b + 2) \mbox{ AND } 4) << 1) + b$ \\ +4. for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\ +\hspace{3mm}4.1 $x \leftarrow x \cdot (2 - bx)$ \\ +5. $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\ +6. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_montgomery\_setup} +\end{figure} + +\textbf{Algorithm mp\_montgomery\_setup.} +This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms. It uses a very interesting trick +to calculate $1/n_0$ when $\beta$ is a power of two. + +EXAM,bn_mp_montgomery_setup.c + +This source code computes the value of $\rho$ required to perform Montgomery reduction. It has been modified to avoid performing excess +multiplications when $\beta$ is not the default 28-bits. + +\section{The Diminished Radix Algorithm} +The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett +or Montgomery methods for certain forms of moduli. The technique is based on the following simple congruence. + +\begin{equation} +(x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)} +\end{equation} + +This observation was used in the MMB \cite{MMB} block cipher to create a diffusion primitive. It used the fact that if $n = 2^{31}$ and $k=1$ that +then a x86 multiplier could produce the 62-bit product and use the ``shrd'' instruction to perform a double-precision right shift. The proof +of the above equation is very simple. First write $x$ in the product form. + +\begin{equation} +x = qn + r +\end{equation} + +Now reduce both sides modulo $(n - k)$. + +\begin{equation} +x \equiv qk + r \mbox{ (mod }(n-k)\mbox{)} +\end{equation} + +The variable $n$ reduces modulo $n - k$ to $k$. By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$ +into the equation the original congruence is reproduced, thus concluding the proof. The following algorithm is based on this observation. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Diminished Radix Reduction}. \\ +\textbf{Input}. Integer $x$, $n$, $k$ \\ +\textbf{Output}. $x \mbox{ mod } (n - k)$ \\ +\hline \\ +1. $q \leftarrow \lfloor x / n \rfloor$ \\ +2. $q \leftarrow k \cdot q$ \\ +3. $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\ +4. $x \leftarrow x + q$ \\ +5. If $x \ge (n - k)$ then \\ +\hspace{3mm}5.1 $x \leftarrow x - (n - k)$ \\ +\hspace{3mm}5.2 Goto step 1. \\ +6. Return $x$ \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Diminished Radix Reduction} +\label{fig:DR} +\end{figure} + +This algorithm will reduce $x$ modulo $n - k$ and return the residue. If $0 \le x < (n - k)^2$ then the algorithm will loop almost always +once or twice and occasionally three times. For simplicity sake the value of $x$ is bounded by the following simple polynomial. + +\begin{equation} +0 \le x < n^2 + k^2 - 2nk +\end{equation} + +The true bound is $0 \le x < (n - k - 1)^2$ but this has quite a few more terms. The value of $q$ after step 1 is bounded by the following. + +\begin{equation} +q < n - 2k - k^2/n +\end{equation} + +Since $k^2$ is going to be considerably smaller than $n$ that term will always be zero. The value of $x$ after step 3 is bounded trivially as +$0 \le x < n$. By step four the sum $x + q$ is bounded by + +\begin{equation} +0 \le q + x < (k + 1)n - 2k^2 - 1 +\end{equation} + +With a second pass $q$ will be loosely bounded by $0 \le q < k^2$ after step 2 while $x$ will still be loosely bounded by $0 \le x < n$ after step 3. After the second pass it is highly unlike that the +sum in step 4 will exceed $n - k$. In practice fewer than three passes of the algorithm are required to reduce virtually every input in the +range $0 \le x < (n - k - 1)^2$. + +\begin{figure} +\begin{small} +\begin{center} +\begin{tabular}{|l|} +\hline +$x = 123456789, n = 256, k = 3$ \\ +\hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\ +$q \leftarrow q*k = 1446759$ \\ +$x \leftarrow x \mbox{ mod } n = 21$ \\ +$x \leftarrow x + q = 1446780$ \\ +$x \leftarrow x - (n - k) = 1446527$ \\ +\hline +$q \leftarrow \lfloor x/n \rfloor = 5650$ \\ +$q \leftarrow q*k = 16950$ \\ +$x \leftarrow x \mbox{ mod } n = 127$ \\ +$x \leftarrow x + q = 17077$ \\ +$x \leftarrow x - (n - k) = 16824$ \\ +\hline +$q \leftarrow \lfloor x/n \rfloor = 65$ \\ +$q \leftarrow q*k = 195$ \\ +$x \leftarrow x \mbox{ mod } n = 184$ \\ +$x \leftarrow x + q = 379$ \\ +$x \leftarrow x - (n - k) = 126$ \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Example Diminished Radix Reduction} +\label{fig:EXDR} +\end{figure} + +Figure~\ref{fig:EXDR} demonstrates the reduction of $x = 123456789$ modulo $n - k = 253$ when $n = 256$ and $k = 3$. Note that even while $x$ +is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast. In this case only +three passes were required to find the residue $x \equiv 126$. + + +\subsection{Choice of Moduli} +On the surface this algorithm looks like a very expensive algorithm. It requires a couple of subtractions followed by multiplication and other +modular reductions. The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen. + +Division in general is a very expensive operation to perform. The one exception is when the division is by a power of the radix of representation used. +Division by ten for example is simple for pencil and paper mathematics since it amounts to shifting the decimal place to the right. Similarly division +by two (\textit{or powers of two}) is very simple for binary computers to perform. It would therefore seem logical to choose $n$ of the form $2^p$ +which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits. + +However, there is one operation related to division of power of twos that is even faster than this. If $n = \beta^p$ then the division may be +performed by moving whole digits to the right $p$ places. In practice division by $\beta^p$ is much faster than division by $2^p$ for any $p$. +Also with the choice of $n = \beta^p$ reducing $x$ modulo $n$ merely requires zeroing the digits above the $p-1$'th digit of $x$. + +Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted +modulus'' will refer to a modulus of the form $2^p - k$. The word ``restricted'' in this case refers to the fact that it is based on the +$2^p$ logic except $p$ must be a multiple of $lg(\beta)$. + +\subsection{Choice of $k$} +Now that division and reduction (\textit{step 1 and 3 of figure~\ref{fig:DR}}) have been optimized to simple digit operations the multiplication by $k$ +in step 2 is the most expensive operation. Fortunately the choice of $k$ is not terribly limited. For all intents and purposes it might +as well be a single digit. The smaller the value of $k$ is the faster the algorithm will be. + +\subsection{Restricted Diminished Radix Reduction} +The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$. This algorithm can reduce +an input $x$ within the range $0 \le x < n^2$ using only a couple passes of the algorithm demonstrated in figure~\ref{fig:DR}. The implementation +of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition +of $x$ and $q$. The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular +exponentiations are performed. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_dr\_reduce}. \\ +\textbf{Input}. mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\ +\hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\ +\textbf{Output}. $x \mbox{ mod } n$ \\ +\hline \\ +1. $m \leftarrow n.used$ \\ +2. If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\ +3. $\mu \leftarrow 0$ \\ +4. for $i$ from $0$ to $m - 1$ do \\ +\hspace{3mm}4.1 $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\ +\hspace{3mm}4.2 $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}4.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +5. $x_{m} \leftarrow \mu$ \\ +6. for $i$ from $m + 1$ to $x.used - 1$ do \\ +\hspace{3mm}6.1 $x_{i} \leftarrow 0$ \\ +7. Clamp excess digits of $x$. \\ +8. If $x \ge n$ then \\ +\hspace{3mm}8.1 $x \leftarrow x - n$ \\ +\hspace{3mm}8.2 Goto step 3. \\ +9. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_dr\_reduce} +\end{figure} + +\textbf{Algorithm mp\_dr\_reduce.} +This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$. It has similar restrictions to that of the Barrett reduction +with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$. + +This algorithm essentially implements the pseudo-code in figure~\ref{fig:DR} except with a slight optimization. The division by $\beta^m$, multiplication by $k$ +and addition of $x \mbox{ mod }\beta^m$ are all performed simultaneously inside the loop on step 4. The division by $\beta^m$ is emulated by accessing +the term at the $m+i$'th position which is subsequently multiplied by $k$ and added to the term at the $i$'th position. After the loop the $m$'th +digit is set to the carry and the upper digits are zeroed. Steps 5 and 6 emulate the reduction modulo $\beta^m$ that should have happend to +$x$ before the addition of the multiple of the upper half. + +At step 8 if $x$ is still larger than $n$ another pass of the algorithm is required. First $n$ is subtracted from $x$ and then the algorithm resumes +at step 3. + +EXAM,bn_mp_dr_reduce.c + +The first step is to grow $x$ as required to $2m$ digits since the reduction is performed in place on $x$. The label on line @49,top:@ is where +the algorithm will resume if further reduction passes are required. In theory it could be placed at the top of the function however, the size of +the modulus and question of whether $x$ is large enough are invariant after the first pass meaning that it would be a waste of time. + +The aliases $tmpx1$ and $tmpx2$ refer to the digits of $x$ where the latter is offset by $m$ digits. By reading digits from $x$ offset by $m$ digits +a division by $\beta^m$ can be simulated virtually for free. The loop on line @61,for@ performs the bulk of the work (\textit{corresponds to step 4 of algorithm 7.11}) +in this algorithm. + +By line @68,mu@ the pointer $tmpx1$ points to the $m$'th digit of $x$ which is where the final carry will be placed. Similarly by line @71,for@ the +same pointer will point to the $m+1$'th digit where the zeroes will be placed. + +Since the algorithm is only valid if both $x$ and $n$ are greater than zero an unsigned comparison suffices to determine if another pass is required. +With the same logic at line @82,sub@ the value of $x$ is known to be greater than or equal to $n$ meaning that an unsigned subtraction can be used +as well. Since the destination of the subtraction is the larger of the inputs the call to algorithm s\_mp\_sub cannot fail and the return code +does not need to be checked. + +\subsubsection{Setup} +To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required. This algorithm is not really complicated but provided for +completeness. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_dr\_setup}. \\ +\textbf{Input}. mp\_int $n$ \\ +\textbf{Output}. $k = \beta - n_0$ \\ +\hline \\ +1. $k \leftarrow \beta - n_0$ \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_dr\_setup} +\end{figure} + +EXAM,bn_mp_dr_setup.c + +\subsubsection{Modulus Detection} +Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus. An integer is said to be +of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\ +\textbf{Input}. mp\_int $n$ \\ +\textbf{Output}. $1$ if $n$ is in D.R form, $0$ otherwise \\ +\hline +1. If $n.used < 2$ then return($0$). \\ +2. for $ix$ from $1$ to $n.used - 1$ do \\ +\hspace{3mm}2.1 If $n_{ix} \ne \beta - 1$ return($0$). \\ +3. Return($1$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_dr\_is\_modulus} +\end{figure} + +\textbf{Algorithm mp\_dr\_is\_modulus.} +This algorithm determines if a value is in Diminished Radix form. Step 1 rejects obvious cases where fewer than two digits are +in the mp\_int. Step 2 tests all but the first digit to see if they are equal to $\beta - 1$. If the algorithm manages to get to +step 3 then $n$ must be of Diminished Radix form. + +EXAM,bn_mp_dr_is_modulus.c + +\subsection{Unrestricted Diminished Radix Reduction} +The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$. This algorithm +is a straightforward adaptation of algorithm~\ref{fig:DR}. + +In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead. However, this new +algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_reduce\_2k}. \\ +\textbf{Input}. mp\_int $a$ and $n$. mp\_digit $k$ \\ +\hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\ +\textbf{Output}. $a \mbox{ (mod }n\mbox{)}$ \\ +\hline +1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ +2. While $a \ge n$ do \\ +\hspace{3mm}2.1 $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\ +\hspace{3mm}2.2 $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\ +\hspace{3mm}2.3 $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\ +\hspace{3mm}2.4 $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\ +\hspace{3mm}2.5 If $a \ge n$ then do \\ +\hspace{6mm}2.5.1 $a \leftarrow a - n$ \\ +3. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_reduce\_2k} +\end{figure} + +\textbf{Algorithm mp\_reduce\_2k.} +This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$. Division by $2^p$ is emulated with a right +shift which makes the algorithm fairly inexpensive to use. + +EXAM,bn_mp_reduce_2k.c + +The algorithm mp\_count\_bits calculates the number of bits in an mp\_int which is used to find the initial value of $p$. The call to mp\_div\_2d +on line @31,mp_div_2d@ calculates both the quotient $q$ and the remainder $a$ required. By doing both in a single function call the code size +is kept fairly small. The multiplication by $k$ is only performed if $k > 1$. This allows reductions modulo $2^p - 1$ to be performed without +any multiplications. + +The unsigned s\_mp\_add, mp\_cmp\_mag and s\_mp\_sub are used in place of their full sign counterparts since the inputs are only valid if they are +positive. By using the unsigned versions the overhead is kept to a minimum. + +\subsubsection{Unrestricted Setup} +To setup this reduction algorithm the value of $k = 2^p - n$ is required. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\ +\textbf{Input}. mp\_int $n$ \\ +\textbf{Output}. $k = 2^p - n$ \\ +\hline +1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ +2. $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\ +3. $x \leftarrow x - n$ (\textit{mp\_sub}) \\ +4. $k \leftarrow x_0$ \\ +5. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_reduce\_2k\_setup} +\end{figure} + +\textbf{Algorithm mp\_reduce\_2k\_setup.} +This algorithm computes the value of $k$ required for the algorithm mp\_reduce\_2k. By making a temporary variable $x$ equal to $2^p$ a subtraction +is sufficient to solve for $k$. Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$. + +EXAM,bn_mp_reduce_2k_setup.c + +\subsubsection{Unrestricted Detection} +An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true. + +\begin{enumerate} +\item The number has only one digit. +\item The number has more than one digit and every bit from the $\beta$'th to the most significant is one. +\end{enumerate} + +If either condition is true than there is a power of two $2^p$ such that $0 < 2^p - n < \beta$. If the input is only +one digit than it will always be of the correct form. Otherwise all of the bits above the first digit must be one. This arises from the fact +that there will be value of $k$ that when added to the modulus causes a carry in the first digit which propagates all the way to the most +significant bit. The resulting sum will be a power of two. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\ +\textbf{Input}. mp\_int $n$ \\ +\textbf{Output}. $1$ if of proper form, $0$ otherwise \\ +\hline +1. If $n.used = 0$ then return($0$). \\ +2. If $n.used = 1$ then return($1$). \\ +3. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ +4. for $x$ from $lg(\beta)$ to $p$ do \\ +\hspace{3mm}4.1 If the ($x \mbox{ mod }lg(\beta)$)'th bit of the $\lfloor x / lg(\beta) \rfloor$ of $n$ is zero then return($0$). \\ +5. Return($1$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_reduce\_is\_2k} +\end{figure} + +\textbf{Algorithm mp\_reduce\_is\_2k.} +This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly. + +EXAM,bn_mp_reduce_is_2k.c + + + +\section{Algorithm Comparison} +So far three very different algorithms for modular reduction have been discussed. Each of the algorithms have their own strengths and weaknesses +that makes having such a selection very useful. The following table sumarizes the three algorithms along with comparisons of work factors. Since +all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table. + +\begin{center} +\begin{small} +\begin{tabular}{|c|c|c|c|c|c|} +\hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\ +\hline Barrett & $m^2 + 2m - 1$ & None & $79$ & $1087$ & $4223$ \\ +\hline Montgomery & $m^2 + m$ & $n$ must be odd & $72$ & $1056$ & $4160$ \\ +\hline D.R. & $2m$ & $n = \beta^m - k$ & $16$ & $64$ & $128$ \\ +\hline +\end{tabular} +\end{small} +\end{center} + +In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete. However, in practice since Montgomery +reduction can be written as a single function with the Comba technique it is much faster. Barrett reduction suffers from the overhead of +calling the half precision multipliers, addition and division by $\beta$ algorithms. + +For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice. The one set of algorithms where Diminished Radix reduction truly +shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}. In these algorithms +primes of the form $\beta^m - k$ can be found and shared amongst users. These primes will allow the Diminished Radix algorithm to be used in +modular exponentiation to greatly speed up the operation. + + + +\section*{Exercises} +\begin{tabular}{cl} +$\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\ + & calculates the correct value of $\rho$. \\ + & \\ +$\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly. \\ + & \\ +$\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\ + & (\textit{figure~\ref{fig:DR}}) terminates. Also prove the probability that it will \\ + & terminate within $1 \le k \le 10$ iterations. \\ + & \\ +\end{tabular} + + +\chapter{Exponentiation} +Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$. A variant of exponentiation, computed +in a finite field or ring, is called modular exponentiation. This latter style of operation is typically used in public key +cryptosystems such as RSA and Diffie-Hellman. The ability to quickly compute modular exponentiations is of great benefit to any +such cryptosystem and many methods have been sought to speed it up. + +\section{Exponentiation Basics} +A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired. However, as $b$ grows in size +the number of multiplications becomes prohibitive. Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature +with a $1024$-bit key. Such a calculation could never be completed as it would take simply far too long. + +Fortunately there is a very simple algorithm based on the laws of exponents. Recall that $lg_a(a^b) = b$ and that $lg_a(a^ba^c) = b + c$ which +are two trivial relationships between the base and the exponent. Let $b_i$ represent the $i$'th bit of $b$ starting from the least +significant bit. If $b$ is a $k$-bit integer than the following equation is true. + +\begin{equation} +a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i} +\end{equation} + +By taking the base $a$ logarithm of both sides of the equation the following equation is the result. + +\begin{equation} +b = \sum_{i=0}^{k-1}2^i \cdot b_i +\end{equation} + +The term $a^{2^i}$ can be found from the $i - 1$'th term by squaring the term since $\left ( a^{2^i} \right )^2$ is equal to +$a^{2^{i+1}}$. This observation forms the basis of essentially all fast exponentiation algorithms. It requires $k$ squarings and on average +$k \over 2$ multiplications to compute the result. This is indeed quite an improvement over simply multiplying by $a$ a total of $b-1$ times. + +While this current method is a considerable speed up there are further improvements to be made. For example, the $a^{2^i}$ term does not need to +be computed in an auxilary variable. Consider the following equivalent algorithm. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Left to Right Exponentiation}. \\ +\textbf{Input}. Integer $a$, $b$ and $k$ \\ +\textbf{Output}. $c = a^b$ \\ +\hline \\ +1. $c \leftarrow 1$ \\ +2. for $i$ from $k - 1$ to $0$ do \\ +\hspace{3mm}2.1 $c \leftarrow c^2$ \\ +\hspace{3mm}2.2 $c \leftarrow c \cdot a^{b_i}$ \\ +3. Return $c$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Left to Right Exponentiation} +\label{fig:LTOR} +\end{figure} + +This algorithm starts from the most significant bit and works towards the least significant bit. When the $i$'th bit of $b$ is set $a$ is +multiplied against the current product. In each iteration the product is squared which doubles the exponent of the individual terms of the +product. + +For example, let $b = 101100_2 \equiv 44_{10}$. The following chart demonstrates the actions of the algorithm. + +\newpage\begin{figure} +\begin{center} +\begin{tabular}{|c|c|} +\hline \textbf{Value of $i$} & \textbf{Value of $c$} \\ +\hline - & $1$ \\ +\hline $5$ & $a$ \\ +\hline $4$ & $a^2$ \\ +\hline $3$ & $a^4 \cdot a$ \\ +\hline $2$ & $a^8 \cdot a^2 \cdot a$ \\ +\hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\ +\hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\ +\hline +\end{tabular} +\end{center} +\caption{Example of Left to Right Exponentiation} +\end{figure} + +When the product $a^{32} \cdot a^8 \cdot a^4$ is simplified it is equal $a^{44}$ which is the desired exponentiation. This particular algorithm is +called ``Left to Right'' because it reads the exponent in that order. All of the exponentiation algorithms that will be presented are of this nature. + +\subsection{Single Digit Exponentiation} +The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit. It is intended +to be used when a small power of an input is required (\textit{e.g. $a^5$}). It is faster than simply multiplying $b - 1$ times for all values of +$b$ that are greater than three. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_expt\_d}. \\ +\textbf{Input}. mp\_int $a$ and mp\_digit $b$ \\ +\textbf{Output}. $c = a^b$ \\ +\hline \\ +1. $g \leftarrow a$ (\textit{mp\_init\_copy}) \\ +2. $c \leftarrow 1$ (\textit{mp\_set}) \\ +3. for $x$ from 1 to $lg(\beta)$ do \\ +\hspace{3mm}3.1 $c \leftarrow c^2$ (\textit{mp\_sqr}) \\ +\hspace{3mm}3.2 If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\ +\hspace{6mm}3.2.1 $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\ +\hspace{3mm}3.3 $b \leftarrow b << 1$ \\ +4. Clear $g$. \\ +5. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_expt\_d} +\end{figure} + +\textbf{Algorithm mp\_expt\_d.} +This algorithm computes the value of $a$ raised to the power of a single digit $b$. It uses the left to right exponentiation algorithm to +quickly compute the exponentiation. It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the +exponent is a fixed width. + +A copy of $a$ is made first to allow destination variable $c$ be the same as the source variable $a$. The result is set to the initial value of +$1$ in the subsequent step. + +Inside the loop the exponent is read from the most significant bit first down to the least significant bit. First $c$ is invariably squared +on step 3.1. In the following step if the most significant bit of $b$ is one the copy of $a$ is multiplied against $c$. The value +of $b$ is shifted left one bit to make the next bit down from the most signficant bit the new most significant bit. In effect each +iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location. + +EXAM,bn_mp_expt_d.c + +Line @29,mp_set@ sets the initial value of the result to $1$. Next the loop on line @31,for@ steps through each bit of the exponent starting from +the most significant down towards the least significant. The invariant squaring operation placed on line @333,mp_sqr@ is performed first. After +the squaring the result $c$ is multiplied by the base $g$ if and only if the most significant bit of the exponent is set. The shift on line +@47,<<@ moves all of the bits of the exponent upwards towards the most significant location. + +\section{$k$-ary Exponentiation} +When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor +slower than squaring. Recall from the previous algorithm that $b_{i}$ refers to the $i$'th bit of the exponent $b$. Suppose instead it referred to +the $i$'th $k$-bit digit of the exponent of $b$. For $k = 1$ the definitions are synonymous and for $k > 1$ algorithm~\ref{fig:KARY} +computes the same exponentiation. A group of $k$ bits from the exponent is called a \textit{window}. That is it is a small window on only a +portion of the entire exponent. Consider the following modification to the basic left to right exponentiation algorithm. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{$k$-ary Exponentiation}. \\ +\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\ +\textbf{Output}. $c = a^b$ \\ +\hline \\ +1. $c \leftarrow 1$ \\ +2. for $i$ from $t - 1$ to $0$ do \\ +\hspace{3mm}2.1 $c \leftarrow c^{2^k} $ \\ +\hspace{3mm}2.2 Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\ +\hspace{3mm}2.3 $c \leftarrow c \cdot a^g$ \\ +3. Return $c$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{$k$-ary Exponentiation} +\label{fig:KARY} +\end{figure} + +The squaring on step 2.1 can be calculated by squaring the value $c$ successively $k$ times. If the values of $a^g$ for $0 < g < 2^k$ have been +precomputed this algorithm requires only $t$ multiplications and $tk$ squarings. The table can be generated with $2^{k - 1} - 1$ squarings and +$2^{k - 1} + 1$ multiplications. This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$. +However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}. + +Suppose $k = 4$ and $t = 100$. This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation. The +original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value. The total number of squarings +has increased slightly but the number of multiplications has nearly halved. + +\subsection{Optimal Values of $k$} +An optimal value of $k$ will minimize $2^{k} + \lceil n / k \rceil + n - 1$ for a fixed number of bits in the exponent $n$. The simplest +approach is to brute force search amongst the values $k = 2, 3, \ldots, 8$ for the lowest result. Table~\ref{fig:OPTK} lists optimal values of $k$ +for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}. + +\begin{figure}[here] +\begin{center} +\begin{small} +\begin{tabular}{|c|c|c|c|c|c|} +\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\ +\hline $16$ & $2$ & $27$ & $24$ \\ +\hline $32$ & $3$ & $49$ & $48$ \\ +\hline $64$ & $3$ & $92$ & $96$ \\ +\hline $128$ & $4$ & $175$ & $192$ \\ +\hline $256$ & $4$ & $335$ & $384$ \\ +\hline $512$ & $5$ & $645$ & $768$ \\ +\hline $1024$ & $6$ & $1257$ & $1536$ \\ +\hline $2048$ & $6$ & $2452$ & $3072$ \\ +\hline $4096$ & $7$ & $4808$ & $6144$ \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Optimal Values of $k$ for $k$-ary Exponentiation} +\label{fig:OPTK} +\end{figure} + +\subsection{Sliding-Window Exponentiation} +A simple modification to the previous algorithm is only generate the upper half of the table in the range $2^{k-1} \le g < 2^k$. Essentially +this is a table for all values of $g$ where the most significant bit of $g$ is a one. However, in order for this to be allowed in the +algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided. + +Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}. + +\begin{figure}[here] +\begin{center} +\begin{small} +\begin{tabular}{|c|c|c|c|c|c|} +\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\ +\hline $16$ & $3$ & $24$ & $27$ \\ +\hline $32$ & $3$ & $45$ & $49$ \\ +\hline $64$ & $4$ & $87$ & $92$ \\ +\hline $128$ & $4$ & $167$ & $175$ \\ +\hline $256$ & $5$ & $322$ & $335$ \\ +\hline $512$ & $6$ & $628$ & $645$ \\ +\hline $1024$ & $6$ & $1225$ & $1257$ \\ +\hline $2048$ & $7$ & $2403$ & $2452$ \\ +\hline $4096$ & $8$ & $4735$ & $4808$ \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Optimal Values of $k$ for Sliding Window Exponentiation} +\label{fig:OPTK2} +\end{figure} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\ +\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\ +\textbf{Output}. $c = a^b$ \\ +\hline \\ +1. $c \leftarrow 1$ \\ +2. for $i$ from $t - 1$ to $0$ do \\ +\hspace{3mm}2.1 If the $i$'th bit of $b$ is a zero then \\ +\hspace{6mm}2.1.1 $c \leftarrow c^2$ \\ +\hspace{3mm}2.2 else do \\ +\hspace{6mm}2.2.1 $c \leftarrow c^{2^k}$ \\ +\hspace{6mm}2.2.2 Extract the $k$ bits from $(b_{i}b_{i-1}\ldots b_{i-(k-1)})$ and store it in $g$. \\ +\hspace{6mm}2.2.3 $c \leftarrow c \cdot a^g$ \\ +\hspace{6mm}2.2.4 $i \leftarrow i - k$ \\ +3. Return $c$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Sliding Window $k$-ary Exponentiation} +\end{figure} + +Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent. While this +algorithm requires the same number of squarings it can potentially have fewer multiplications. The pre-computed table $a^g$ is also half +the size as the previous table. + +Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms. The first algorithm will divide the exponent up as +the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$. The second algorithm will break the +exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$. The single digit $0$ in the second representation are where +a single squaring took place instead of a squaring and multiplication. In total the first method requires $10$ multiplications and $18$ +squarings. The second method requires $8$ multiplications and $18$ squarings. + +In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster. + +\section{Modular Exponentiation} + +Modular exponentiation is essentially computing the power of a base within a finite field or ring. For example, computing +$d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation. Instead of first computing $a^b$ and then reducing it +modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation. + +This guarantees that any intermediate result is bounded by $0 \le d \le c^2 - 2c + 1$ and can be reduced modulo $c$ quickly using +one of the algorithms presented in ~REDUCTION~. + +Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first. This algorithm +will allow the exponent $b$ to be negative which is computed as $c \equiv \left (1 / a \right )^{\vert b \vert} \mbox{(mod }d\mbox{)}$. The +value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}). If no inverse exists the algorithm +terminates with an error. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_exptmod}. \\ +\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ +\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ +\hline \\ +1. If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\ +2. If $b.sign = MP\_NEG$ then \\ +\hspace{3mm}2.1 $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\ +\hspace{3mm}2.2 $x' \leftarrow \vert x \vert$ \\ +\hspace{3mm}2.3 Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\ +3. if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\ +\hspace{3mm}3.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\ +4. else \\ +\hspace{3mm}4.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_exptmod} +\end{figure} + +\textbf{Algorithm mp\_exptmod.} +The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod. It is a sliding window $k$-ary algorithm +which uses Barrett reduction to reduce the product modulo $p$. The second algorithm mp\_exptmod\_fast performs the same operation +except it uses either Montgomery or Diminished Radix reduction. The two latter reduction algorithms are clumped in the same exponentiation +algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}). + +EXAM,bn_mp_exptmod.c + +In order to keep the algorithms in a known state the first step on line @29,if@ is to reject any negative modulus as input. If the exponent is +negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$. The temporary variable $tmpG$ is assigned +the modular inverse of $G$ and $tmpX$ is assigned the absolute value of $X$. The algorithm will recuse with these new values with a positive +exponent. + +If the exponent is positive the algorithm resumes the exponentiation. Line @63,dr_@ determines if the modulus is of the restricted Diminished Radix +form. If it is not line @65,reduce@ attempts to determine if it is of a unrestricted Diminished Radix form. The integer $dr$ will take on one +of three values. + +\begin{enumerate} +\item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form. +\item $dr = 1$ means that the modulus is of restricted Diminished Radix form. +\item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form. +\end{enumerate} + +Line @69,if@ determines if the fast modular exponentiation algorithm can be used. It is allowed if $dr \ne 0$ or if the modulus is odd. Otherwise, +the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction. + +\subsection{Barrett Modular Exponentiation} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_exptmod}. \\ +\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ +\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ +\hline \\ +1. $k \leftarrow lg(x)$ \\ +2. $winsize \leftarrow \left \lbrace \begin{array}{ll} + 2 & \mbox{if }k \le 7 \\ + 3 & \mbox{if }7 < k \le 36 \\ + 4 & \mbox{if }36 < k \le 140 \\ + 5 & \mbox{if }140 < k \le 450 \\ + 6 & \mbox{if }450 < k \le 1303 \\ + 7 & \mbox{if }1303 < k \le 3529 \\ + 8 & \mbox{if }3529 < k \\ + \end{array} \right .$ \\ +3. Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\ +4. Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\ +5. $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\ +\\ +Setup the table of small powers of $g$. First find $g^{2^{winsize}}$ and then all multiples of it. \\ +6. $k \leftarrow 2^{winsize - 1}$ \\ +7. $M_{k} \leftarrow M_1$ \\ +8. for $ix$ from 0 to $winsize - 2$ do \\ +\hspace{3mm}8.1 $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr}) \\ +\hspace{3mm}8.2 $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\ +9. for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\ +\hspace{3mm}9.1 $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\ +\hspace{3mm}9.2 $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\ +10. $res \leftarrow 1$ \\ +\\ +Start Sliding Window. \\ +11. $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\ +12. Loop \\ +\hspace{3mm}12.1 $bitcnt \leftarrow bitcnt - 1$ \\ +\hspace{3mm}12.2 If $bitcnt = 0$ then do \\ +\hspace{6mm}12.2.1 If $digidx = -1$ goto step 13. \\ +\hspace{6mm}12.2.2 $buf \leftarrow x_{digidx}$ \\ +\hspace{6mm}12.2.3 $digidx \leftarrow digidx - 1$ \\ +\hspace{6mm}12.2.4 $bitcnt \leftarrow lg(\beta)$ \\ +Continued on next page. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm s\_mp\_exptmod} +\end{figure} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\ +\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ +\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ +\hline \\ +\hspace{3mm}12.3 $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\ +\hspace{3mm}12.4 $buf \leftarrow buf << 1$ \\ +\hspace{3mm}12.5 if $mode = 0$ and $y = 0$ then goto step 12. \\ +\hspace{3mm}12.6 if $mode = 1$ and $y = 0$ then do \\ +\hspace{6mm}12.6.1 $res \leftarrow res^2$ \\ +\hspace{6mm}12.6.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ +\hspace{6mm}12.6.3 Goto step 12. \\ +\hspace{3mm}12.7 $bitcpy \leftarrow bitcpy + 1$ \\ +\hspace{3mm}12.8 $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\ +\hspace{3mm}12.9 $mode \leftarrow 2$ \\ +\hspace{3mm}12.10 If $bitcpy = winsize$ then do \\ +\hspace{6mm}Window is full so perform the squarings and single multiplication. \\ +\hspace{6mm}12.10.1 for $ix$ from $0$ to $winsize -1$ do \\ +\hspace{9mm}12.10.1.1 $res \leftarrow res^2$ \\ +\hspace{9mm}12.10.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ +\hspace{6mm}12.10.2 $res \leftarrow res \cdot M_{bitbuf}$ \\ +\hspace{6mm}12.10.3 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ +\hspace{6mm}Reset the window. \\ +\hspace{6mm}12.10.4 $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\ +\\ +No more windows left. Check for residual bits of exponent. \\ +13. If $mode = 2$ and $bitcpy > 0$ then do \\ +\hspace{3mm}13.1 for $ix$ form $0$ to $bitcpy - 1$ do \\ +\hspace{6mm}13.1.1 $res \leftarrow res^2$ \\ +\hspace{6mm}13.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ +\hspace{6mm}13.1.3 $bitbuf \leftarrow bitbuf << 1$ \\ +\hspace{6mm}13.1.4 If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\ +\hspace{9mm}13.1.4.1 $res \leftarrow res \cdot M_{1}$ \\ +\hspace{9mm}13.1.4.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ +14. $y \leftarrow res$ \\ +15. Clear $res$, $mu$ and the $M$ array. \\ +16. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm s\_mp\_exptmod (continued)} +\end{figure} + +\textbf{Algorithm s\_mp\_exptmod.} +This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$. It takes advantage of the Barrett reduction +algorithm to keep the product small throughout the algorithm. + +The first two steps determine the optimal window size based on the number of bits in the exponent. The larger the exponent the +larger the window size becomes. After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated. This +table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$. + +After the table is allocated the first power of $g$ is found. Since $g \ge p$ is allowed it must be first reduced modulo $p$ to make +the rest of the algorithm more efficient. The first element of the table at $2^{winsize - 1}$ is found by squaring $M_1$ successively $winsize - 2$ +times. The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$. + +Now that the table is available the sliding window may begin. The following list describes the functions of all the variables in the window. +\begin{enumerate} +\item The variable $mode$ dictates how the bits of the exponent are interpreted. +\begin{enumerate} + \item When $mode = 0$ the bits are ignored since no non-zero bit of the exponent has been seen yet. For example, if the exponent were simply + $1$ then there would be $lg(\beta) - 1$ zero bits before the first non-zero bit. In this case bits are ignored until a non-zero bit is found. + \item When $mode = 1$ a non-zero bit has been seen before and a new $winsize$-bit window has not been formed yet. In this mode leading $0$ bits + are read and a single squaring is performed. If a non-zero bit is read a new window is created. + \item When $mode = 2$ the algorithm is in the middle of forming a window and new bits are appended to the window from the most significant bit + downwards. +\end{enumerate} +\item The variable $bitcnt$ indicates how many bits are left in the current digit of the exponent left to be read. When it reaches zero a new digit + is fetched from the exponent. +\item The variable $buf$ holds the currently read digit of the exponent. +\item The variable $digidx$ is an index into the exponents digits. It starts at the leading digit $x.used - 1$ and moves towards the trailing digit. +\item The variable $bitcpy$ indicates how many bits are in the currently formed window. When it reaches $winsize$ the window is flushed and + the appropriate operations performed. +\item The variable $bitbuf$ holds the current bits of the window being formed. +\end{enumerate} + +All of step 12 is the window processing loop. It will iterate while there are digits available form the exponent to read. The first step +inside this loop is to extract a new digit if no more bits are available in the current digit. If there are no bits left a new digit is +read and if there are no digits left than the loop terminates. + +After a digit is made available step 12.3 will extract the most significant bit of the current digit and move all other bits in the digit +upwards. In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to +trailing edges the entire exponent is read from most significant bit to least significant bit. + +At step 12.5 if the $mode$ and currently extracted bit $y$ are both zero the bit is ignored and the next bit is read. This prevents the +algorithm from having to perform trivial squaring and reduction operations before the first non-zero bit is read. Step 12.6 and 12.7-10 handle +the two cases of $mode = 1$ and $mode = 2$ respectively. + +FIGU,expt_state,Sliding Window State Diagram + +By step 13 there are no more digits left in the exponent. However, there may be partial bits in the window left. If $mode = 2$ then +a Left-to-Right algorithm is used to process the remaining few bits. + +EXAM,bn_s_mp_exptmod.c + +Lines @31,if@ through @45,}@ determine the optimal window size based on the length of the exponent in bits. The window divisions are sorted +from smallest to greatest so that in each \textbf{if} statement only one condition must be tested. For example, by the \textbf{if} statement +on line @37,if@ the value of $x$ is already known to be greater than $140$. + +The conditional piece of code beginning on line @42,ifdef@ allows the window size to be restricted to five bits. This logic is used to ensure +the table of precomputed powers of $G$ remains relatively small. + +The for loop on line @60,for@ initializes the $M$ array while lines @71,mp_init@ and @75,mp_reduce@ through @85,}@ initialize the reduction +function that will be used for this modulus. + +-- More later. + +\section{Quick Power of Two} +Calculating $b = 2^a$ can be performed much quicker than with any of the previous algorithms. Recall that a logical shift left $m << k$ is +equivalent to $m \cdot 2^k$. By this logic when $m = 1$ a quick power of two can be achieved. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_2expt}. \\ +\textbf{Input}. integer $b$ \\ +\textbf{Output}. $a \leftarrow 2^b$ \\ +\hline \\ +1. $a \leftarrow 0$ \\ +2. If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\ +3. $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\ +4. $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\ +5. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_2expt} +\end{figure} + +\textbf{Algorithm mp\_2expt.} + +EXAM,bn_mp_2expt.c + +\chapter{Higher Level Algorithms} + +This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package. These +routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important. + +The first section describes a method of integer division with remainder that is universally well known. It provides the signed division logic +for the package. The subsequent section discusses a set of algorithms which allow a single digit to be the 2nd operand for a variety of operations. +These algorithms serve mostly to simplify other algorithms where small constants are required. The last two sections discuss how to manipulate +various representations of integers. For example, converting from an mp\_int to a string of character. + +\section{Integer Division with Remainder} +\label{sec:division} + +Integer division aside from modular exponentiation is the most intensive algorithm to compute. Like addition, subtraction and multiplication +the basis of this algorithm is the long-hand division algorithm taught to school children. Throughout this discussion several common variables +will be used. Let $x$ represent the divisor and $y$ represent the dividend. Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and +let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$. The following simple algorithm will be used to start the discussion. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\ +\textbf{Input}. integer $x$ and $y$ \\ +\textbf{Output}. $q = \lfloor y/x\rfloor, r = y - xq$ \\ +\hline \\ +1. $q \leftarrow 0$ \\ +2. $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\ +3. for $t$ from $n$ down to $0$ do \\ +\hspace{3mm}3.1 Maximize $k$ such that $kx\beta^t$ is less than or equal to $y$ and $(k + 1)x\beta^t$ is greater. \\ +\hspace{3mm}3.2 $q \leftarrow q + k\beta^t$ \\ +\hspace{3mm}3.3 $y \leftarrow y - kx\beta^t$ \\ +4. $r \leftarrow y$ \\ +5. Return($q, r$) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Radix-$\beta$ Integer Division} +\label{fig:raddiv} +\end{figure} + +As children we are taught this very simple algorithm for the case of $\beta = 10$. Almost instinctively several optimizations are taught for which +their reason of existing are never explained. For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor. + +To find the first digit of the quotient the value of $k$ must be maximized such that $kx\beta^t$ is less than or equal to $y$ and +simultaneously $(k + 1)x\beta^t$ is greater than $y$. Implicitly $k$ is the maximum value the $t$'th digit of the quotient may have. The habitual method +used to find the maximum is to ``eyeball'' the two numbers, typically only the leading digits and quickly estimate a quotient. By only using leading +digits a much simpler division may be used to form an educated guess at what the value must be. In this case $k = \lfloor 54/23\rfloor = 2$ quickly +arises as a possible solution. Indeed $2x\beta^2 = 4600$ is less than $y = 5471$ and simultaneously $(k + 1)x\beta^2 = 6900$ is larger than $y$. +As a result $k\beta^2$ is added to the quotient which now equals $q = 200$ and $4600$ is subtracted from $y$ to give a remainder of $y = 841$. + +Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder +$y = 841 - 3x\beta = 181$. Finally the last iteration of the loop produces $k = 7$ which leads to the quotient $q = 230 + 7 = 237$ and the +remainder $y = 181 - 7x = 20$. The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since +$237 \cdot 23 + 20 = 5471$ is true. + +\subsection{Quotient Estimation} +\label{sec:divest} +As alluded to earlier the quotient digit $k$ can be estimated from only the leading digits of both the divisor and dividend. When $p$ leading +digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows. Technically +speaking the estimation is based on assuming the lower $\vert \vert y \vert \vert - p$ and $\vert \vert x \vert \vert - p$ lower digits of the +dividend and divisor are zero. + +The value of the estimation may off by a few values in either direction and in general is fairly correct. A simplification \cite[pp. 271]{TAOCPV2} +of the estimation technique is to use $t + 1$ digits of the dividend and $t$ digits of the divisor, in particularly when $t = 1$. The estimate +using this technique is never too small. For the following proof let $t = \vert \vert y \vert \vert - 1$ and $s = \vert \vert x \vert \vert - 1$ +represent the most significant digits of the dividend and divisor respectively. + +\textbf{Proof.}\textit{ The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to +$k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. } +The first obvious case is when $\hat k = \beta - 1$ in which case the proof is concluded since the real quotient cannot be larger. For all other +cases $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ and $\hat k x_s \ge y_t\beta + y_{t-1} - x_s + 1$. The latter portion of the inequalility +$-x_s + 1$ arises from the fact that a truncated integer division will give the same quotient for at most $x_s - 1$ values. Next a series of +inequalities will prove the hypothesis. + +\begin{equation} +y - \hat k x \le y - \hat k x_s\beta^s +\end{equation} + +This is trivially true since $x \ge x_s\beta^s$. Next we replace $\hat kx_s\beta^s$ by the previous inequality for $\hat kx_s$. + +\begin{equation} +y - \hat k x \le y_t\beta^t + \ldots + y_0 - (y_t\beta^t + y_{t-1}\beta^{t-1} - x_s\beta^t + \beta^s) +\end{equation} + +By simplifying the previous inequality the following inequality is formed. + +\begin{equation} +y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s +\end{equation} + +Subsequently, + +\begin{equation} +y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s < x_s\beta^s \le x +\end{equation} + +Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof. \textbf{QED} + + +\subsection{Normalized Integers} +For the purposes of division a normalized input is when the divisors leading digit $x_n$ is greater than or equal to $\beta / 2$. By multiplying both +$x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original +remainder. The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will +lie in the domain of a single digit. Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$. + +\begin{equation} +{{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta} +\end{equation} + +At most the quotient approaches $2\beta$, however, in practice this will not occur since that would imply the previous quotient digit was too small. + +\subsection{Radix-$\beta$ Division with Remainder} +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_div}. \\ +\textbf{Input}. mp\_int $a, b$ \\ +\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\ +\hline \\ +1. If $b = 0$ return(\textit{MP\_VAL}). \\ +2. If $\vert a \vert < \vert b \vert$ then do \\ +\hspace{3mm}2.1 $d \leftarrow a$ \\ +\hspace{3mm}2.2 $c \leftarrow 0$ \\ +\hspace{3mm}2.3 Return(\textit{MP\_OKAY}). \\ +\\ +Setup the quotient to receive the digits. \\ +3. Grow $q$ to $a.used + 2$ digits. \\ +4. $q \leftarrow 0$ \\ +5. $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\ +6. $sign \leftarrow \left \lbrace \begin{array}{ll} + MP\_ZPOS & \mbox{if }a.sign = b.sign \\ + MP\_NEG & \mbox{otherwise} \\ + \end{array} \right .$ \\ +\\ +Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\ +7. $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\ +8. $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\ +\\ +Find the leading digit of the quotient. \\ +9. $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\ +10. $y \leftarrow y \cdot \beta^{n - t}$ \\ +11. While ($x \ge y$) do \\ +\hspace{3mm}11.1 $q_{n - t} \leftarrow q_{n - t} + 1$ \\ +\hspace{3mm}11.2 $x \leftarrow x - y$ \\ +12. $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\ +\\ +Continued on the next page. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_div} +\end{figure} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_div} (continued). \\ +\textbf{Input}. mp\_int $a, b$ \\ +\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\ +\hline \\ +Now find the remainder fo the digits. \\ +13. for $i$ from $n$ down to $(t + 1)$ do \\ +\hspace{3mm}13.1 If $i > x.used$ then jump to the next iteration of this loop. \\ +\hspace{3mm}13.2 If $x_{i} = y_{t}$ then \\ +\hspace{6mm}13.2.1 $q_{i - t - 1} \leftarrow \beta - 1$ \\ +\hspace{3mm}13.3 else \\ +\hspace{6mm}13.3.1 $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\ +\hspace{6mm}13.3.2 $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\ +\hspace{6mm}13.3.3 $q_{i - t - 1} \leftarrow \hat r$ \\ +\hspace{3mm}13.4 $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\ +\\ +Fixup quotient estimation. \\ +\hspace{3mm}13.5 Loop \\ +\hspace{6mm}13.5.1 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\ +\hspace{6mm}13.5.2 t$1 \leftarrow 0$ \\ +\hspace{6mm}13.5.3 t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\ +\hspace{6mm}13.5.4 $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\ +\hspace{6mm}13.5.5 t$2_0 \leftarrow x_{i - 2}, $ t$2_1 \leftarrow x_{i - 1}, $ t$2_2 \leftarrow x_i, $ t$2.used \leftarrow 3$ \\ +\hspace{6mm}13.5.6 If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\ +\hspace{3mm}13.6 t$1 \leftarrow y \cdot q_{i - t - 1}$ \\ +\hspace{3mm}13.7 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\ +\hspace{3mm}13.8 $x \leftarrow x - $ t$1$ \\ +\hspace{3mm}13.9 If $x.sign = MP\_NEG$ then \\ +\hspace{6mm}13.10 t$1 \leftarrow y$ \\ +\hspace{6mm}13.11 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\ +\hspace{6mm}13.12 $x \leftarrow x + $ t$1$ \\ +\hspace{6mm}13.13 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\ +\\ +Finalize the result. \\ +14. Clamp excess digits of $q$ \\ +15. $c \leftarrow q, c.sign \leftarrow sign$ \\ +16. $x.sign \leftarrow a.sign$ \\ +17. $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\ +18. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_div (continued)} +\end{figure} +\textbf{Algorithm mp\_div.} +This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor. The algorithm is a signed +division and will produce a fully qualified quotient and remainder. + +First the divisor $b$ must be non-zero which is enforced in step one. If the divisor is larger than the dividend than the quotient is implicitly +zero and the remainder is the dividend. + +After the first two trivial cases of inputs are handled the variable $q$ is setup to receive the digits of the quotient. Two unsigned copies of the +divisor $y$ and dividend $x$ are made as well. The core of the division algorithm is an unsigned division and will only work if the values are +positive. Now the two values $x$ and $y$ must be normalized such that the leading digit of $y$ is greater than or equal to $\beta / 2$. +This is performed by shifting both to the left by enough bits to get the desired normalization. + +At this point the division algorithm can begin producing digits of the quotient. Recall that maximum value of the estimation used is +$2\beta - {2 \over \beta}$ which means that a digit of the quotient must be first produced by another means. In this case $y$ is shifted +to the left (\textit{step ten}) so that it has the same number of digits as $x$. The loop on step eleven will subtract multiples of the +shifted copy of $y$ until $x$ is smaller. Since the leading digit of $y$ is greater than or equal to $\beta/2$ this loop will iterate at most two +times to produce the desired leading digit of the quotient. + +Now the remainder of the digits can be produced. The equation $\hat q = \lfloor {{x_i \beta + x_{i-1}}\over y_t} \rfloor$ is used to fairly +accurately approximate the true quotient digit. The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by +induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$. + +Recall from section~\ref{sec:divest} that the estimation is never too low but may be too high. The next step of the estimation process is +to refine the estimation. The loop on step 13.5 uses $x_i\beta^2 + x_{i-1}\beta + x_{i-2}$ and $q_{i - t - 1}(y_t\beta + y_{t-1})$ as a higher +order approximation to adjust the quotient digit. + +After both phases of estimation the quotient digit may still be off by a value of one\footnote{This is similar to the error introduced +by optimizing Barrett reduction.}. Steps 13.6 and 13.7 subtract the multiple of the divisor from the dividend (\textit{Similar to step 3.3 of +algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large. + +Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the +remainder. An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC} +is that when the estimations are being made (\textit{inside the loop on step 13.5}) that the digits $y_{t-1}$, $x_{i-2}$ and $x_{i-1}$ may lie +outside their respective boundaries. For example, if $t = 0$ or $i \le 1$ then the digits would be undefined. In those cases the digits should +respectively be replaced with a zero. + +EXAM,bn_mp_div.c + +The implementation of this algorithm differs slightly from the pseudo code presented previously. In this algorithm either of the quotient $c$ or +remainder $d$ may be passed as a \textbf{NULL} pointer which indicates their value is not desired. For example, the C code to call the division +algorithm with only the quotient is + +\begin{verbatim} +mp_div(&a, &b, &c, NULL); /* c = [a/b] */ +\end{verbatim} + +Lines @108,if@ and @113,if@ handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor +respectively. After the two trivial cases all of the temporary variables are initialized. Line @147,neg@ determines the sign of +the quotient and line @148,sign@ ensures that both $x$ and $y$ are positive. + +The number of bits in the leading digit is calculated on line @151,norm@. Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits +of precision which when reduced modulo $lg(\beta)$ produces the value of $k$. In this case $k$ is the number of bits in the leading digit which is +exactly what is required. For the algorithm to operate $k$ must equal $lg(\beta) - 1$ and when it does not the inputs must be normalized by shifting +them to the left by $lg(\beta) - 1 - k$ bits. + +Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively. These are first used to produce the +leading digit of the quotient. The loop beginning on line @184,for@ will produce the remainder of the quotient digits. + +The conditional ``continue'' on line @186,continue@ is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the +algorithm eliminates multiple non-zero digits in a single iteration. This ensures that $x_i$ is always non-zero since by definition the digits +above the $i$'th position $x$ must be zero in order for the quotient to be precise\footnote{Precise as far as integer division is concerned.}. + +Lines @214,t1@, @216,t1@ and @222,t2@ through @225,t2@ manually construct the high accuracy estimations by setting the digits of the two mp\_int +variables directly. + +\section{Single Digit Helpers} + +This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants. All of +the helper functions assume the single digit input is positive and will treat them as such. + +\subsection{Single Digit Addition and Subtraction} + +Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction +algorithms. As a result these algorithms are subtantially simpler with a slight cost in performance. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_add\_d}. \\ +\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ +\textbf{Output}. $c = a + b$ \\ +\hline \\ +1. $t \leftarrow b$ (\textit{mp\_set}) \\ +2. $c \leftarrow a + t$ \\ +3. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_add\_d} +\end{figure} + +\textbf{Algorithm mp\_add\_d.} +This algorithm initiates a temporary mp\_int with the value of the single digit and uses algorithm mp\_add to add the two values together. + +EXAM,bn_mp_add_d.c + +Clever use of the letter 't'. + +\subsubsection{Subtraction} +The single digit subtraction algorithm mp\_sub\_d is essentially the same except it uses mp\_sub to subtract the digit from the mp\_int. + +\subsection{Single Digit Multiplication} +Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline +multiplication algorithm. Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands +only has one digit. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_mul\_d}. \\ +\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ +\textbf{Output}. $c = ab$ \\ +\hline \\ +1. $pa \leftarrow a.used$ \\ +2. Grow $c$ to at least $pa + 1$ digits. \\ +3. $oldused \leftarrow c.used$ \\ +4. $c.used \leftarrow pa + 1$ \\ +5. $c.sign \leftarrow a.sign$ \\ +6. $\mu \leftarrow 0$ \\ +7. for $ix$ from $0$ to $pa - 1$ do \\ +\hspace{3mm}7.1 $\hat r \leftarrow \mu + a_{ix}b$ \\ +\hspace{3mm}7.2 $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}7.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +8. $c_{pa} \leftarrow \mu$ \\ +9. for $ix$ from $pa + 1$ to $oldused$ do \\ +\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\ +10. Clamp excess digits of $c$. \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_mul\_d} +\end{figure} +\textbf{Algorithm mp\_mul\_d.} +This algorithm quickly multiplies an mp\_int by a small single digit value. It is specially tailored to the job and has a minimal of overhead. +Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations. + +EXAM,bn_mp_mul_d.c + +In this implementation the destination $c$ may point to the same mp\_int as the source $a$ since the result is written after the digit is +read from the source. This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively. + +\subsection{Single Digit Division} +Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion. Since the +divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_div\_d}. \\ +\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ +\textbf{Output}. $c = \lfloor a / b \rfloor, d = a - cb$ \\ +\hline \\ +1. If $b = 0$ then return(\textit{MP\_VAL}).\\ +2. If $b = 3$ then use algorithm mp\_div\_3 instead. \\ +3. Init $q$ to $a.used$ digits. \\ +4. $q.used \leftarrow a.used$ \\ +5. $q.sign \leftarrow a.sign$ \\ +6. $\hat w \leftarrow 0$ \\ +7. for $ix$ from $a.used - 1$ down to $0$ do \\ +\hspace{3mm}7.1 $\hat w \leftarrow \hat w \beta + a_{ix}$ \\ +\hspace{3mm}7.2 If $\hat w \ge b$ then \\ +\hspace{6mm}7.2.1 $t \leftarrow \lfloor \hat w / b \rfloor$ \\ +\hspace{6mm}7.2.2 $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\ +\hspace{3mm}7.3 else\\ +\hspace{6mm}7.3.1 $t \leftarrow 0$ \\ +\hspace{3mm}7.4 $q_{ix} \leftarrow t$ \\ +8. $d \leftarrow \hat w$ \\ +9. Clamp excess digits of $q$. \\ +10. $c \leftarrow q$ \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_div\_d} +\end{figure} +\textbf{Algorithm mp\_div\_d.} +This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach. Essentially in every iteration of the +algorithm another digit of the dividend is reduced and another digit of quotient produced. Provided $b < \beta$ the value of $\hat w$ +after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$. + +If the divisor $b$ is equal to three a variant of this algorithm is used which is called mp\_div\_3. It replaces the division by three with +a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup. In essence it is much like the Barrett reduction +from chapter seven. + +EXAM,bn_mp_div_d.c + +Like the implementation of algorithm mp\_div this algorithm allows either of the quotient or remainder to be passed as a \textbf{NULL} pointer to +indicate the respective value is not required. This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created. + +The division and remainder on lines @44,/@ and @45,%@ can be replaced often by a single division on most processors. For example, the 32-bit x86 based +processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously. Unfortunately the GCC +compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively. + +\subsection{Single Digit Root Extraction} + +Finding the $n$'th root of an integer is fairly easy as far as numerical analysis is concerned. Algorithms such as the Newton-Raphson approximation +(\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$. + +\begin{equation} +x_{i+1} = x_i - {f(x_i) \over f'(x_i)} +\label{eqn:newton} +\end{equation} + +In this case the $n$'th root is desired and $f(x) = x^n - a$ where $a$ is the integer of which the root is desired. The derivative of $f(x)$ is +simply $f'(x) = nx^{n - 1}$. Of particular importance is that this algorithm will be used over the integers not over the a more continuous domain +such as the real numbers. As a result the root found can be above the true root by few and must be manually adjusted. Ideally at the end of the +algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_n\_root}. \\ +\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ +\textbf{Output}. $c^b \le a$ \\ +\hline \\ +1. If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\ +2. $sign \leftarrow a.sign$ \\ +3. $a.sign \leftarrow MP\_ZPOS$ \\ +4. t$2 \leftarrow 2$ \\ +5. Loop \\ +\hspace{3mm}5.1 t$1 \leftarrow $ t$2$ \\ +\hspace{3mm}5.2 t$3 \leftarrow $ t$1^{b - 1}$ \\ +\hspace{3mm}5.3 t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\ +\hspace{3mm}5.4 t$2 \leftarrow $ t$2 - a$ \\ +\hspace{3mm}5.5 t$3 \leftarrow $ t$3 \cdot b$ \\ +\hspace{3mm}5.6 t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\ +\hspace{3mm}5.7 t$2 \leftarrow $ t$1 - $ t$3$ \\ +\hspace{3mm}5.8 If t$1 \ne $ t$2$ then goto step 5. \\ +6. Loop \\ +\hspace{3mm}6.1 t$2 \leftarrow $ t$1^b$ \\ +\hspace{3mm}6.2 If t$2 > a$ then \\ +\hspace{6mm}6.2.1 t$1 \leftarrow $ t$1 - 1$ \\ +\hspace{6mm}6.2.2 Goto step 6. \\ +7. $a.sign \leftarrow sign$ \\ +8. $c \leftarrow $ t$1$ \\ +9. $c.sign \leftarrow sign$ \\ +10. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_n\_root} +\end{figure} +\textbf{Algorithm mp\_n\_root.} +This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach. It is partially optimized based on the observation +that the numerator of ${f(x) \over f'(x)}$ can be derived from a partial denominator. That is at first the denominator is calculated by finding +$x^{b - 1}$. This value can then be multiplied by $x$ and have $a$ subtracted from it to find the numerator. This saves a total of $b - 1$ +multiplications by t$1$ inside the loop. + +The initial value of the approximation is t$2 = 2$ which allows the algorithm to start with very small values and quickly converge on the +root. Ideally this algorithm is meant to find the $n$'th root of an input where $n$ is bounded by $2 \le n \le 5$. + +EXAM,bn_mp_n_root.c + +\section{Random Number Generation} + +Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms. Pollard-Rho +factoring for example, can make use of random values as starting points to find factors of a composite integer. In this case the algorithm presented +is solely for simulations and not intended for cryptographic use. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_rand}. \\ +\textbf{Input}. An integer $b$ \\ +\textbf{Output}. A pseudo-random number of $b$ digits \\ +\hline \\ +1. $a \leftarrow 0$ \\ +2. If $b \le 0$ return(\textit{MP\_OKAY}) \\ +3. Pick a non-zero random digit $d$. \\ +4. $a \leftarrow a + d$ \\ +5. for $ix$ from 1 to $d - 1$ do \\ +\hspace{3mm}5.1 $a \leftarrow a \cdot \beta$ \\ +\hspace{3mm}5.2 Pick a random digit $d$. \\ +\hspace{3mm}5.3 $a \leftarrow a + d$ \\ +6. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_rand} +\end{figure} +\textbf{Algorithm mp\_rand.} +This algorithm produces a pseudo-random integer of $b$ digits. By ensuring that the first digit is non-zero the algorithm also guarantees that the +final result has at least $b$ digits. It relies heavily on a third-part random number generator which should ideally generate uniformly all of +the integers from $0$ to $\beta - 1$. + +EXAM,bn_mp_rand.c + +\section{Formatted Representations} +The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties. For example, the ability to +be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers +into a program. + +\subsection{Reading Radix-n Input} +For the purposes of this text we will assume that a simple lower ASCII map (\ref{fig:ASC}) is used for the values of from $0$ to $63$ to +printable characters. For example, when the character ``N'' is read it represents the integer $23$. The first $16$ characters of the +map are for the common representations up to hexadecimal. After that they match the ``base64'' encoding scheme which are suitable chosen +such that they are printable. While outputting as base64 may not be too helpful for human operators it does allow communication via non binary +mediums. + +\newpage\begin{figure}[here] +\begin{center} +\begin{tabular}{cc|cc|cc|cc} +\hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} \\ +\hline +0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\ +4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\ +8 & 8 & 9 & 9 & 10 & A & 11 & B \\ +12 & C & 13 & D & 14 & E & 15 & F \\ +16 & G & 17 & H & 18 & I & 19 & J \\ +20 & K & 21 & L & 22 & M & 23 & N \\ +24 & O & 25 & P & 26 & Q & 27 & R \\ +28 & S & 29 & T & 30 & U & 31 & V \\ +32 & W & 33 & X & 34 & Y & 35 & Z \\ +36 & a & 37 & b & 38 & c & 39 & d \\ +40 & e & 41 & f & 42 & g & 43 & h \\ +44 & i & 45 & j & 46 & k & 47 & l \\ +48 & m & 49 & n & 50 & o & 51 & p \\ +52 & q & 53 & r & 54 & s & 55 & t \\ +56 & u & 57 & v & 58 & w & 59 & x \\ +60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\ +\hline +\end{tabular} +\end{center} +\caption{Lower ASCII Map} +\label{fig:ASC} +\end{figure} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_read\_radix}. \\ +\textbf{Input}. A string $str$ of length $sn$ and radix $r$. \\ +\textbf{Output}. The radix-$\beta$ equivalent mp\_int. \\ +\hline \\ +1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\ +2. $ix \leftarrow 0$ \\ +3. If $str_0 =$ ``-'' then do \\ +\hspace{3mm}3.1 $ix \leftarrow ix + 1$ \\ +\hspace{3mm}3.2 $sign \leftarrow MP\_NEG$ \\ +4. else \\ +\hspace{3mm}4.1 $sign \leftarrow MP\_ZPOS$ \\ +5. $a \leftarrow 0$ \\ +6. for $iy$ from $ix$ to $sn - 1$ do \\ +\hspace{3mm}6.1 Let $y$ denote the position in the map of $str_{iy}$. \\ +\hspace{3mm}6.2 If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\ +\hspace{3mm}6.3 $a \leftarrow a \cdot r$ \\ +\hspace{3mm}6.4 $a \leftarrow a + y$ \\ +7. If $a \ne 0$ then $a.sign \leftarrow sign$ \\ +8. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_read\_radix} +\end{figure} +\textbf{Algorithm mp\_read\_radix.} +This algorithm will read an ASCII string and produce the radix-$\beta$ mp\_int representation of the same integer. A minus symbol ``-'' may precede the +string to indicate the value is negative, otherwise it is assumed to be positive. The algorithm will read up to $sn$ characters from the input +and will stop when it reads a character it cannot map the algorithm stops reading characters from the string. This allows numbers to be embedded +as part of larger input without any significant problem. + +EXAM,bn_mp_read_radix.c + +\subsection{Generating Radix-$n$ Output} +Generating radix-$n$ output is fairly trivial with a division and remainder algorithm. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_toradix}. \\ +\textbf{Input}. A mp\_int $a$ and an integer $r$\\ +\textbf{Output}. The radix-$r$ representation of $a$ \\ +\hline \\ +1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\ +2. If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}). \\ +3. $t \leftarrow a$ \\ +4. $str \leftarrow$ ``'' \\ +5. if $t.sign = MP\_NEG$ then \\ +\hspace{3mm}5.1 $str \leftarrow str + $ ``-'' \\ +\hspace{3mm}5.2 $t.sign = MP\_ZPOS$ \\ +6. While ($t \ne 0$) do \\ +\hspace{3mm}6.1 $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\ +\hspace{3mm}6.2 $t \leftarrow \lfloor t / r \rfloor$ \\ +\hspace{3mm}6.3 Look up $d$ in the map and store the equivalent character in $y$. \\ +\hspace{3mm}6.4 $str \leftarrow str + y$ \\ +7. If $str_0 = $``$-$'' then \\ +\hspace{3mm}7.1 Reverse the digits $str_1, str_2, \ldots str_n$. \\ +8. Otherwise \\ +\hspace{3mm}8.1 Reverse the digits $str_0, str_1, \ldots str_n$. \\ +9. Return(\textit{MP\_OKAY}).\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_toradix} +\end{figure} +\textbf{Algorithm mp\_toradix.} +This algorithm computes the radix-$r$ representation of an mp\_int $a$. The ``digits'' of the representation are extracted by reducing +successive powers of $\lfloor a / r^k \rfloor$ the input modulo $r$ until $r^k > a$. Note that instead of actually dividing by $r^k$ in +each iteration the quotient $\lfloor a / r \rfloor$ is saved for the next iteration. As a result a series of trivial $n \times 1$ divisions +are required instead of a series of $n \times k$ divisions. One design flaw of this approach is that the digits are produced in the reverse order +(see~\ref{fig:mpradix}). To remedy this flaw the digits must be swapped or simply ``reversed''. + +\begin{figure} +\begin{center} +\begin{tabular}{|c|c|c|} +\hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\ +\hline $1234$ & -- & -- \\ +\hline $123$ & $4$ & ``4'' \\ +\hline $12$ & $3$ & ``43'' \\ +\hline $1$ & $2$ & ``432'' \\ +\hline $0$ & $1$ & ``4321'' \\ +\hline +\end{tabular} +\end{center} +\caption{Example of Algorithm mp\_toradix.} +\label{fig:mpradix} +\end{figure} + +EXAM,bn_mp_toradix.c + +\chapter{Number Theoretic Algorithms} +This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi +symbol computation. These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and +various Sieve based factoring algorithms. + +\section{Greatest Common Divisor} +The greatest common divisor of two integers $a$ and $b$, often denoted as $(a, b)$ is the largest integer $k$ that is a proper divisor of +both $a$ and $b$. That is, $k$ is the largest integer such that $0 \equiv a \mbox{ (mod }k\mbox{)}$ and $0 \equiv b \mbox{ (mod }k\mbox{)}$ occur +simultaneously. + +The most common approach (cite) is to reduce one input modulo another. That is if $a$ and $b$ are divisible by some integer $k$ and if $qa + r = b$ then +$r$ is also divisible by $k$. The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Greatest Common Divisor (I)}. \\ +\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ +\textbf{Output}. The greatest common divisor $(a, b)$. \\ +\hline \\ +1. While ($b > 0$) do \\ +\hspace{3mm}1.1 $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\ +\hspace{3mm}1.2 $a \leftarrow b$ \\ +\hspace{3mm}1.3 $b \leftarrow r$ \\ +2. Return($a$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Greatest Common Divisor (I)} +\label{fig:gcd1} +\end{figure} + +This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly. However, divisions are +relatively expensive operations to perform and should ideally be avoided. There is another approach based on a similar relationship of +greatest common divisors. The faster approach is based on the observation that if $k$ divides both $a$ and $b$ it will also divide $a - b$. +In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Greatest Common Divisor (II)}. \\ +\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ +\textbf{Output}. The greatest common divisor $(a, b)$. \\ +\hline \\ +1. While ($b > 0$) do \\ +\hspace{3mm}1.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\ +\hspace{3mm}1.2 $b \leftarrow b - a$ \\ +2. Return($a$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Greatest Common Divisor (II)} +\label{fig:gcd2} +\end{figure} + +\textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.} +The algorithm in figure~\ref{fig:gcd2} will eventually terminate since $b \ge a$ the subtraction in step 1.2 will be a value less than $b$. In other +words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$. Since both $a$ and $b$ are always +divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the +second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof. \textbf{QED}. + +As a matter of practicality algorithm \ref{fig:gcd1} decreases far too slowly to be useful. Specially if $b$ is much larger than $a$ such that +$b - a$ is still very much larger than $a$. A simple addition to the algorithm is to divide $b - a$ by a power of some integer $p$ which does +not divide the greatest common divisor but will divide $b - a$. In this case ${b - a} \over p$ is also an integer and still divisible by +the greatest common divisor. + +However, instead of factoring $b - a$ to find a suitable value of $p$ the powers of $p$ can be removed from $a$ and $b$ that are in common first. +Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Greatest Common Divisor (III)}. \\ +\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ +\textbf{Output}. The greatest common divisor $(a, b)$. \\ +\hline \\ +1. $k \leftarrow 0$ \\ +2. While $a$ and $b$ are both divisible by $p$ do \\ +\hspace{3mm}2.1 $a \leftarrow \lfloor a / p \rfloor$ \\ +\hspace{3mm}2.2 $b \leftarrow \lfloor b / p \rfloor$ \\ +\hspace{3mm}2.3 $k \leftarrow k + 1$ \\ +3. While $a$ is divisible by $p$ do \\ +\hspace{3mm}3.1 $a \leftarrow \lfloor a / p \rfloor$ \\ +4. While $b$ is divisible by $p$ do \\ +\hspace{3mm}4.1 $b \leftarrow \lfloor b / p \rfloor$ \\ +5. While ($b > 0$) do \\ +\hspace{3mm}5.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\ +\hspace{3mm}5.2 $b \leftarrow b - a$ \\ +\hspace{3mm}5.3 While $b$ is divisible by $p$ do \\ +\hspace{6mm}5.3.1 $b \leftarrow \lfloor b / p \rfloor$ \\ +6. Return($a \cdot p^k$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Greatest Common Divisor (III)} +\label{fig:gcd3} +\end{figure} + +This algorithm is based on the first except it removes powers of $p$ first and inside the main loop to ensure the tuple $\left < a, b \right >$ +decreases more rapidly. The first loop on step two removes powers of $p$ that are in common. A count, $k$, is kept which will present a common +divisor of $p^k$. After step two the remaining common divisor of $a$ and $b$ cannot be divisible by $p$. This means that $p$ can be safely +divided out of the difference $b - a$ so long as the division leaves no remainder. + +In particular the value of $p$ should be chosen such that the division on step 5.3.1 occur often. It also helps that division by $p$ be easy +to compute. The ideal choice of $p$ is two since division by two amounts to a right logical shift. Another important observation is that by +step five both $a$ and $b$ are odd. Therefore, the diffrence $b - a$ must be even which means that each iteration removes one bit from the +largest of the pair. + +\subsection{Complete Greatest Common Divisor} +The algorithms presented so far cannot handle inputs which are zero or negative. The following algorithm can handle all input cases properly +and will produce the greatest common divisor. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_gcd}. \\ +\textbf{Input}. mp\_int $a$ and $b$ \\ +\textbf{Output}. The greatest common divisor $c = (a, b)$. \\ +\hline \\ +1. If $a = 0$ then \\ +\hspace{3mm}1.1 $c \leftarrow \vert b \vert $ \\ +\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ +2. If $b = 0$ then \\ +\hspace{3mm}2.1 $c \leftarrow \vert a \vert $ \\ +\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\ +3. $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\ +4. $k \leftarrow 0$ \\ +5. While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}5.1 $k \leftarrow k + 1$ \\ +\hspace{3mm}5.2 $u \leftarrow \lfloor u / 2 \rfloor$ \\ +\hspace{3mm}5.3 $v \leftarrow \lfloor v / 2 \rfloor$ \\ +6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\ +7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ +8. While $v.used > 0$ \\ +\hspace{3mm}8.1 If $\vert u \vert > \vert v \vert$ then \\ +\hspace{6mm}8.1.1 Swap $u$ and $v$. \\ +\hspace{3mm}8.2 $v \leftarrow \vert v \vert - \vert u \vert$ \\ +\hspace{3mm}8.3 While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{6mm}8.3.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ +9. $c \leftarrow u \cdot 2^k$ \\ +10. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_gcd} +\end{figure} +\textbf{Algorithm mp\_gcd.} +This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$. The algorithm was originally based on Algorithm B of +Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain. In theory it achieves the same asymptotic working time as +Algorithm B and in practice this appears to be true. + +The first two steps handle the cases where either one of or both inputs are zero. If either input is zero the greatest common divisor is the +largest input or zero if they are both zero. If the inputs are not trivial than $u$ and $v$ are assigned the absolute values of +$a$ and $b$ respectively and the algorithm will proceed to reduce the pair. + +Step five will divide out any common factors of two and keep track of the count in the variable $k$. After this step, two is no longer a +factor of the remaining greatest common divisor between $u$ and $v$ and can be safely evenly divided out of either whenever they are even. Step +six and seven ensure that the $u$ and $v$ respectively have no more factors of two. At most only one of the while--loops will iterate since +they cannot both be even. + +By step eight both of $u$ and $v$ are odd which is required for the inner logic. First the pair are swapped such that $v$ is equal to +or greater than $u$. This ensures that the subtraction on step 8.2 will always produce a positive and even result. Step 8.3 removes any +factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd. + +After $v = 0$ occurs the variable $u$ has the greatest common divisor of the pair $\left < u, v \right >$ just after step six. The result +must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier. + +EXAM,bn_mp_gcd.c + +This function makes use of the macros mp\_iszero and mp\_iseven. The former evaluates to $1$ if the input mp\_int is equivalent to the +integer zero otherwise it evaluates to $0$. The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise +it evaluates to $0$. Note that just because mp\_iseven may evaluate to $0$ does not mean the input is odd, it could also be zero. The three +trivial cases of inputs are handled on lines @23,zero@ through @29,}@. After those lines the inputs are assumed to be non-zero. + +Lines @32,if@ and @36,if@ make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively. At this point the common factors of two +must be divided out of the two inputs. The block starting at line @43,common@ removes common factors of two by first counting the number of trailing +zero bits in both. The local integer $k$ is used to keep track of how many factors of $2$ are pulled out of both values. It is assumed that +the number of factors will not exceed the maximum value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than +entries than are accessible by an ``int'' so this is not a limitation.}. + +At this point there are no more common factors of two in the two values. The divisions by a power of two on lines @60,div_2d@ and @67,div_2d@ remove +any independent factors of two such that both $u$ and $v$ are guaranteed to be an odd integer before hitting the main body of the algorithm. The while loop +on line @72, while@ performs the reduction of the pair until $v$ is equal to zero. The unsigned comparison and subtraction algorithms are used in +place of the full signed routines since both values are guaranteed to be positive and the result of the subtraction is guaranteed to be non-negative. + +\section{Least Common Multiple} +The least common multiple of a pair of integers is their product divided by their greatest common divisor. For two integers $a$ and $b$ the +least common multiple is normally denoted as $[ a, b ]$ and numerically equivalent to ${ab} \over {(a, b)}$. For example, if $a = 2 \cdot 2 \cdot 3 = 12$ +and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$. + +The least common multiple arises often in coding theory as well as number theory. If two functions have periods of $a$ and $b$ respectively they will +collide, that is be in synchronous states, after only $[ a, b ]$ iterations. This is why, for example, random number generators based on +Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}). +Similarly in number theory if a composite $n$ has two prime factors $p$ and $q$ then maximal order of any unit of $\Z/n\Z$ will be $[ p - 1, q - 1] $. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_lcm}. \\ +\textbf{Input}. mp\_int $a$ and $b$ \\ +\textbf{Output}. The least common multiple $c = [a, b]$. \\ +\hline \\ +1. $c \leftarrow (a, b)$ \\ +2. $t \leftarrow a \cdot b$ \\ +3. $c \leftarrow \lfloor t / c \rfloor$ \\ +4. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_lcm} +\end{figure} +\textbf{Algorithm mp\_lcm.} +This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$. It computes the least common multiple directly by +dividing the product of the two inputs by their greatest common divisor. + +EXAM,bn_mp_lcm.c + +\section{Jacobi Symbol Computation} +To explain the Jacobi Symbol we shall first discuss the Legendre function\footnote{Arrg. What is the name of this?} off which the Jacobi symbol is +defined. The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$. Numerically it is +equivalent to equation \ref{eqn:legendre}. + +\textit{-- Tom, don't be an ass, cite your source here...!} + +\begin{equation} +a^{(p-1)/2} \equiv \begin{array}{rl} + -1 & \mbox{if }a\mbox{ is a quadratic non-residue.} \\ + 0 & \mbox{if }a\mbox{ divides }p\mbox{.} \\ + 1 & \mbox{if }a\mbox{ is a quadratic residue}. + \end{array} \mbox{ (mod }p\mbox{)} +\label{eqn:legendre} +\end{equation} + +\textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.} +An integer $a$ is a quadratic residue if the following equation has a solution. + +\begin{equation} +x^2 \equiv a \mbox{ (mod }p\mbox{)} +\label{eqn:root} +\end{equation} + +Consider the following equation. + +\begin{equation} +0 \equiv x^{p-1} - 1 \equiv \left \lbrace \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \right \rbrace + \left ( a^{(p-1)/2} - 1 \right ) \mbox{ (mod }p\mbox{)} +\label{eqn:rooti} +\end{equation} + +Whether equation \ref{eqn:root} has a solution or not equation \ref{eqn:rooti} is always true. If $a^{(p-1)/2} - 1 \equiv 0 \mbox{ (mod }p\mbox{)}$ +then the quantity in the braces must be zero. By reduction, + +\begin{eqnarray} +\left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0 \nonumber \\ +\left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\ +x^2 \equiv a \mbox{ (mod }p\mbox{)} +\end{eqnarray} + +As a result there must be a solution to the quadratic equation and in turn $a$ must be a quadratic residue. If $a$ does not divide $p$ and $a$ +is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since +\begin{equation} +0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)} +\end{equation} +One of the terms on the right hand side must be zero. \textbf{QED} + +\subsection{Jacobi Symbol} +The Jacobi symbol is a generalization of the Legendre function for any odd non prime moduli $p$ greater than 2. If $p = \prod_{i=0}^n p_i$ then +the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation. + +\begin{equation} +\left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right ) +\end{equation} + +By inspection if $p$ is prime the Jacobi symbol is equivalent to the Legendre function. The following facts\footnote{See HAC \cite[pp. 72-74]{HAC} for +further details.} will be used to derive an efficient Jacobi symbol algorithm. Where $p$ is an odd integer greater than two and $a, b \in \Z$ the +following are true. + +\begin{enumerate} +\item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$. +\item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$. +\item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$. +\item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$. Otherwise, it equals $-1$. +\item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$. More specifically +$\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$. +\end{enumerate} + +Using these facts if $a = 2^k \cdot a'$ then + +\begin{eqnarray} +\left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\ + = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right ) +\label{eqn:jacobi} +\end{eqnarray} + +By fact five, + +\begin{equation} +\left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} +\end{equation} + +Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then + +\begin{equation} +\left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} +\end{equation} + +By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed. + +\begin{equation} +\left ( { a \over p } \right ) = \left ( {2 \over p } \right )^k \left ( {{p\mbox{ mod }a'} \over a'} \right ) \cdot (-1)^{(p-1)(a'-1)/4} +\end{equation} + +The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively. The value of +$\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$. Using this approach the +factors of $p$ do not have to be known. Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the +Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_jacobi}. \\ +\textbf{Input}. mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\ +\textbf{Output}. The Jacobi symbol $c = \left ( {a \over p } \right )$. \\ +\hline \\ +1. If $a = 0$ then \\ +\hspace{3mm}1.1 $c \leftarrow 0$ \\ +\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ +2. If $a = 1$ then \\ +\hspace{3mm}2.1 $c \leftarrow 1$ \\ +\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\ +3. $a' \leftarrow a$ \\ +4. $k \leftarrow 0$ \\ +5. While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}5.1 $k \leftarrow k + 1$ \\ +\hspace{3mm}5.2 $a' \leftarrow \lfloor a' / 2 \rfloor$ \\ +6. If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\ +\hspace{3mm}6.1 $s \leftarrow 1$ \\ +7. else \\ +\hspace{3mm}7.1 $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\ +\hspace{3mm}7.2 If $r = 1$ or $r = 7$ then \\ +\hspace{6mm}7.2.1 $s \leftarrow 1$ \\ +\hspace{3mm}7.3 else \\ +\hspace{6mm}7.3.1 $s \leftarrow -1$ \\ +8. If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\ +\hspace{3mm}8.1 $s \leftarrow -s$ \\ +9. If $a' \ne 1$ then \\ +\hspace{3mm}9.1 $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\ +\hspace{3mm}9.2 $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\ +10. $c \leftarrow s$ \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_jacobi} +\end{figure} +\textbf{Algorithm mp\_jacobi.} +This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three. The algorithm +is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}. + +Step numbers one and two handle the trivial cases of $a = 0$ and $a = 1$ respectively. Step five determines the number of two factors in the +input $a$. If $k$ is even than the term $\left ( { 2 \over p } \right )^k$ must always evaluate to one. If $k$ is odd than the term evaluates to one +if $p_0$ is congruent to one or seven modulo eight, otherwise it evaluates to $-1$. After the the $\left ( { 2 \over p } \right )^k$ term is handled +the $(-1)^{(p-1)(a'-1)/4}$ is computed and multiplied against the current product $s$. The latter term evaluates to one if both $p$ and $a'$ +are congruent to one modulo four, otherwise it evaluates to negative one. + +By step nine if $a'$ does not equal one a recursion is required. Step 9.1 computes $p' \equiv p \mbox{ (mod }a'\mbox{)}$ and will recurse to compute +$\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product. + +EXAM,bn_mp_jacobi.c + +As a matter of practicality the variable $a'$ as per the pseudo-code is reprensented by the variable $a1$ since the $'$ symbol is not valid for a C +variable name character. + +The two simple cases of $a = 0$ and $a = 1$ are handled at the very beginning to simplify the algorithm. If the input is non-trivial the algorithm +has to proceed compute the Jacobi. The variable $s$ is used to hold the current Jacobi product. Note that $s$ is merely a C ``int'' data type since +the values it may obtain are merely $-1$, $0$ and $1$. + +After a local copy of $a$ is made all of the factors of two are divided out and the total stored in $k$. Technically only the least significant +bit of $k$ is required, however, it makes the algorithm simpler to follow to perform an addition. In practice an exclusive-or and addition have the same +processor requirements and neither is faster than the other. + +Line @59, if@ through @70, }@ determines the value of $\left ( { 2 \over p } \right )^k$. If the least significant bit of $k$ is zero than +$k$ is even and the value is one. Otherwise, the value of $s$ depends on which residue class $p$ belongs to modulo eight. The value of +$(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines @73, if@ through @75, }@. + +Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$. + +\textit{-- Comment about default $s$ and such...} + +\section{Modular Inverse} +\label{sec:modinv} +The modular inverse of a number actually refers to the modular multiplicative inverse. Essentially for any integer $a$ such that $(a, p) = 1$ there +exist another integer $b$ such that $ab \equiv 1 \mbox{ (mod }p\mbox{)}$. The integer $b$ is called the multiplicative inverse of $a$ which is +denoted as $b = a^{-1}$. Technically speaking modular inversion is a well defined operation for any finite ring or field not just for rings and +fields of integers. However, the former will be the matter of discussion. + +The simplest approach is to compute the algebraic inverse of the input. That is to compute $b \equiv a^{\Phi(p) - 1}$. If $\Phi(p)$ is the +order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$. The proof of which is trivial. + +\begin{equation} +ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)} +\end{equation} + +However, as simple as this approach may be it has two serious flaws. It requires that the value of $\Phi(p)$ be known which if $p$ is composite +requires all of the prime factors. This approach also is very slow as the size of $p$ grows. + +A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear +Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation. + +\begin{equation} +ab + pq = 1 +\end{equation} + +Where $a$, $b$, $p$ and $q$ are all integers. If such a pair of integers $ \left < b, q \right >$ exist than $b$ is the multiplicative inverse of +$a$ modulo $p$. The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$. +However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place. The +binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine +equation. + +\subsection{General Case} +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_invmod}. \\ +\textbf{Input}. mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$. \\ +\textbf{Output}. The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\ +\hline \\ +1. If $b \le 0$ then return(\textit{MP\_VAL}). \\ +2. If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\ +3. $x \leftarrow \vert a \vert, y \leftarrow b$ \\ +4. If $x_0 \equiv y_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\ +5. $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\ +6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\ +\hspace{3mm}6.2 If ($A.used > 0$ and $A_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($B.used > 0$ and $B_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\ +\hspace{6mm}6.2.1 $A \leftarrow A + y$ \\ +\hspace{6mm}6.2.2 $B \leftarrow B - x$ \\ +\hspace{3mm}6.3 $A \leftarrow \lfloor A / 2 \rfloor$ \\ +\hspace{3mm}6.4 $B \leftarrow \lfloor B / 2 \rfloor$ \\ +7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ +\hspace{3mm}7.2 If ($C.used > 0$ and $C_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($D.used > 0$ and $D_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\ +\hspace{6mm}7.2.1 $C \leftarrow C + y$ \\ +\hspace{6mm}7.2.2 $D \leftarrow D - x$ \\ +\hspace{3mm}7.3 $C \leftarrow \lfloor C / 2 \rfloor$ \\ +\hspace{3mm}7.4 $D \leftarrow \lfloor D / 2 \rfloor$ \\ +8. If $u \ge v$ then \\ +\hspace{3mm}8.1 $u \leftarrow u - v$ \\ +\hspace{3mm}8.2 $A \leftarrow A - C$ \\ +\hspace{3mm}8.3 $B \leftarrow B - D$ \\ +9. else \\ +\hspace{3mm}9.1 $v \leftarrow v - u$ \\ +\hspace{3mm}9.2 $C \leftarrow C - A$ \\ +\hspace{3mm}9.3 $D \leftarrow D - B$ \\ +10. If $u \ne 0$ goto step 6. \\ +11. If $v \ne 1$ return(\textit{MP\_VAL}). \\ +12. While $C \le 0$ do \\ +\hspace{3mm}12.1 $C \leftarrow C + b$ \\ +13. While $C \ge b$ do \\ +\hspace{3mm}13.1 $C \leftarrow C - b$ \\ +14. $c \leftarrow C$ \\ +15. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\end{figure} +\textbf{Algorithm mp\_invmod.} +This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$. This algorithm is a variation of the +extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}. It has been modified to only compute the modular inverse and not a complete +Diophantine solution. + +If $b \le 0$ than the modulus is invalid and MP\_VAL is returned. Similarly if both $a$ and $b$ are even then there cannot be a multiplicative +inverse for $a$ and the error is reported. + +The astute reader will observe that steps seven through nine are very similar to the binary greatest common divisor algorithm mp\_gcd. In this case +the other variables to the Diophantine equation are solved. The algorithm terminates when $u = 0$ in which case the solution is + +\begin{equation} +Ca + Db = v +\end{equation} + +If $v$, the greatest common divisor of $a$ and $b$ is not equal to one then the algorithm will report an error as no inverse exists. Otherwise, $C$ +is the modular inverse of $a$. The actual value of $C$ is congruent to, but not necessarily equal to, the ideal modular inverse which should lie +within $1 \le a^{-1} < b$. Step numbers twelve and thirteen adjust the inverse until it is in range. If the original input $a$ is within $0 < a < p$ +then only a couple of additions or subtractions will be required to adjust the inverse. + +EXAM,bn_mp_invmod.c + +\subsubsection{Odd Moduli} + +When the modulus $b$ is odd the variables $A$ and $C$ are fixed and are not required to compute the inverse. In particular by attempting to solve +the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$. + +The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed. This +optimization will halve the time required to compute the modular inverse. + +\section{Primality Tests} + +A non-zero integer $a$ is said to be prime if it is not divisible by any other integer excluding one and itself. For example, $a = 7$ is prime +since the integers $2 \ldots 6$ do not evenly divide $a$. By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$. + +Prime numbers arise in cryptography considerably as they allow finite fields to be formed. The ability to determine whether an integer is prime or +not quickly has been a viable subject in cryptography and number theory for considerable time. The algorithms that will be presented are all +probablistic algorithms in that when they report an integer is composite it must be composite. However, when the algorithms report an integer is +prime the algorithm may be incorrect. + +As will be discussed it is possible to limit the probability of error so well that for practical purposes the probablity of error might as +well be zero. For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question. + +\subsection{Trial Division} + +Trial division means to attempt to evenly divide a candidate integer by small prime integers. If the candidate can be evenly divided it obviously +cannot be prime. By dividing by all primes $1 < p \le \sqrt{n}$ this test can actually prove whether an integer is prime. However, such a test +would require a prohibitive amount of time as $n$ grows. + +Instead of dividing by every prime, a smaller, more mangeable set of primes may be used instead. By performing trial division with only a subset +of the primes less than $\sqrt{n} + 1$ the algorithm cannot prove if a candidate is prime. However, often it can prove a candidate is not prime. + +The benefit of this test is that trial division by small values is fairly efficient. Specially compared to the other algorithms that will be +discussed shortly. The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by +$1 - {1.12 \over ln(q)}$. The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range +$3 \le q \le 100$. + +At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly. At $q = 90$ further testing is generally not going to +be of any practical use. In the case of LibTomMath the default limit $q = 256$ was chosen since it is not too high and will eliminate +approximately $80\%$ of all candidate integers. The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base. The +array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\ +\textbf{Input}. mp\_int $a$ \\ +\textbf{Output}. $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$. \\ +\hline \\ +1. for $ix$ from $0$ to $PRIME\_SIZE$ do \\ +\hspace{3mm}1.1 $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\ +\hspace{3mm}1.2 If $d = 0$ then \\ +\hspace{6mm}1.2.1 $c \leftarrow 1$ \\ +\hspace{6mm}1.2.2 Return(\textit{MP\_OKAY}). \\ +2. $c \leftarrow 0$ \\ +3. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_prime\_is\_divisible} +\end{figure} +\textbf{Algorithm mp\_prime\_is\_divisible.} +This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions. + +EXAM,bn_mp_prime_is_divisible.c + +The algorithm defaults to a return of $0$ in case an error occurs. The values in the prime table are all specified to be in the range of a +mp\_digit. The table \_\_prime\_tab is defined in the following file. + +EXAM,bn_prime_tab.c + +Note that there are two possible tables. When an mp\_digit is 7-bits long only the primes upto $127$ may be included, otherwise the primes +upto $1619$ are used. Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit. + +\subsection{The Fermat Test} +The Fermat test is probably one the oldest tests to have a non-trivial probability of success. It is based on the fact that if $n$ is in +fact prime then $a^{n} \equiv a \mbox{ (mod }n\mbox{)}$ for all $0 < a < n$. The reason being that if $n$ is prime than the order of +the multiplicative sub group is $n - 1$. Any base $a$ must have an order which divides $n - 1$ and as such $a^n$ is equivalent to +$a^1 = a$. + +If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$. In which case +it is possible that $a^n \nequiv a \mbox{ (mod }n\mbox{)}$. However, this test is not absolute as it is possible that the order +of a base will divide $n - 1$ which would then be reported as prime. Such a base yields what is known as a Fermat pseudo-prime. Several +integers known as Carmichael numbers will be a pseudo-prime to all valid bases. Fortunately such numbers are extremely rare as $n$ grows +in size. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_prime\_fermat}. \\ +\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\ +\textbf{Output}. $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$. \\ +\hline \\ +1. $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\ +2. If $t = b$ then \\ +\hspace{3mm}2.1 $c = 1$ \\ +3. else \\ +\hspace{3mm}3.1 $c = 0$ \\ +4. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_prime\_fermat} +\end{figure} +\textbf{Algorithm mp\_prime\_fermat.} +This algorithm determines whether an mp\_int $a$ is a Fermat prime to the base $b$ or not. It uses a single modular exponentiation to +determine the result. + +EXAM,bn_mp_prime_fermat.c + +\subsection{The Miller-Rabin Test} +The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen +candidate integers. The algorithm is based on the observation that if $n - 1 = 2^kr$ and if $b^r \nequiv \pm 1$ then after upto $k - 1$ squarings the +value must be equal to $-1$. The squarings are stopped as soon as $-1$ is observed. If the value of $1$ is observed first it means that +some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\ +\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\ +\textbf{Output}. $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$. \\ +\hline +1. $a' \leftarrow a - 1$ \\ +2. $r \leftarrow n1$ \\ +3. $c \leftarrow 0, s \leftarrow 0$ \\ +4. While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}4.1 $s \leftarrow s + 1$ \\ +\hspace{3mm}4.2 $r \leftarrow \lfloor r / 2 \rfloor$ \\ +5. $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\ +6. If $y \nequiv \pm 1$ then \\ +\hspace{3mm}6.1 $j \leftarrow 1$ \\ +\hspace{3mm}6.2 While $j \le (s - 1)$ and $y \nequiv a'$ \\ +\hspace{6mm}6.2.1 $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\ +\hspace{6mm}6.2.2 If $y = 1$ then goto step 8. \\ +\hspace{6mm}6.2.3 $j \leftarrow j + 1$ \\ +\hspace{3mm}6.3 If $y \nequiv a'$ goto step 8. \\ +7. $c \leftarrow 1$\\ +8. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_prime\_miller\_rabin} +\end{figure} +\textbf{Algorithm mp\_prime\_miller\_rabin.} +This algorithm performs one trial round of the Miller-Rabin algorithm to the base $b$. It will set $c = 1$ if the algorithm cannot determine +if $b$ is composite or $c = 0$ if $b$ is provably composite. The values of $s$ and $r$ are computed such that $a' = a - 1 = 2^sr$. + +If the value $y \equiv b^r$ is congruent to $\pm 1$ then the algorithm cannot prove if $a$ is composite or not. Otherwise, the algorithm will +square $y$ upto $s - 1$ times stopping only when $y \equiv -1$. If $y^2 \equiv 1$ and $y \nequiv \pm 1$ then the algorithm can report that $a$ +is provably composite. If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite. If $a$ is not provably +composite then it is \textit{probably} prime. + +EXAM,bn_mp_prime_miller_rabin.c + + + + +\backmatter +\appendix +\begin{thebibliography}{ABCDEF} +\bibitem[1]{TAOCPV2} +Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998 + +\bibitem[2]{HAC} +A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996 + +\bibitem[3]{ROSE} +Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999 + +\bibitem[4]{COMBA} +Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990) + +\bibitem[5]{KARA} +A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294 + +\bibitem[6]{KARAP} +Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002 + +\bibitem[7]{BARRETT} +Paul Barrett, \textit{Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor}, Advances in Cryptology, Crypto '86, Springer-Verlag. + +\bibitem[8]{MONT} +P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985. + +\bibitem[9]{DRMET} +Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories + +\bibitem[10]{MMB} +J. Daemen and R. Govaerts and J. Vandewalle, \textit{Block ciphers based on Modular Arithmetic}, State and {P}rogress in the {R}esearch of {C}ryptography, 1993, pp. 80-89 + +\bibitem[11]{RSAREF} +R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems} + +\bibitem[12]{DHREF} +Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976 + +\bibitem[13]{IEEE} +IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985) + +\bibitem[14]{GMP} +GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/} + +\bibitem[15]{MPI} +Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/} + +\bibitem[16]{OPENSSL} +OpenSSL Cryptographic Toolkit, \url{http://openssl.org} + +\bibitem[17]{LIP} +Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip} + +\bibitem[18]{ISOC} +JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.'' + +\bibitem[19]{JAVA} +The Sun Java Website, \url{http://java.sun.com/} + +\end{thebibliography} + +\input{tommath.ind} + +\end{document} diff --git a/lib/hcrypto/libtommath/tommath.tex b/lib/hcrypto/libtommath/tommath.tex new file mode 100644 index 000000000..c79a5370f --- /dev/null +++ b/lib/hcrypto/libtommath/tommath.tex @@ -0,0 +1,6691 @@ +\documentclass[b5paper]{book} +\usepackage{hyperref} +\usepackage{makeidx} +\usepackage{amssymb} +\usepackage{color} +\usepackage{alltt} +\usepackage{graphicx} +\usepackage{layout} +\def\union{\cup} +\def\intersect{\cap} +\def\getsrandom{\stackrel{\rm R}{\gets}} +\def\cross{\times} +\def\cat{\hspace{0.5em} \| \hspace{0.5em}} +\def\catn{$\|$} +\def\divides{\hspace{0.3em} | \hspace{0.3em}} +\def\nequiv{\not\equiv} +\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}} +\def\lcm{{\rm lcm}} +\def\gcd{{\rm gcd}} +\def\log{{\rm log}} +\def\ord{{\rm ord}} +\def\abs{{\mathit abs}} +\def\rep{{\mathit rep}} +\def\mod{{\mathit\ mod\ }} +\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})} +\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor} +\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil} +\def\Or{{\rm\ or\ }} +\def\And{{\rm\ and\ }} +\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}} +\def\implies{\Rightarrow} +\def\undefined{{\rm ``undefined"}} +\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}} +\let\oldphi\phi +\def\phi{\varphi} +\def\Pr{{\rm Pr}} +\newcommand{\str}[1]{{\mathbf{#1}}} +\def\F{{\mathbb F}} +\def\N{{\mathbb N}} +\def\Z{{\mathbb Z}} +\def\R{{\mathbb R}} +\def\C{{\mathbb C}} +\def\Q{{\mathbb Q}} +\definecolor{DGray}{gray}{0.5} +\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}} +\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}} +\def\gap{\vspace{0.5ex}} +\makeindex +\begin{document} +\frontmatter +\pagestyle{empty} +\title{Multi--Precision Math} +\author{\mbox{ +%\begin{small} +\begin{tabular}{c} +Tom St Denis \\ +Algonquin College \\ +\\ +Mads Rasmussen \\ +Open Communications Security \\ +\\ +Greg Rose \\ +QUALCOMM Australia \\ +\end{tabular} +%\end{small} +} +} +\maketitle +This text has been placed in the public domain. This text corresponds to the v0.39 release of the +LibTomMath project. + +\begin{alltt} +Tom St Denis +111 Banning Rd +Ottawa, Ontario +K2L 1C3 +Canada + +Phone: 1-613-836-3160 +Email: tomstdenis@gmail.com +\end{alltt} + +This text is formatted to the international B5 paper size of 176mm wide by 250mm tall using the \LaTeX{} +{\em book} macro package and the Perl {\em booker} package. + +\tableofcontents +\listoffigures +\chapter*{Prefaces} +When I tell people about my LibTom projects and that I release them as public domain they are often puzzled. +They ask why I did it and especially why I continue to work on them for free. The best I can explain it is ``Because I can.'' +Which seems odd and perhaps too terse for adult conversation. I often qualify it with ``I am able, I am willing.'' which +perhaps explains it better. I am the first to admit there is not anything that special with what I have done. Perhaps +others can see that too and then we would have a society to be proud of. My LibTom projects are what I am doing to give +back to society in the form of tools and knowledge that can help others in their endeavours. + +I started writing this book because it was the most logical task to further my goal of open academia. The LibTomMath source +code itself was written to be easy to follow and learn from. There are times, however, where pure C source code does not +explain the algorithms properly. Hence this book. The book literally starts with the foundation of the library and works +itself outwards to the more complicated algorithms. The use of both pseudo--code and verbatim source code provides a duality +of ``theory'' and ``practice'' that the computer science students of the world shall appreciate. I never deviate too far +from relatively straightforward algebra and I hope that this book can be a valuable learning asset. + +This book and indeed much of the LibTom projects would not exist in their current form if it was not for a plethora +of kind people donating their time, resources and kind words to help support my work. Writing a text of significant +length (along with the source code) is a tiresome and lengthy process. Currently the LibTom project is four years old, +comprises of literally thousands of users and over 100,000 lines of source code, TeX and other material. People like Mads and Greg +were there at the beginning to encourage me to work well. It is amazing how timely validation from others can boost morale to +continue the project. Definitely my parents were there for me by providing room and board during the many months of work in 2003. + +To my many friends whom I have met through the years I thank you for the good times and the words of encouragement. I hope I +honour your kind gestures with this project. + +Open Source. Open Academia. Open Minds. + +\begin{flushright} Tom St Denis \end{flushright} + +\newpage +I found the opportunity to work with Tom appealing for several reasons, not only could I broaden my own horizons, but also +contribute to educate others facing the problem of having to handle big number mathematical calculations. + +This book is Tom's child and he has been caring and fostering the project ever since the beginning with a clear mind of +how he wanted the project to turn out. I have helped by proofreading the text and we have had several discussions about +the layout and language used. + +I hold a masters degree in cryptography from the University of Southern Denmark and have always been interested in the +practical aspects of cryptography. + +Having worked in the security consultancy business for several years in S\~{a}o Paulo, Brazil, I have been in touch with a +great deal of work in which multiple precision mathematics was needed. Understanding the possibilities for speeding up +multiple precision calculations is often very important since we deal with outdated machine architecture where modular +reductions, for example, become painfully slow. + +This text is for people who stop and wonder when first examining algorithms such as RSA for the first time and asks +themselves, ``You tell me this is only secure for large numbers, fine; but how do you implement these numbers?'' + +\begin{flushright} +Mads Rasmussen + +S\~{a}o Paulo - SP + +Brazil +\end{flushright} + +\newpage +It's all because I broke my leg. That just happened to be at about the same time that Tom asked for someone to review the section of the book about +Karatsuba multiplication. I was laid up, alone and immobile, and thought ``Why not?'' I vaguely knew what Karatsuba multiplication was, but not +really, so I thought I could help, learn, and stop myself from watching daytime cable TV, all at once. + +At the time of writing this, I've still not met Tom or Mads in meatspace. I've been following Tom's progress since his first splash on the +sci.crypt Usenet news group. I watched him go from a clueless newbie, to the cryptographic equivalent of a reformed smoker, to a real +contributor to the field, over a period of about two years. I've been impressed with his obvious intelligence, and astounded by his productivity. +Of course, he's young enough to be my own child, so he doesn't have my problems with staying awake. + +When I reviewed that single section of the book, in its very earliest form, I was very pleasantly surprised. So I decided to collaborate more fully, +and at least review all of it, and perhaps write some bits too. There's still a long way to go with it, and I have watched a number of close +friends go through the mill of publication, so I think that the way to go is longer than Tom thinks it is. Nevertheless, it's a good effort, +and I'm pleased to be involved with it. + +\begin{flushright} +Greg Rose, Sydney, Australia, June 2003. +\end{flushright} + +\mainmatter +\pagestyle{headings} +\chapter{Introduction} +\section{Multiple Precision Arithmetic} + +\subsection{What is Multiple Precision Arithmetic?} +When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively +raise or lower the precision of the numbers we are dealing with. For example, in decimal we almost immediate can +reason that $7$ times $6$ is $42$. However, $42$ has two digits of precision as opposed to one digit we started with. +Further multiplications of say $3$ result in a larger precision result $126$. In these few examples we have multiple +precisions for the numbers we are working with. Despite the various levels of precision a single subset\footnote{With the occasional optimization.} + of algorithms can be designed to accomodate them. + +By way of comparison a fixed or single precision operation would lose precision on various operations. For example, in +the decimal system with fixed precision $6 \cdot 7 = 2$. + +Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in +schools to manually add, subtract, multiply and divide. + +\subsection{The Need for Multiple Precision Arithmetic} +The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation +of public-key cryptography algorithms. Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require +integers of significant magnitude to resist known cryptanalytic attacks. For example, at the time of this writing a +typical RSA modulus would be at least greater than $10^{309}$. However, modern programming languages such as ISO C \cite{ISOC} and +Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision. + +\begin{figure}[!here] +\begin{center} +\begin{tabular}{|r|c|} +\hline \textbf{Data Type} & \textbf{Range} \\ +\hline char & $-128 \ldots 127$ \\ +\hline short & $-32768 \ldots 32767$ \\ +\hline long & $-2147483648 \ldots 2147483647$ \\ +\hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\ +\hline +\end{tabular} +\end{center} +\caption{Typical Data Types for the C Programming Language} +\label{fig:ISOC} +\end{figure} + +The largest data type guaranteed to be provided by the ISO C programming +language\footnote{As per the ISO C standard. However, each compiler vendor is allowed to augment the precision as they +see fit.} can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is +insufficient to accomodate the magnitude required for the problem at hand. An RSA modulus of magnitude $10^{19}$ could be +trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer, +rendering any protocol based on the algorithm insecure. Multiple precision algorithms solve this very problem by +extending the range of representable integers while using single precision data types. + +Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic +primitives. Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in +various cryptographic journals, can render algorithms such as RSA and Diffie-Hellman more efficient. In fact, several +major companies such as RSA Security, Certicom and Entrust have built entire product lines on the implementation and +deployment of efficient algorithms. + +However, cryptography is not the only field of study that can benefit from fast multiple precision integer routines. +Another auxiliary use of multiple precision integers is high precision floating point data types. +The basic IEEE \cite{IEEE} standard floating point type is made up of an integer mantissa $q$, an exponent $e$ and a sign bit $s$. +Numbers are given in the form $n = q \cdot b^e \cdot -1^s$ where $b = 2$ is the most common base for IEEE. Since IEEE +floating point is meant to be implemented in hardware the precision of the mantissa is often fairly small +(\textit{23, 48 and 64 bits}). The mantissa is merely an integer and a multiple precision integer could be used to create +a mantissa of much larger precision than hardware alone can efficiently support. This approach could be useful where +scientific applications must minimize the total output error over long calculations. + +Yet another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$). +In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}. + +\subsection{Benefits of Multiple Precision Arithmetic} +\index{precision} +The benefit of multiple precision representations over single or fixed precision representations is that +no precision is lost while representing the result of an operation which requires excess precision. For example, +the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully. A multiple +precision algorithm would augment the precision of the destination to accomodate the result while a single precision system +would truncate excess bits to maintain a fixed level of precision. + +It is possible to implement algorithms which require large integers with fixed precision algorithms. For example, elliptic +curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum +size the system will ever need. Such an approach can lead to vastly simpler algorithms which can accomodate the +integers required even if the host platform cannot natively accomodate them\footnote{For example, the average smartcard +processor has an 8 bit accumulator.}. However, as efficient as such an approach may be, the resulting source code is not +normally very flexible. It cannot, at runtime, accomodate inputs of higher magnitude than the designer anticipated. + +Multiple precision algorithms have the most overhead of any style of arithmetic. For the the most part the +overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved +platforms. However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the +inputs. That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input +without the designer's explicit forethought. This leads to lower cost of ownership for the code as it only has to +be written and tested once. + +\section{Purpose of This Text} +The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms. +That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping'' +elements that are neglected by authors of other texts on the subject. Several well reknowned texts \cite{TAOCPV2,HAC} +give considerably detailed explanations of the theoretical aspects of algorithms and often very little information +regarding the practical implementation aspects. + +In most cases how an algorithm is explained and how it is actually implemented are two very different concepts. For +example, the Handbook of Applied Cryptography (\textit{HAC}), algorithm 14.7 on page 594, gives a relatively simple +algorithm for performing multiple precision integer addition. However, the description lacks any discussion concerning +the fact that the two integer inputs may be of differing magnitudes. As a result the implementation is not as simple +as the text would lead people to believe. Similarly the division routine (\textit{algorithm 14.20, pp. 598}) does not +discuss how to handle sign or handle the dividend's decreasing magnitude in the main loop (\textit{step \#3}). + +Both texts also do not discuss several key optimal algorithms required such as ``Comba'' and Karatsuba multipliers +and fast modular inversion, which we consider practical oversights. These optimal algorithms are vital to achieve +any form of useful performance in non-trivial applications. + +To solve this problem the focus of this text is on the practical aspects of implementing a multiple precision integer +package. As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.com}} package is used +to demonstrate algorithms with real implementations\footnote{In the ISO C programming language.} that have been field +tested and work very well. The LibTomMath library is freely available on the Internet for all uses and this text +discusses a very large portion of the inner workings of the library. + +The algorithms that are presented will always include at least one ``pseudo-code'' description followed +by the actual C source code that implements the algorithm. The pseudo-code can be used to implement the same +algorithm in other programming languages as the reader sees fit. + +This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch. Showing +the reader how the algorithms fit together as well as where to start on various taskings. + +\section{Discussion and Notation} +\subsection{Notation} +A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1}, \ldots, x_1, x_0)_{ \beta }$ and represent +the integer $x \equiv \sum_{i=0}^{n-1} x_i\beta^i$. The elements of the array $x$ are said to be the radix $\beta$ digits +of the integer. For example, $x = (1,2,3)_{10}$ would represent the integer +$1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$. + +\index{mp\_int} +The term ``mp\_int'' shall refer to a composite structure which contains the digits of the integer it represents, as well +as auxilary data required to manipulate the data. These additional members are discussed further in section +\ref{sec:MPINT}. For the purposes of this text a ``multiple precision integer'' and an ``mp\_int'' are assumed to be +synonymous. When an algorithm is specified to accept an mp\_int variable it is assumed the various auxliary data members +are present as well. An expression of the type \textit{variablename.item} implies that it should evaluate to the +member named ``item'' of the variable. For example, a string of characters may have a member ``length'' which would +evaluate to the number of characters in the string. If the string $a$ equals ``hello'' then it follows that +$a.length = 5$. + +For certain discussions more generic algorithms are presented to help the reader understand the final algorithm used +to solve a given problem. When an algorithm is described as accepting an integer input it is assumed the input is +a plain integer with no additional multiple-precision members. That is, algorithms that use integers as opposed to +mp\_ints as inputs do not concern themselves with the housekeeping operations required such as memory management. These +algorithms will be used to establish the relevant theory which will subsequently be used to describe a multiple +precision algorithm to solve the same problem. + +\subsection{Precision Notation} +The variable $\beta$ represents the radix of a single digit of a multiple precision integer and +must be of the form $q^p$ for $q, p \in \Z^+$. A single precision variable must be able to represent integers in +the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range +$0 \le x < q \beta^2$. The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the +carry. Since all modern computers are binary, it is assumed that $q$ is two. + +\index{mp\_digit} \index{mp\_word} +Within the source code that will be presented for each algorithm, the data type \textbf{mp\_digit} will represent +a single precision integer type, while, the data type \textbf{mp\_word} will represent a double precision integer type. In +several algorithms (notably the Comba routines) temporary results will be stored in arrays of double precision mp\_words. +For the purposes of this text $x_j$ will refer to the $j$'th digit of a single precision array and $\hat x_j$ will refer to +the $j$'th digit of a double precision array. Whenever an expression is to be assigned to a double precision +variable it is assumed that all single precision variables are promoted to double precision during the evaluation. +Expressions that are assigned to a single precision variable are truncated to fit within the precision of a single +precision data type. + +For example, if $\beta = 10^2$ a single precision data type may represent a value in the +range $0 \le x < 10^3$, while a double precision data type may represent a value in the range $0 \le x < 10^5$. Let +$a = 23$ and $b = 49$ represent two single precision variables. The single precision product shall be written +as $c \leftarrow a \cdot b$ while the double precision product shall be written as $\hat c \leftarrow a \cdot b$. +In this particular case, $\hat c = 1127$ and $c = 127$. The most significant digit of the product would not fit +in a single precision data type and as a result $c \ne \hat c$. + +\subsection{Algorithm Inputs and Outputs} +Within the algorithm descriptions all variables are assumed to be scalars of either single or double precision +as indicated. The only exception to this rule is when variables have been indicated to be of type mp\_int. This +distinction is important as scalars are often used as array indicies and various other counters. + +\subsection{Mathematical Expressions} +The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an integer not greater than the expression +itself. For example, $\lfloor 5.7 \rfloor = 5$. Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression +rounded to an integer not less than the expression itself. For example, $\lceil 5.1 \rceil = 6$. Typically when +the $/$ division symbol is used the intention is to perform an integer division with truncation. For example, +$5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity. When an expression is written as a +fraction a real value division is implied, for example ${5 \over 2} = 2.5$. + +The norm of a multiple precision integer, for example $\vert \vert x \vert \vert$, will be used to represent the number of digits in the representation +of the integer. For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$. + +\subsection{Work Effort} +\index{big-Oh} +To measure the efficiency of the specified algorithms, a modified big-Oh notation is used. In this system all +single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}. +That is a single precision addition, multiplication and division are assumed to take the same time to +complete. While this is generally not true in practice, it will simplify the discussions considerably. + +Some algorithms have slight advantages over others which is why some constants will not be removed in +the notation. For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a +baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work. In standard big-Oh notation these +would both be said to be equivalent to $O(n^2)$. However, +in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small. As a +result small constant factors in the work effort will make an observable difference in algorithm efficiency. + +All of the algorithms presented in this text have a polynomial time work level. That is, of the form +$O(n^k)$ for $n, k \in \Z^{+}$. This will help make useful comparisons in terms of the speed of the algorithms and how +various optimizations will help pay off in the long run. + +\section{Exercises} +Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to +the discussion at hand. These exercises are not designed to be prize winning problems, but instead to be thought +provoking. Wherever possible the problems are forward minded, stating problems that will be answered in subsequent +chapters. The reader is encouraged to finish the exercises as they appear to get a better understanding of the +subject material. + +That being said, the problems are designed to affirm knowledge of a particular subject matter. Students in particular +are encouraged to verify they can answer the problems correctly before moving on. + +Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of +the problem. However, unlike \cite{TAOCPV2} the problems do not get nearly as hard. The scoring of these +exercises ranges from one (the easiest) to five (the hardest). The following table sumarizes the +scoring system used. + +\begin{figure}[here] +\begin{center} +\begin{small} +\begin{tabular}{|c|l|} +\hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\ + & minutes to solve. Usually does not involve much computer time \\ + & to solve. \\ +\hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\ + & time usage. Usually requires a program to be written to \\ + & solve the problem. \\ +\hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\ + & of work. Usually involves trivial research and development of \\ + & new theory from the perspective of a student. \\ +\hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\ + & of work and research, the solution to which will demonstrate \\ + & a higher mastery of the subject matter. \\ +\hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\ + & novice to solve. Solutions to these problems will demonstrate a \\ + & complete mastery of the given subject. \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Exercise Scoring System} +\end{figure} + +Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or +devising new theory. These problems are quick tests to see if the material is understood. Problems at the second level +are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer. These +two levels are essentially entry level questions. + +Problems at the third level are meant to be a bit more difficult than the first two levels. The answer is often +fairly obvious but arriving at an exacting solution requires some thought and skill. These problems will almost always +involve devising a new algorithm or implementing a variation of another algorithm previously presented. Readers who can +answer these questions will feel comfortable with the concepts behind the topic at hand. + +Problems at the fourth level are meant to be similar to those of the level three questions except they will require +additional research to be completed. The reader will most likely not know the answer right away, nor will the text provide +the exact details of the answer until a subsequent chapter. + +Problems at the fifth level are meant to be the hardest +problems relative to all the other problems in the chapter. People who can correctly answer fifth level problems have a +mastery of the subject matter at hand. + +Often problems will be tied together. The purpose of this is to start a chain of thought that will be discussed in future chapters. The reader +is encouraged to answer the follow-up problems and try to draw the relevance of problems. + +\section{Introduction to LibTomMath} + +\subsection{What is LibTomMath?} +LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C. By portable it +is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on +any given platform. + +The library has been successfully tested under numerous operating systems including Unix\footnote{All of these +trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux, PalmOS and on standalone hardware such +as the Gameboy Advance. The library is designed to contain enough functionality to be able to develop applications such +as public key cryptosystems and still maintain a relatively small footprint. + +\subsection{Goals of LibTomMath} + +Libraries which obtain the most efficiency are rarely written in a high level programming language such as C. However, +even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the +library. Specifically the code has been written to work well with the GNU C Compiler (\textit{GCC}) on both x86 and ARM +processors. Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window +exponentiation and Montgomery reduction have been provided to make the library more efficient. + +Even with the nearly optimal and specialized algorithms that have been included the Application Programing Interface +(\textit{API}) has been kept as simple as possible. Often generic place holder routines will make use of specialized +algorithms automatically without the developer's specific attention. One such example is the generic multiplication +algorithm \textbf{mp\_mul()} which will automatically use Toom--Cook, Karatsuba, Comba or baseline multiplication +based on the magnitude of the inputs and the configuration of the library. + +Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project. Ideally the library should +be source compatible with another popular library which makes it more attractive for developers to use. In this case the +MPI library was used as a API template for all the basic functions. MPI was chosen because it is another library that fits +in the same niche as LibTomMath. Even though LibTomMath uses MPI as the template for the function names and argument +passing conventions, it has been written from scratch by Tom St Denis. + +The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum'' +library exists which can be used to teach computer science students how to perform fast and reliable multiple precision +integer arithmetic. To this end the source code has been given quite a few comments and algorithm discussion points. + +\section{Choice of LibTomMath} +LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but +for more worthy reasons. Other libraries such as GMP \cite{GMP}, MPI \cite{MPI}, LIP \cite{LIP} and OpenSSL +\cite{OPENSSL} have multiple precision integer arithmetic routines but would not be ideal for this text for +reasons that will be explained in the following sub-sections. + +\subsection{Code Base} +The LibTomMath code base is all portable ISO C source code. This means that there are no platform dependent conditional +segments of code littered throughout the source. This clean and uncluttered approach to the library means that a +developer can more readily discern the true intent of a given section of source code without trying to keep track of +what conditional code will be used. + +The code base of LibTomMath is well organized. Each function is in its own separate source code file +which allows the reader to find a given function very quickly. On average there are $76$ lines of code per source +file which makes the source very easily to follow. By comparison MPI and LIP are single file projects making code tracing +very hard. GMP has many conditional code segments which also hinder tracing. + +When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $100$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.} + which is fairly small compared to GMP (over $250$KiB). LibTomMath is slightly larger than MPI (which compiles to about +$50$KiB) but LibTomMath is also much faster and more complete than MPI. + +\subsection{API Simplicity} +LibTomMath is designed after the MPI library and shares the API design. Quite often programs that use MPI will build +with LibTomMath without change. The function names correlate directly to the action they perform. Almost all of the +functions share the same parameter passing convention. The learning curve is fairly shallow with the API provided +which is an extremely valuable benefit for the student and developer alike. + +The LIP library is an example of a library with an API that is awkward to work with. LIP uses function names that are often ``compressed'' to +illegible short hand. LibTomMath does not share this characteristic. + +The GMP library also does not return error codes. Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors +are signaled to the host application. This happens to be the fastest approach but definitely not the most versatile. In +effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely +undersireable in many situations. + +\subsection{Optimizations} +While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does +feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring. GMP +and LIP also feature such optimizations while MPI only uses baseline algorithms with no optimizations. GMP lacks a few +of the additional modular reduction optimizations that LibTomMath features\footnote{At the time of this writing GMP +only had Barrett and Montgomery modular reduction algorithms.}. + +LibTomMath is almost always an order of magnitude faster than the MPI library at computationally expensive tasks such as modular +exponentiation. In the grand scheme of ``bignum'' libraries LibTomMath is faster than the average library and usually +slower than the best libraries such as GMP and OpenSSL by only a small factor. + +\subsection{Portability and Stability} +LibTomMath will build ``out of the box'' on any platform equipped with a modern version of the GNU C Compiler +(\textit{GCC}). This means that without changes the library will build without configuration or setting up any +variables. LIP and MPI will build ``out of the box'' as well but have numerous known bugs. Most notably the author of +MPI has recently stopped working on his library and LIP has long since been discontinued. + +GMP requires a configuration script to run and will not build out of the box. GMP and LibTomMath are still in active +development and are very stable across a variety of platforms. + +\subsection{Choice} +LibTomMath is a relatively compact, well documented, highly optimized and portable library which seems only natural for +the case study of this text. Various source files from the LibTomMath project will be included within the text. However, +the reader is encouraged to download their own copy of the library to actually be able to work with the library. + +\chapter{Getting Started} +\section{Library Basics} +The trick to writing any useful library of source code is to build a solid foundation and work outwards from it. First, +a problem along with allowable solution parameters should be identified and analyzed. In this particular case the +inability to accomodate multiple precision integers is the problem. Futhermore, the solution must be written +as portable source code that is reasonably efficient across several different computer platforms. + +After a foundation is formed the remainder of the library can be designed and implemented in a hierarchical fashion. +That is, to implement the lowest level dependencies first and work towards the most abstract functions last. For example, +before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm. +By building outwards from a base foundation instead of using a parallel design methodology the resulting project is +highly modular. Being highly modular is a desirable property of any project as it often means the resulting product +has a small footprint and updates are easy to perform. + +Usually when I start a project I will begin with the header files. I define the data types I think I will need and +prototype the initial functions that are not dependent on other functions (within the library). After I +implement these base functions I prototype more dependent functions and implement them. The process repeats until +I implement all of the functions I require. For example, in the case of LibTomMath I implemented functions such as +mp\_init() well before I implemented mp\_mul() and even further before I implemented mp\_exptmod(). As an example as to +why this design works note that the Karatsuba and Toom-Cook multipliers were written \textit{after} the +dependent function mp\_exptmod() was written. Adding the new multiplication algorithms did not require changes to the +mp\_exptmod() function itself and lowered the total cost of ownership (\textit{so to speak}) and of development +for new algorithms. This methodology allows new algorithms to be tested in a complete framework with relative ease. + +\begin{center} +\begin{figure}[here] +\includegraphics{pics/design_process.ps} +\caption{Design Flow of the First Few Original LibTomMath Functions.} +\label{pic:design_process} +\end{figure} +\end{center} + +Only after the majority of the functions were in place did I pursue a less hierarchical approach to auditing and optimizing +the source code. For example, one day I may audit the multipliers and the next day the polynomial basis functions. + +It only makes sense to begin the text with the preliminary data types and support algorithms required as well. +This chapter discusses the core algorithms of the library which are the dependents for every other algorithm. + +\section{What is a Multiple Precision Integer?} +Recall that most programming languages, in particular ISO C \cite{ISOC}, only have fixed precision data types that on their own cannot +be used to represent values larger than their precision will allow. The purpose of multiple precision algorithms is +to use fixed precision data types to create and manipulate multiple precision integers which may represent values +that are very large. + +As a well known analogy, school children are taught how to form numbers larger than nine by prepending more radix ten digits. In the decimal system +the largest single digit value is $9$. However, by concatenating digits together larger numbers may be represented. Newly prepended digits +(\textit{to the left}) are said to be in a different power of ten column. That is, the number $123$ can be described as having a $1$ in the hundreds +column, $2$ in the tens column and $3$ in the ones column. Or more formally $123 = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0$. Computer based +multiple precision arithmetic is essentially the same concept. Larger integers are represented by adjoining fixed +precision computer words with the exception that a different radix is used. + +What most people probably do not think about explicitly are the various other attributes that describe a multiple precision +integer. For example, the integer $154_{10}$ has two immediately obvious properties. First, the integer is positive, +that is the sign of this particular integer is positive as opposed to negative. Second, the integer has three digits in +its representation. There is an additional property that the integer posesses that does not concern pencil-and-paper +arithmetic. The third property is how many digits placeholders are available to hold the integer. + +The human analogy of this third property is ensuring there is enough space on the paper to write the integer. For example, +if one starts writing a large number too far to the right on a piece of paper they will have to erase it and move left. +Similarly, computer algorithms must maintain strict control over memory usage to ensure that the digits of an integer +will not exceed the allowed boundaries. These three properties make up what is known as a multiple precision +integer or mp\_int for short. + +\subsection{The mp\_int Structure} +\label{sec:MPINT} +The mp\_int structure is the ISO C based manifestation of what represents a multiple precision integer. The ISO C standard does not provide for +any such data type but it does provide for making composite data types known as structures. The following is the structure definition +used within LibTomMath. + +\index{mp\_int} +\begin{figure}[here] +\begin{center} +\begin{small} +%\begin{verbatim} +\begin{tabular}{|l|} +\hline +typedef struct \{ \\ +\hspace{3mm}int used, alloc, sign;\\ +\hspace{3mm}mp\_digit *dp;\\ +\} \textbf{mp\_int}; \\ +\hline +\end{tabular} +%\end{verbatim} +\end{small} +\caption{The mp\_int Structure} +\label{fig:mpint} +\end{center} +\end{figure} + +The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows. + +\begin{enumerate} +\item The \textbf{used} parameter denotes how many digits of the array \textbf{dp} contain the digits used to represent +a given integer. The \textbf{used} count must be positive (or zero) and may not exceed the \textbf{alloc} count. + +\item The \textbf{alloc} parameter denotes how +many digits are available in the array to use by functions before it has to increase in size. When the \textbf{used} count +of a result would exceed the \textbf{alloc} count all of the algorithms will automatically increase the size of the +array to accommodate the precision of the result. + +\item The pointer \textbf{dp} points to a dynamically allocated array of digits that represent the given multiple +precision integer. It is padded with $(\textbf{alloc} - \textbf{used})$ zero digits. The array is maintained in a least +significant digit order. As a pencil and paper analogy the array is organized such that the right most digits are stored +first starting at the location indexed by zero\footnote{In C all arrays begin at zero.} in the array. For example, +if \textbf{dp} contains $\lbrace a, b, c, \ldots \rbrace$ where \textbf{dp}$_0 = a$, \textbf{dp}$_1 = b$, \textbf{dp}$_2 = c$, $\ldots$ then +it would represent the integer $a + b\beta + c\beta^2 + \ldots$ + +\index{MP\_ZPOS} \index{MP\_NEG} +\item The \textbf{sign} parameter denotes the sign as either zero/positive (\textbf{MP\_ZPOS}) or negative (\textbf{MP\_NEG}). +\end{enumerate} + +\subsubsection{Valid mp\_int Structures} +Several rules are placed on the state of an mp\_int structure and are assumed to be followed for reasons of efficiency. +The only exceptions are when the structure is passed to initialization functions such as mp\_init() and mp\_init\_copy(). + +\begin{enumerate} +\item The value of \textbf{alloc} may not be less than one. That is \textbf{dp} always points to a previously allocated +array of digits. +\item The value of \textbf{used} may not exceed \textbf{alloc} and must be greater than or equal to zero. +\item The value of \textbf{used} implies the digit at index $(used - 1)$ of the \textbf{dp} array is non-zero. That is, +leading zero digits in the most significant positions must be trimmed. + \begin{enumerate} + \item Digits in the \textbf{dp} array at and above the \textbf{used} location must be zero. + \end{enumerate} +\item The value of \textbf{sign} must be \textbf{MP\_ZPOS} if \textbf{used} is zero; +this represents the mp\_int value of zero. +\end{enumerate} + +\section{Argument Passing} +A convention of argument passing must be adopted early on in the development of any library. Making the function +prototypes consistent will help eliminate many headaches in the future as the library grows to significant complexity. +In LibTomMath the multiple precision integer functions accept parameters from left to right as pointers to mp\_int +structures. That means that the source (input) operands are placed on the left and the destination (output) on the right. +Consider the following examples. + +\begin{verbatim} + mp_mul(&a, &b, &c); /* c = a * b */ + mp_add(&a, &b, &a); /* a = a + b */ + mp_sqr(&a, &b); /* b = a * a */ +\end{verbatim} + +The left to right order is a fairly natural way to implement the functions since it lets the developer read aloud the +functions and make sense of them. For example, the first function would read ``multiply a and b and store in c''. + +Certain libraries (\textit{LIP by Lenstra for instance}) accept parameters the other way around, to mimic the order +of assignment expressions. That is, the destination (output) is on the left and arguments (inputs) are on the right. In +truth, it is entirely a matter of preference. In the case of LibTomMath the convention from the MPI library has been +adopted. + +Another very useful design consideration, provided for in LibTomMath, is whether to allow argument sources to also be a +destination. For example, the second example (\textit{mp\_add}) adds $a$ to $b$ and stores in $a$. This is an important +feature to implement since it allows the calling functions to cut down on the number of variables it must maintain. +However, to implement this feature specific care has to be given to ensure the destination is not modified before the +source is fully read. + +\section{Return Values} +A well implemented application, no matter what its purpose, should trap as many runtime errors as possible and return them +to the caller. By catching runtime errors a library can be guaranteed to prevent undefined behaviour. However, the end +developer can still manage to cause a library to crash. For example, by passing an invalid pointer an application may +fault by dereferencing memory not owned by the application. + +In the case of LibTomMath the only errors that are checked for are related to inappropriate inputs (division by zero for +instance) and memory allocation errors. It will not check that the mp\_int passed to any function is valid nor +will it check pointers for validity. Any function that can cause a runtime error will return an error code as an +\textbf{int} data type with one of the following values (fig \ref{fig:errcodes}). + +\index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM} +\begin{figure}[here] +\begin{center} +\begin{tabular}{|l|l|} +\hline \textbf{Value} & \textbf{Meaning} \\ +\hline \textbf{MP\_OKAY} & The function was successful \\ +\hline \textbf{MP\_VAL} & One of the input value(s) was invalid \\ +\hline \textbf{MP\_MEM} & The function ran out of heap memory \\ +\hline +\end{tabular} +\end{center} +\caption{LibTomMath Error Codes} +\label{fig:errcodes} +\end{figure} + +When an error is detected within a function it should free any memory it allocated, often during the initialization of +temporary mp\_ints, and return as soon as possible. The goal is to leave the system in the same state it was when the +function was called. Error checking with this style of API is fairly simple. + +\begin{verbatim} + int err; + if ((err = mp_add(&a, &b, &c)) != MP_OKAY) { + printf("Error: %s\n", mp_error_to_string(err)); + exit(EXIT_FAILURE); + } +\end{verbatim} + +The GMP \cite{GMP} library uses C style \textit{signals} to flag errors which is of questionable use. Not all errors are fatal +and it was not deemed ideal by the author of LibTomMath to force developers to have signal handlers for such cases. + +\section{Initialization and Clearing} +The logical starting point when actually writing multiple precision integer functions is the initialization and +clearing of the mp\_int structures. These two algorithms will be used by the majority of the higher level algorithms. + +Given the basic mp\_int structure an initialization routine must first allocate memory to hold the digits of +the integer. Often it is optimal to allocate a sufficiently large pre-set number of digits even though +the initial integer will represent zero. If only a single digit were allocated quite a few subsequent re-allocations +would occur when operations are performed on the integers. There is a tradeoff between how many default digits to allocate +and how many re-allocations are tolerable. Obviously allocating an excessive amount of digits initially will waste +memory and become unmanageable. + +If the memory for the digits has been successfully allocated then the rest of the members of the structure must +be initialized. Since the initial state of an mp\_int is to represent the zero integer, the allocated digits must be set +to zero. The \textbf{used} count set to zero and \textbf{sign} set to \textbf{MP\_ZPOS}. + +\subsection{Initializing an mp\_int} +An mp\_int is said to be initialized if it is set to a valid, preferably default, state such that all of the members of the +structure are set to valid values. The mp\_init algorithm will perform such an action. + +\index{mp\_init} +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_init}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. Allocate memory and initialize $a$ to a known valid mp\_int state. \\ +\hline \\ +1. Allocate memory for \textbf{MP\_PREC} digits. \\ +2. If the allocation failed return(\textit{MP\_MEM}) \\ +3. for $n$ from $0$ to $MP\_PREC - 1$ do \\ +\hspace{3mm}3.1 $a_n \leftarrow 0$\\ +4. $a.sign \leftarrow MP\_ZPOS$\\ +5. $a.used \leftarrow 0$\\ +6. $a.alloc \leftarrow MP\_PREC$\\ +7. Return(\textit{MP\_OKAY})\\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_init} +\end{figure} + +\textbf{Algorithm mp\_init.} +The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly +manipulte it. It is assumed that the input may not have had any of its members previously initialized which is certainly +a valid assumption if the input resides on the stack. + +Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for +the digits is allocated. If this fails the function returns before setting any of the other members. The \textbf{MP\_PREC} +name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.} +used to dictate the minimum precision of newly initialized mp\_int integers. Ideally, it is at least equal to the smallest +precision number you'll be working with. + +Allocating a block of digits at first instead of a single digit has the benefit of lowering the number of usually slow +heap operations later functions will have to perform in the future. If \textbf{MP\_PREC} is set correctly the slack +memory and the number of heap operations will be trivial. + +Once the allocation has been made the digits have to be set to zero as well as the \textbf{used}, \textbf{sign} and +\textbf{alloc} members initialized. This ensures that the mp\_int will always represent the default state of zero regardless +of the original condition of the input. + +\textbf{Remark.} +This function introduces the idiosyncrasy that all iterative loops, commonly initiated with the ``for'' keyword, iterate incrementally +when the ``to'' keyword is placed between two expressions. For example, ``for $a$ from $b$ to $c$ do'' means that +a subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$. In each +iteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$. If $b > c$ occured +the loop would not iterate. By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate +decrementally. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_init.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure. It +is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack. The +call to mp\_init() is used only to initialize the members of the structure to a known default state. + +Here we see (line 24) the memory allocation is performed first. This allows us to exit cleanly and quickly +if there is an error. If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there +was a memory error. The function XMALLOC is what actually allocates the memory. Technically XMALLOC is not a function +but a macro defined in ``tommath.h``. By default, XMALLOC will evaluate to malloc() which is the C library's built--in +memory allocation routine. + +In order to assure the mp\_int is in a known state the digits must be set to zero. On most platforms this could have been +accomplished by using calloc() instead of malloc(). However, to correctly initialize a integer type to a given value in a +portable fashion you have to actually assign the value. The for loop (line 30) performs this required +operation. + +After the memory has been successfully initialized the remainder of the members are initialized +(lines 34 through 35) to their respective default states. At this point the algorithm has succeeded and +a success code is returned to the calling function. If this function returns \textbf{MP\_OKAY} it is safe to assume the +mp\_int structure has been properly initialized and is safe to use with other functions within the library. + +\subsection{Clearing an mp\_int} +When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be +returned to the application's memory pool with the mp\_clear algorithm. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_clear}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. The memory for $a$ shall be deallocated. \\ +\hline \\ +1. If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\ +2. for $n$ from 0 to $a.used - 1$ do \\ +\hspace{3mm}2.1 $a_n \leftarrow 0$ \\ +3. Free the memory allocated for the digits of $a$. \\ +4. $a.used \leftarrow 0$ \\ +5. $a.alloc \leftarrow 0$ \\ +6. $a.sign \leftarrow MP\_ZPOS$ \\ +7. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_clear} +\end{figure} + +\textbf{Algorithm mp\_clear.} +This algorithm accomplishes two goals. First, it clears the digits and the other mp\_int members. This ensures that +if a developer accidentally re-uses a cleared structure it is less likely to cause problems. The second goal +is to free the allocated memory. + +The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this +algorithm will not try to free the memory multiple times. Cleared mp\_ints are detectable by having a pre-defined invalid +digit pointer \textbf{dp} setting. + +Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm +with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_clear.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The algorithm only operates on the mp\_int if it hasn't been previously cleared. The if statement (line 25) +checks to see if the \textbf{dp} member is not \textbf{NULL}. If the mp\_int is a valid mp\_int then \textbf{dp} cannot be +\textbf{NULL} in which case the if statement will evaluate to true. + +The digits of the mp\_int are cleared by the for loop (line 27) which assigns a zero to every digit. Similar to mp\_init() +the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable. + +The digits are deallocated off the heap via the XFREE macro. Similar to XMALLOC the XFREE macro actually evaluates to +a standard C library function. In this case the free() function. Since free() only deallocates the memory the pointer +still has to be reset to \textbf{NULL} manually (line 35). + +Now that the digits have been cleared and deallocated the other members are set to their final values (lines 36 and 37). + +\section{Maintenance Algorithms} + +The previous sections describes how to initialize and clear an mp\_int structure. To further support operations +that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be +able to augment the precision of an mp\_int and +initialize mp\_ints with differing initial conditions. + +These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level +algorithms such as addition, multiplication and modular exponentiation. + +\subsection{Augmenting an mp\_int's Precision} +When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire +result of an operation without loss of precision. Quite often the size of the array given by the \textbf{alloc} member +is large enough to simply increase the \textbf{used} digit count. However, when the size of the array is too small it +must be re-sized appropriately to accomodate the result. The mp\_grow algorithm will provide this functionality. + +\newpage\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_grow}. \\ +\textbf{Input}. An mp\_int $a$ and an integer $b$. \\ +\textbf{Output}. $a$ is expanded to accomodate $b$ digits. \\ +\hline \\ +1. if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\ +2. $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\ +3. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\ +4. Re-allocate the array of digits $a$ to size $v$ \\ +5. If the allocation failed then return(\textit{MP\_MEM}). \\ +6. for n from a.alloc to $v - 1$ do \\ +\hspace{+3mm}6.1 $a_n \leftarrow 0$ \\ +7. $a.alloc \leftarrow v$ \\ +8. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_grow} +\end{figure} + +\textbf{Algorithm mp\_grow.} +It is ideal to prevent re-allocations from being performed if they are not required (step one). This is useful to +prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow. + +The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three). +This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values. + +It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact. This is much +akin to how the \textit{realloc} function from the standard C library works. Since the newly allocated digits are +assumed to contain undefined values they are initially set to zero. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_grow.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +A quick optimization is to first determine if a memory re-allocation is required at all. The if statement (line 24) checks +if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count. If the count is not larger than \textbf{alloc} +the function skips the re-allocation part thus saving time. + +When a re-allocation is performed it is turned into an optimal request to save time in the future. The requested digit count is +padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line 25). The XREALLOC function is used +to re-allocate the memory. As per the other functions XREALLOC is actually a macro which evaluates to realloc by default. The realloc +function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before +the re-allocation. All that is left is to clear the newly allocated digits and return. + +Note that the re-allocation result is actually stored in a temporary pointer $tmp$. This is to allow this function to return +an error with a valid pointer. Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$. That would +result in a memory leak if XREALLOC ever failed. + +\subsection{Initializing Variable Precision mp\_ints} +Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size +of input mp\_ints to a given algorithm. The purpose of algorithm mp\_init\_size is similar to mp\_init except that it +will allocate \textit{at least} a specified number of digits. + +\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_init\_size}. \\ +\textbf{Input}. An mp\_int $a$ and the requested number of digits $b$. \\ +\textbf{Output}. $a$ is initialized to hold at least $b$ digits. \\ +\hline \\ +1. $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\ +2. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\ +3. Allocate $v$ digits. \\ +4. for $n$ from $0$ to $v - 1$ do \\ +\hspace{3mm}4.1 $a_n \leftarrow 0$ \\ +5. $a.sign \leftarrow MP\_ZPOS$\\ +6. $a.used \leftarrow 0$\\ +7. $a.alloc \leftarrow v$\\ +8. Return(\textit{MP\_OKAY})\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_init\_size} +\end{figure} + +\textbf{Algorithm mp\_init\_size.} +This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of +digits allocated can be controlled by the second input argument $b$. The input size is padded upwards so it is a +multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits. This padding is used to prevent trivial +allocations from becoming a bottleneck in the rest of the algorithms. + +Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero. This +particular algorithm is useful if it is known ahead of time the approximate size of the input. If the approximation is +correct no further memory re-allocations are required to work with the mp\_int. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_size.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The number of digits $b$ requested is padded (line 24) by first augmenting it to the next multiple of +\textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result. If the memory can be successfully allocated the +mp\_int is placed in a default state representing the integer zero. Otherwise, the error code \textbf{MP\_MEM} will be +returned (line 29). + +The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@). The +\textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set +to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines 33, 34 and 35). If the function +returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the +functions to work with. + +\subsection{Multiple Integer Initializations and Clearings} +Occasionally a function will require a series of mp\_int data types to be made available simultaneously. +The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single +statement. It is essentially a shortcut to multiple initializations. + +\newpage\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_init\_multi}. \\ +\textbf{Input}. Variable length array $V_k$ of mp\_int variables of length $k$. \\ +\textbf{Output}. The array is initialized such that each mp\_int of $V_k$ is ready to use. \\ +\hline \\ +1. for $n$ from 0 to $k - 1$ do \\ +\hspace{+3mm}1.1. Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\ +\hspace{+3mm}1.2. If initialization failed then do \\ +\hspace{+6mm}1.2.1. for $j$ from $0$ to $n$ do \\ +\hspace{+9mm}1.2.1.1. Free the mp\_int $V_j$ (\textit{mp\_clear}) \\ +\hspace{+6mm}1.2.2. Return(\textit{MP\_MEM}) \\ +2. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_init\_multi} +\end{figure} + +\textbf{Algorithm mp\_init\_multi.} +The algorithm will initialize the array of mp\_int variables one at a time. If a runtime error has been detected +(\textit{step 1.2}) all of the previously initialized variables are cleared. The goal is an ``all or nothing'' +initialization which allows for quick recovery from runtime errors. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_multi.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This function intializes a variable length list of mp\_int structure pointers. However, instead of having the mp\_int +structures in an actual C array they are simply passed as arguments to the function. This function makes use of the +``...'' argument syntax of the C programming language. The list is terminated with a final \textbf{NULL} argument +appended on the right. + +The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function. A count +$n$ of succesfully initialized mp\_int structures is maintained (line 48) such that if a failure does occur, +the algorithm can backtrack and free the previously initialized structures (lines 28 to 47). + + +\subsection{Clamping Excess Digits} +When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of +the function instead of checking during the computation. For example, a multiplication of a $i$ digit number by a +$j$ digit produces a result of at most $i + j$ digits. It is entirely possible that the result is $i + j - 1$ +though, with no final carry into the last position. However, suppose the destination had to be first expanded +(\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry. +That would be a considerable waste of time since heap operations are relatively slow. + +The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function +terminates. This way a single heap operation (\textit{at most}) is required. However, if the result was not checked +there would be an excess high order zero digit. + +For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$. The leading zero digit +will not contribute to the precision of the result. In fact, through subsequent operations more leading zero digits would +accumulate to the point the size of the integer would be prohibitive. As a result even though the precision is very +low the representation is excessively large. + +The mp\_clamp algorithm is designed to solve this very problem. It will trim high-order zeros by decrementing the +\textbf{used} count until a non-zero most significant digit is found. Also in this system, zero is considered to be a +positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to +\textbf{MP\_ZPOS}. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_clamp}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. Any excess leading zero digits of $a$ are removed \\ +\hline \\ +1. while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\ +\hspace{+3mm}1.1 $a.used \leftarrow a.used - 1$ \\ +2. if $a.used = 0$ then do \\ +\hspace{+3mm}2.1 $a.sign \leftarrow MP\_ZPOS$ \\ +\hline \\ +\end{tabular} +\end{center} +\caption{Algorithm mp\_clamp} +\end{figure} + +\textbf{Algorithm mp\_clamp.} +As can be expected this algorithm is very simple. The loop on step one is expected to iterate only once or twice at +the most. For example, this will happen in cases where there is not a carry to fill the last position. Step two fixes the sign for +when all of the digits are zero to ensure that the mp\_int is valid at all times. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_clamp.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Note on line 28 how to test for the \textbf{used} count is made on the left of the \&\& operator. In the C programming +language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails. This is +important since if the \textbf{used} is zero the test on the right would fetch below the array. That is obviously +undesirable. The parenthesis on line 31 is used to make sure the \textbf{used} count is decremented and not +the pointer ``a''. + +\section*{Exercises} +\begin{tabular}{cl} +$\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\ + & \\ +$\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations. \\ + & \\ +$\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\ + & encryption when $\beta = 2^{28}$. \\ + & \\ +$\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp. What does it prevent? \\ + & \\ +$\left [ 1 \right ]$ & Give an example of when the algorithm mp\_init\_copy might be useful. \\ + & \\ +\end{tabular} + + +%%% +% CHAPTER FOUR +%%% + +\chapter{Basic Operations} + +\section{Introduction} +In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining +mp\_int structures. This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low +level basis of the entire library. While these algorithm are relatively trivial it is important to understand how they +work before proceeding since these algorithms will be used almost intrinsically in the following chapters. + +The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of +mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures +represent. + +\section{Assigning Values to mp\_int Structures} +\subsection{Copying an mp\_int} +Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making +a copy for the purposes of this text. The copy of the mp\_int will be a separate entity that represents the same +value as the mp\_int it was copied from. The mp\_copy algorithm provides this functionality. + +\newpage\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_copy}. \\ +\textbf{Input}. An mp\_int $a$ and $b$. \\ +\textbf{Output}. Store a copy of $a$ in $b$. \\ +\hline \\ +1. If $b.alloc < a.used$ then grow $b$ to $a.used$ digits. (\textit{mp\_grow}) \\ +2. for $n$ from 0 to $a.used - 1$ do \\ +\hspace{3mm}2.1 $b_{n} \leftarrow a_{n}$ \\ +3. for $n$ from $a.used$ to $b.used - 1$ do \\ +\hspace{3mm}3.1 $b_{n} \leftarrow 0$ \\ +4. $b.used \leftarrow a.used$ \\ +5. $b.sign \leftarrow a.sign$ \\ +6. return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_copy} +\end{figure} + +\textbf{Algorithm mp\_copy.} +This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will +represent the same integer as the mp\_int $a$. The mp\_int $b$ shall be a complete and distinct copy of the +mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$. + +If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow +algorithm. The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two +and three). The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of +$b$. + +\textbf{Remark.} This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the +text. The error return codes of other algorithms are not explicitly checked in the pseudo-code presented. For example, in +step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded. Text space is +limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return +the error code itself. However, the C code presented will demonstrate all of the error handling logic required to +implement the pseudo-code. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_copy.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output +mp\_int structures passed to a function are one and the same. For this case it is optimal to return immediately without +copying digits (line 25). + +The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$. If $b.alloc$ is less than +$a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines 30 to 33). In order to +simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits +of the mp\_ints $a$ and $b$ respectively. These aliases (lines 43 and 46) allow the compiler to access the digits without first dereferencing the +mp\_int pointers and then subsequently the pointer to the digits. + +After the aliases are established the digits from $a$ are copied into $b$ (lines 49 to 51) and then the excess +digits of $b$ are set to zero (lines 54 to 56). Both ``for'' loops make use of the pointer aliases and in +fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits. This optimization +allows the alias to stay in a machine register fairly easy between the two loops. + +\textbf{Remarks.} The use of pointer aliases is an implementation methodology first introduced in this function that will +be used considerably in other functions. Technically, a pointer alias is simply a short hand alias used to lower the +number of pointer dereferencing operations required to access data. For example, a for loop may resemble + +\begin{alltt} +for (x = 0; x < 100; x++) \{ + a->num[4]->dp[x] = 0; +\} +\end{alltt} + +This could be re-written using aliases as + +\begin{alltt} +mp_digit *tmpa; +a = a->num[4]->dp; +for (x = 0; x < 100; x++) \{ + *a++ = 0; +\} +\end{alltt} + +In this case an alias is used to access the +array of digits within an mp\_int structure directly. It may seem that a pointer alias is strictly not required +as a compiler may optimize out the redundant pointer operations. However, there are two dominant reasons to use aliases. + +The first reason is that most compilers will not effectively optimize pointer arithmetic. For example, some optimizations +may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC). Also some optimizations may +work for GCC and not MSVC. As such it is ideal to find a common ground for as many compilers as possible. Pointer +aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code +stands a better chance of being faster. + +The second reason is that pointer aliases often can make an algorithm simpler to read. Consider the first ``for'' +loop of the function mp\_copy() re-written to not use pointer aliases. + +\begin{alltt} + /* copy all the digits */ + for (n = 0; n < a->used; n++) \{ + b->dp[n] = a->dp[n]; + \} +\end{alltt} + +Whether this code is harder to read depends strongly on the individual. However, it is quantifiably slightly more +complicated as there are four variables within the statement instead of just two. + +\subsubsection{Nested Statements} +Another commonly used technique in the source routines is that certain sections of code are nested. This is used in +particular with the pointer aliases to highlight code phases. For example, a Comba multiplier (discussed in chapter six) +will typically have three different phases. First the temporaries are initialized, then the columns calculated and +finally the carries are propagated. In this example the middle column production phase will typically be nested as it +uses temporary variables and aliases the most. + +The nesting also simplies the source code as variables that are nested are only valid for their scope. As a result +the various temporary variables required do not propagate into other sections of code. + + +\subsection{Creating a Clone} +Another common operation is to make a local temporary copy of an mp\_int argument. To initialize an mp\_int +and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone. This is +useful within functions that need to modify an argument but do not wish to actually modify the original copy. The +mp\_init\_copy algorithm has been designed to help perform this task. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_init\_copy}. \\ +\textbf{Input}. An mp\_int $a$ and $b$\\ +\textbf{Output}. $a$ is initialized to be a copy of $b$. \\ +\hline \\ +1. Init $a$. (\textit{mp\_init}) \\ +2. Copy $b$ to $a$. (\textit{mp\_copy}) \\ +3. Return the status of the copy operation. \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_init\_copy} +\end{figure} + +\textbf{Algorithm mp\_init\_copy.} +This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it. As +such this algorithm will perform two operations in one step. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_copy.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}. Note that +\textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call +and \textbf{a} will be left intact. + +\section{Zeroing an Integer} +Reseting an mp\_int to the default state is a common step in many algorithms. The mp\_zero algorithm will be the algorithm used to +perform this task. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_zero}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. Zero the contents of $a$ \\ +\hline \\ +1. $a.used \leftarrow 0$ \\ +2. $a.sign \leftarrow$ MP\_ZPOS \\ +3. for $n$ from 0 to $a.alloc - 1$ do \\ +\hspace{3mm}3.1 $a_n \leftarrow 0$ \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_zero} +\end{figure} + +\textbf{Algorithm mp\_zero.} +This algorithm simply resets a mp\_int to the default state. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_zero.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the +\textbf{sign} variable is set to \textbf{MP\_ZPOS}. + +\section{Sign Manipulation} +\subsection{Absolute Value} +With the mp\_int representation of an integer, calculating the absolute value is trivial. The mp\_abs algorithm will compute +the absolute value of an mp\_int. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_abs}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. Computes $b = \vert a \vert$ \\ +\hline \\ +1. Copy $a$ to $b$. (\textit{mp\_copy}) \\ +2. If the copy failed return(\textit{MP\_MEM}). \\ +3. $b.sign \leftarrow MP\_ZPOS$ \\ +4. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_abs} +\end{figure} + +\textbf{Algorithm mp\_abs.} +This algorithm computes the absolute of an mp\_int input. First it copies $a$ over $b$. This is an example of an +algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful. This allows, +for instance, the developer to pass the same mp\_int as the source and destination to this function without addition +logic to handle it. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_abs.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This fairly trivial algorithm first eliminates non--required duplications (line 28) and then sets the +\textbf{sign} flag to \textbf{MP\_ZPOS}. + +\subsection{Integer Negation} +With the mp\_int representation of an integer, calculating the negation is also trivial. The mp\_neg algorithm will compute +the negative of an mp\_int input. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_neg}. \\ +\textbf{Input}. An mp\_int $a$ \\ +\textbf{Output}. Computes $b = -a$ \\ +\hline \\ +1. Copy $a$ to $b$. (\textit{mp\_copy}) \\ +2. If the copy failed return(\textit{MP\_MEM}). \\ +3. If $a.used = 0$ then return(\textit{MP\_OKAY}). \\ +4. If $a.sign = MP\_ZPOS$ then do \\ +\hspace{3mm}4.1 $b.sign = MP\_NEG$. \\ +5. else do \\ +\hspace{3mm}5.1 $b.sign = MP\_ZPOS$. \\ +6. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_neg} +\end{figure} + +\textbf{Algorithm mp\_neg.} +This algorithm computes the negation of an input. First it copies $a$ over $b$. If $a$ has no used digits then +the algorithm returns immediately. Otherwise it flips the sign flag and stores the result in $b$. Note that if +$a$ had no digits then it must be positive by definition. Had step three been omitted then the algorithm would return +zero as negative. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_neg.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Like mp\_abs() this function avoids non--required duplications (line 22) and then sets the sign. We +have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}. If the mp\_int is zero +than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}. + +\section{Small Constants} +\subsection{Setting Small Constants} +Often a mp\_int must be set to a relatively small value such as $1$ or $2$. For these cases the mp\_set algorithm is useful. + +\newpage\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_set}. \\ +\textbf{Input}. An mp\_int $a$ and a digit $b$ \\ +\textbf{Output}. Make $a$ equivalent to $b$ \\ +\hline \\ +1. Zero $a$ (\textit{mp\_zero}). \\ +2. $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\ +3. $a.used \leftarrow \left \lbrace \begin{array}{ll} + 1 & \mbox{if }a_0 > 0 \\ + 0 & \mbox{if }a_0 = 0 + \end{array} \right .$ \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_set} +\end{figure} + +\textbf{Algorithm mp\_set.} +This algorithm sets a mp\_int to a small single digit value. Step number 1 ensures that the integer is reset to the default state. The +single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_set.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +First we zero (line 21) the mp\_int to make sure that the other members are initialized for a +small positive constant. mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count +is zero. Next we set the digit and reduce it modulo $\beta$ (line 22). After this step we have to +check if the resulting digit is zero or not. If it is not then we set the \textbf{used} count to one, otherwise +to zero. + +We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with +$2^k - 1$ will perform the same operation. + +One important limitation of this function is that it will only set one digit. The size of a digit is not fixed, meaning source that uses +this function should take that into account. Only trivially small constants can be set using this function. + +\subsection{Setting Large Constants} +To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal. It accepts a ``long'' +data type as input and will always treat it as a 32-bit integer. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_set\_int}. \\ +\textbf{Input}. An mp\_int $a$ and a ``long'' integer $b$ \\ +\textbf{Output}. Make $a$ equivalent to $b$ \\ +\hline \\ +1. Zero $a$ (\textit{mp\_zero}) \\ +2. for $n$ from 0 to 7 do \\ +\hspace{3mm}2.1 $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\ +\hspace{3mm}2.2 $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\ +\hspace{3mm}2.3 $a_0 \leftarrow a_0 + u$ \\ +\hspace{3mm}2.4 $a.used \leftarrow a.used + 1$ \\ +3. Clamp excess used digits (\textit{mp\_clamp}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_set\_int} +\end{figure} + +\textbf{Algorithm mp\_set\_int.} +The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the +mp\_int. Step 2.1 will multiply the current result by sixteen making room for four more bits in the less significant positions. In step 2.2 the +next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is +incremented to reflect the addition. The \textbf{used} digit counter is incremented since if any of the leading digits were zero the mp\_int would have +zero digits used and the newly added four bits would be ignored. + +Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_set\_int.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes. The weird +addition on line 39 ensures that the newly added in bits are added to the number of digits. While it may not +seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line 28 +as well as the call to mp\_clamp() on line 41. Both functions will clamp excess leading digits which keeps +the number of used digits low. + +\section{Comparisons} +\subsection{Unsigned Comparisions} +Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers. For example, +to compare $1,234$ to $1,264$ the digits are extracted by their positions. That is we compare $1 \cdot 10^3 + 2 \cdot 10^2 + 3 \cdot 10^1 + 4 \cdot 10^0$ +to $1 \cdot 10^3 + 2 \cdot 10^2 + 6 \cdot 10^1 + 4 \cdot 10^0$ by comparing single digits at a time starting with the highest magnitude +positions. If any leading digit of one integer is greater than a digit in the same position of another integer then obviously it must be greater. + +The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two +mp\_int variables alone. It will ignore the sign of the two inputs. Such a function is useful when an absolute comparison is required or if the +signs are known to agree in advance. + +To facilitate working with the results of the comparison functions three constants are required. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{|r|l|} +\hline \textbf{Constant} & \textbf{Meaning} \\ +\hline \textbf{MP\_GT} & Greater Than \\ +\hline \textbf{MP\_EQ} & Equal To \\ +\hline \textbf{MP\_LT} & Less Than \\ +\hline +\end{tabular} +\end{center} +\caption{Comparison Return Codes} +\end{figure} + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_cmp\_mag}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$. \\ +\textbf{Output}. Unsigned comparison results ($a$ to the left of $b$). \\ +\hline \\ +1. If $a.used > b.used$ then return(\textit{MP\_GT}) \\ +2. If $a.used < b.used$ then return(\textit{MP\_LT}) \\ +3. for n from $a.used - 1$ to 0 do \\ +\hspace{+3mm}3.1 if $a_n > b_n$ then return(\textit{MP\_GT}) \\ +\hspace{+3mm}3.2 if $a_n < b_n$ then return(\textit{MP\_LT}) \\ +4. Return(\textit{MP\_EQ}) \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_cmp\_mag} +\end{figure} + +\textbf{Algorithm mp\_cmp\_mag.} +By saying ``$a$ to the left of $b$'' it is meant that the comparison is with respect to $a$, that is if $a$ is greater than $b$ it will return +\textbf{MP\_GT} and similar with respect to when $a = b$ and $a < b$. The first two steps compare the number of digits used in both $a$ and $b$. +Obviously if the digit counts differ there would be an imaginary zero digit in the smaller number where the leading digit of the larger number is. +If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit. + +By step three both inputs must have the same number of digits so its safe to start from either $a.used - 1$ or $b.used - 1$ and count down to +the zero'th digit. If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_cmp\_mag.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The two if statements (lines 25 and 29) compare the number of digits in the two inputs. These two are +performed before all of the digits are compared since it is a very cheap test to perform and can potentially save +considerable time. The implementation given is also not valid without those two statements. $b.alloc$ may be +smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits. + + + +\subsection{Signed Comparisons} +Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}). Based on an unsigned magnitude +comparison a trivial signed comparison algorithm can be written. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_cmp}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$ \\ +\textbf{Output}. Signed Comparison Results ($a$ to the left of $b$) \\ +\hline \\ +1. if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\ +2. if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\ +3. if $a.sign = MP\_NEG$ then \\ +\hspace{+3mm}3.1 Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\ +4 Otherwise \\ +\hspace{+3mm}4.1 Return the unsigned comparison of $a$ and $b$ \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_cmp} +\end{figure} + +\textbf{Algorithm mp\_cmp.} +The first two steps compare the signs of the two inputs. If the signs do not agree then it can return right away with the appropriate +comparison code. When the signs are equal the digits of the inputs must be compared to determine the correct result. In step +three the unsigned comparision flips the order of the arguments since they are both negative. For instance, if $-a > -b$ then +$\vert a \vert < \vert b \vert$. Step number four will compare the two when they are both positive. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_cmp.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The two if statements (lines 23 and 24) perform the initial sign comparison. If the signs are not the equal then which ever +has the positive sign is larger. The inputs are compared (line 32) based on magnitudes. If the signs were both +negative then the unsigned comparison is performed in the opposite direction (line 34). Otherwise, the signs are assumed to +be both positive and a forward direction unsigned comparison is performed. + +\section*{Exercises} +\begin{tabular}{cl} +$\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\ + & \\ +$\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits \\ + & of two random digits (of equal magnitude) before a difference is found. \\ + & \\ +$\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based \\ + & on the observations made in the previous problem. \\ + & +\end{tabular} + +\chapter{Basic Arithmetic} +\section{Introduction} +At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been +established. The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms. These +algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms. It is very important +that these algorithms are highly optimized. On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms +which easily places them at $O(n^2)$ or even $O(n^3)$ work levels. + +All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right +logical shifts respectively. A logical shift is analogous to sliding the decimal point of radix-10 representations. For example, the real +number $0.9345$ is equivalent to $93.45\%$ which is found by sliding the the decimal two places to the right (\textit{multiplying by $\beta^2 = 10^2$}). +Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two. +For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$. + +One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed +from the number. For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$. However, with a logical shift the +result is $110_2$. + +\section{Addition and Subtraction} +In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus. For example, with 32-bit integers +$a - b\mbox{ (mod }2^{32}\mbox{)}$ is the same as $a + (2^{32} - b) \mbox{ (mod }2^{32}\mbox{)}$ since $2^{32} \equiv 0 \mbox{ (mod }2^{32}\mbox{)}$. +As a result subtraction can be performed with a trivial series of logical operations and an addition. + +However, in multiple precision arithmetic negative numbers are not represented in the same way. Instead a sign flag is used to keep track of the +sign of the integer. As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or +subtraction algorithms with the sign fixed up appropriately. + +The lower level algorithms will add or subtract integers without regard to the sign flag. That is they will add or subtract the magnitude of +the integers respectively. + +\subsection{Low Level Addition} +An unsigned addition of multiple precision integers is performed with the same long-hand algorithm used to add decimal numbers. That is to add the +trailing digits first and propagate the resulting carry upwards. Since this is a lower level algorithm the name will have a ``s\_'' prefix. +Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely. + +\newpage +\begin{figure}[!here] +\begin{center} +\begin{small} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_add}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$ \\ +\textbf{Output}. The unsigned addition $c = \vert a \vert + \vert b \vert$. \\ +\hline \\ +1. if $a.used > b.used$ then \\ +\hspace{+3mm}1.1 $min \leftarrow b.used$ \\ +\hspace{+3mm}1.2 $max \leftarrow a.used$ \\ +\hspace{+3mm}1.3 $x \leftarrow a$ \\ +2. else \\ +\hspace{+3mm}2.1 $min \leftarrow a.used$ \\ +\hspace{+3mm}2.2 $max \leftarrow b.used$ \\ +\hspace{+3mm}2.3 $x \leftarrow b$ \\ +3. If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\ +4. $oldused \leftarrow c.used$ \\ +5. $c.used \leftarrow max + 1$ \\ +6. $u \leftarrow 0$ \\ +7. for $n$ from $0$ to $min - 1$ do \\ +\hspace{+3mm}7.1 $c_n \leftarrow a_n + b_n + u$ \\ +\hspace{+3mm}7.2 $u \leftarrow c_n >> lg(\beta)$ \\ +\hspace{+3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ +8. if $min \ne max$ then do \\ +\hspace{+3mm}8.1 for $n$ from $min$ to $max - 1$ do \\ +\hspace{+6mm}8.1.1 $c_n \leftarrow x_n + u$ \\ +\hspace{+6mm}8.1.2 $u \leftarrow c_n >> lg(\beta)$ \\ +\hspace{+6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ +9. $c_{max} \leftarrow u$ \\ +10. if $olduse > max$ then \\ +\hspace{+3mm}10.1 for $n$ from $max + 1$ to $oldused - 1$ do \\ +\hspace{+6mm}10.1.1 $c_n \leftarrow 0$ \\ +11. Clamp excess digits in $c$. (\textit{mp\_clamp}) \\ +12. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Algorithm s\_mp\_add} +\end{figure} + +\textbf{Algorithm s\_mp\_add.} +This algorithm is loosely based on algorithm 14.7 of HAC \cite[pp. 594]{HAC} but has been extended to allow the inputs to have different magnitudes. +Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}. Even the +MIX pseudo machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes. + +The first thing that has to be accomplished is to sort out which of the two inputs is the largest. The addition logic +will simply add all of the smallest input to the largest input and store that first part of the result in the +destination. Then it will apply a simpler addition loop to excess digits of the larger input. + +The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two +inputs. The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the +same number of digits. After the inputs are sorted the destination $c$ is grown as required to accomodate the sum +of the two inputs. The original \textbf{used} count of $c$ is copied and set to the new used count. + +At this point the first addition loop will go through as many digit positions that both inputs have. The carry +variable $\mu$ is set to zero outside the loop. Inside the loop an ``addition'' step requires three statements to produce +one digit of the summand. First +two digits from $a$ and $b$ are added together along with the carry $\mu$. The carry of this step is extracted and stored +in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$. + +Now all of the digit positions that both inputs have in common have been exhausted. If $min \ne max$ then $x$ is an alias +for one of the inputs that has more digits. A simplified addition loop is then used to essentially copy the remaining digits +and the carry to the destination. + +The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition. + + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_add.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +We first sort (lines 28 to 36) the inputs based on magnitude and determine the $min$ and $max$ variables. +Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias. Next we +grow the destination (38 to 42) ensure that it can accomodate the result of the addition. + +Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style. The three aliases that are on +lines 56, 59 and 62 represent the two inputs and destination variables respectively. These aliases are used to ensure the +compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int. + +The initial carry $u$ will be cleared (line 65), note that $u$ is of type mp\_digit which ensures type +compatibility within the implementation. The initial addition (line 66 to 75) adds digits from +both inputs until the smallest input runs out of digits. Similarly the conditional addition loop +(line 81 to 90) adds the remaining digits from the larger of the two inputs. The addition is finished +with the final carry being stored in $tmpc$ (line 94). Note the ``++'' operator within the same expression. +After line 94, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$. This is useful +for the next loop (line 97 to 99) which set any old upper digits to zero. + +\subsection{Low Level Subtraction} +The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm. The principle difference is that the +unsigned subtraction algorithm requires the result to be positive. That is when computing $a - b$ the condition $\vert a \vert \ge \vert b\vert$ must +be met for this algorithm to function properly. Keep in mind this low level algorithm is not meant to be used in higher level algorithms directly. +This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms. + + +For this algorithm a new variable is required to make the description simpler. Recall from section 1.3.1 that a mp\_digit must be able to represent +the range $0 \le x < 2\beta$ for the algorithms to work correctly. However, it is allowable that a mp\_digit represent a larger range of values. For +this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a +mp\_digit (\textit{this implies $2^{\gamma} > \beta$}). + +For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$. In ISO C an ``unsigned long'' +data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$. + +\newpage\begin{figure}[!here] +\begin{center} +\begin{small} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_sub}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\ +\textbf{Output}. The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\ +\hline \\ +1. $min \leftarrow b.used$ \\ +2. $max \leftarrow a.used$ \\ +3. If $c.alloc < max$ then grow $c$ to hold at least $max$ digits. (\textit{mp\_grow}) \\ +4. $oldused \leftarrow c.used$ \\ +5. $c.used \leftarrow max$ \\ +6. $u \leftarrow 0$ \\ +7. for $n$ from $0$ to $min - 1$ do \\ +\hspace{3mm}7.1 $c_n \leftarrow a_n - b_n - u$ \\ +\hspace{3mm}7.2 $u \leftarrow c_n >> (\gamma - 1)$ \\ +\hspace{3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ +8. if $min < max$ then do \\ +\hspace{3mm}8.1 for $n$ from $min$ to $max - 1$ do \\ +\hspace{6mm}8.1.1 $c_n \leftarrow a_n - u$ \\ +\hspace{6mm}8.1.2 $u \leftarrow c_n >> (\gamma - 1)$ \\ +\hspace{6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ +9. if $oldused > max$ then do \\ +\hspace{3mm}9.1 for $n$ from $max$ to $oldused - 1$ do \\ +\hspace{6mm}9.1.1 $c_n \leftarrow 0$ \\ +10. Clamp excess digits of $c$. (\textit{mp\_clamp}). \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Algorithm s\_mp\_sub} +\end{figure} + +\textbf{Algorithm s\_mp\_sub.} +This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive. That is when +passing variables $a$ and $b$ the condition that $\vert a \vert \ge \vert b \vert$ must be met for the algorithm to function correctly. This +algorithm is loosely based on algorithm 14.9 \cite[pp. 595]{HAC} and is similar to algorithm S in \cite[pp. 267]{TAOCPV2} as well. As was the case +of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude. + +The initial sorting of the inputs is trivial in this algorithm since $a$ is guaranteed to have at least the same magnitude of $b$. Steps 1 and 2 +set the $min$ and $max$ variables. Unlike the addition routine there is guaranteed to be no carry which means that the final result can be at +most $max$ digits in length as opposed to $max + 1$. Similar to the addition algorithm the \textbf{used} count of $c$ is copied locally and +set to the maximal count for the operation. + +The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision +subtraction is used instead. Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction +loops. Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry. + +For example, consider subtracting $0101_2$ from $0100_2$ where $\gamma = 4$ and $\beta = 2$. The least significant bit will force a carry upwards to +the third bit which will be set to zero after the borrow. After the very first bit has been subtracted $4 - 1 \equiv 0011_2$ will remain, When the +third bit of $0101_2$ is subtracted from the result it will cause another carry. In this case though the carry will be forced to propagate all the +way to the most significant bit. + +Recall that $\beta < 2^{\gamma}$. This means that if a carry does occur just before the $lg(\beta)$'th bit it will propagate all the way to the most +significant bit. Thus, the high order bits of the mp\_digit that are not part of the actual digit will either be all zero, or all one. All that +is needed is a single zero or one bit for the carry. Therefore a single logical shift right by $\gamma - 1$ positions is sufficient to extract the +carry. This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed. + +If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and copy operation to propagate through the larger input $a$ into $c$. Step +10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sub.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Like low level addition we ``sort'' the inputs. Except in this case the sorting is hardcoded +(lines 25 and 26). In reality the $min$ and $max$ variables are only aliases and are only +used to make the source code easier to read. Again the pointer alias optimization is used +within this algorithm. The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized +(lines 42, 43 and 44) for $a$, $b$ and $c$ respectively. + +The first subtraction loop (lines 47 through 61) subtract digits from both inputs until the smaller of +the two inputs has been exhausted. As remarked earlier there is an implementation reason for using the ``awkward'' +method of extracting the carry (line 57). The traditional method for extracting the carry would be to shift +by $lg(\beta)$ positions and logically AND the least significant bit. The AND operation is required because all of +the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction. This carry +extraction requires two relatively cheap operations to extract the carry. The other method is to simply shift the +most significant bit to the least significant bit thus extracting the carry with a single cheap operation. This +optimization only works on twos compliment machines which is a safe assumption to make. + +If $a$ has a larger magnitude than $b$ an additional loop (lines 64 through 73) is required to propagate +the carry through $a$ and copy the result to $c$. + +\subsection{High Level Addition} +Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be +established. This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data +types. + +Recall from section 5.2 that an mp\_int represents an integer with an unsigned mantissa (\textit{the array of digits}) and a \textbf{sign} +flag. A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases. + +\begin{figure}[!here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_add}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$ \\ +\textbf{Output}. The signed addition $c = a + b$. \\ +\hline \\ +1. if $a.sign = b.sign$ then do \\ +\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\ +\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\ +2. else do \\ +\hspace{3mm}2.1 if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\ +\hspace{6mm}2.1.1 $c.sign \leftarrow b.sign$ \\ +\hspace{6mm}2.1.2 $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\ +\hspace{3mm}2.2 else do \\ +\hspace{6mm}2.2.1 $c.sign \leftarrow a.sign$ \\ +\hspace{6mm}2.2.2 $c \leftarrow \vert a \vert - \vert b \vert$ \\ +3. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_add} +\end{figure} + +\textbf{Algorithm mp\_add.} +This algorithm performs the signed addition of two mp\_int variables. There is no reference algorithm to draw upon from +either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations. The algorithm is fairly +straightforward but restricted since subtraction can only produce positive results. + +\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{|c|c|c|c|c|} +\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\ +\hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\ +\hline $+$ & $+$ & No & $c = a + b$ & $a.sign$ \\ +\hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\ +\hline $-$ & $-$ & No & $c = a + b$ & $a.sign$ \\ +\hline &&&&\\ + +\hline $+$ & $-$ & No & $c = b - a$ & $b.sign$ \\ +\hline $-$ & $+$ & No & $c = b - a$ & $b.sign$ \\ + +\hline &&&&\\ + +\hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\ +\hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\ + +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Addition Guide Chart} +\label{fig:AddChart} +\end{figure} + +Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three +specific cases need to be handled. The return code of the unsigned operations at step 1.2, 2.1.2 and 2.2.2 are +forwarded to step three to check for errors. This simplifies the description of the algorithm considerably and best +follows how the implementation actually was achieved. + +Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed. Recall from the descriptions of algorithms +s\_mp\_add and s\_mp\_sub that the mp\_clamp function is used at the end to trim excess digits. The mp\_clamp algorithm will set the \textbf{sign} +to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero. + +For example, consider performing $-a + a$ with algorithm mp\_add. By the description of the algorithm the sign is set to \textbf{MP\_NEG} which would +produce a result of $-0$. However, since the sign is set first then the unsigned addition is performed the subsequent usage of algorithm mp\_clamp +within algorithm s\_mp\_add will force $-0$ to become $0$. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_add.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The source code follows the algorithm fairly closely. The most notable new source code addition is the usage of the $res$ integer variable which +is used to pass result of the unsigned operations forward. Unlike in the algorithm, the variable $res$ is merely returned as is without +explicitly checking it and returning the constant \textbf{MP\_OKAY}. The observation is this algorithm will succeed or fail only if the lower +level functions do so. Returning their return code is sufficient. + +\subsection{High Level Subtraction} +The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm. + +\newpage\begin{figure}[!here] +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_sub}. \\ +\textbf{Input}. Two mp\_ints $a$ and $b$ \\ +\textbf{Output}. The signed subtraction $c = a - b$. \\ +\hline \\ +1. if $a.sign \ne b.sign$ then do \\ +\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\ +\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\ +2. else do \\ +\hspace{3mm}2.1 if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\ +\hspace{6mm}2.1.1 $c.sign \leftarrow a.sign$ \\ +\hspace{6mm}2.1.2 $c \leftarrow \vert a \vert - \vert b \vert$ (\textit{s\_mp\_sub}) \\ +\hspace{3mm}2.2 else do \\ +\hspace{6mm}2.2.1 $c.sign \leftarrow \left \lbrace \begin{array}{ll} + MP\_ZPOS & \mbox{if }a.sign = MP\_NEG \\ + MP\_NEG & \mbox{otherwise} \\ + \end{array} \right .$ \\ +\hspace{6mm}2.2.2 $c \leftarrow \vert b \vert - \vert a \vert$ \\ +3. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\caption{Algorithm mp\_sub} +\end{figure} + +\textbf{Algorithm mp\_sub.} +This algorithm performs the signed subtraction of two inputs. Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or +\cite{HAC}. Also this algorithm is restricted by algorithm s\_mp\_sub. Chart \ref{fig:SubChart} lists the eight possible inputs and +the operations required. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{|c|c|c|c|c|} +\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\ +\hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\ +\hline $+$ & $-$ & No & $c = a + b$ & $a.sign$ \\ +\hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\ +\hline $-$ & $+$ & No & $c = a + b$ & $a.sign$ \\ +\hline &&&& \\ +\hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\ +\hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\ +\hline &&&& \\ +\hline $+$ & $+$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\ +\hline $-$ & $-$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Subtraction Guide Chart} +\label{fig:SubChart} +\end{figure} + +Similar to the case of algorithm mp\_add the \textbf{sign} is set first before the unsigned addition or subtraction. That is to prevent the +algorithm from producing $-a - -a = -0$ as a result. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_sub.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Much like the implementation of algorithm mp\_add the variable $res$ is used to catch the return code of the unsigned addition or subtraction operations +and forward it to the end of the function. On line 39 the ``not equal to'' \textbf{MP\_LT} expression is used to emulate a +``greater than or equal to'' comparison. + +\section{Bit and Digit Shifting} +It is quite common to think of a multiple precision integer as a polynomial in $x$, that is $y = f(\beta)$ where $f(x) = \sum_{i=0}^{n-1} a_i x^i$. +This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring. + +In order to facilitate operations on polynomials in $x$ as above a series of simple ``digit'' algorithms have to be established. That is to shift +the digits left or right as well to shift individual bits of the digits left and right. It is important to note that not all ``shift'' operations +are on radix-$\beta$ digits. + +\subsection{Multiplication by Two} + +In a binary system where the radix is a power of two multiplication by two not only arises often in other algorithms it is a fairly efficient +operation to perform. A single precision logical shift left is sufficient to multiply a single digit by two. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_mul\_2}. \\ +\textbf{Input}. One mp\_int $a$ \\ +\textbf{Output}. $b = 2a$. \\ +\hline \\ +1. If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits. (\textit{mp\_grow}) \\ +2. $oldused \leftarrow b.used$ \\ +3. $b.used \leftarrow a.used$ \\ +4. $r \leftarrow 0$ \\ +5. for $n$ from 0 to $a.used - 1$ do \\ +\hspace{3mm}5.1 $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\ +\hspace{3mm}5.2 $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}5.3 $r \leftarrow rr$ \\ +6. If $r \ne 0$ then do \\ +\hspace{3mm}6.1 $b_{n + 1} \leftarrow r$ \\ +\hspace{3mm}6.2 $b.used \leftarrow b.used + 1$ \\ +7. If $b.used < oldused - 1$ then do \\ +\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\ +\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\ +8. $b.sign \leftarrow a.sign$ \\ +9. Return(\textit{MP\_OKAY}).\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_mul\_2} +\end{figure} + +\textbf{Algorithm mp\_mul\_2.} +This algorithm will quickly multiply a mp\_int by two provided $\beta$ is a power of two. Neither \cite{TAOCPV2} nor \cite{HAC} describe such +an algorithm despite the fact it arises often in other algorithms. The algorithm is setup much like the lower level algorithm s\_mp\_add since +it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$. + +Step 1 and 2 grow the input as required to accomodate the maximum number of \textbf{used} digits in the result. The initial \textbf{used} count +is set to $a.used$ at step 4. Only if there is a final carry will the \textbf{used} count require adjustment. + +Step 6 is an optimization implementation of the addition loop for this specific case. That is since the two values being added together +are the same there is no need to perform two reads from the digits of $a$. Step 6.1 performs a single precision shift on the current digit $a_n$ to +obtain what will be the carry for the next iteration. Step 6.2 calculates the $n$'th digit of the result as single precision shift of $a_n$ plus +the previous carry. Recall from section 4.1 that $a_n << 1$ is equivalent to $a_n \cdot 2$. An iteration of the addition loop is finished with +forwarding the carry to the next iteration. + +Step 7 takes care of any final carry by setting the $a.used$'th digit of the result to the carry and augmenting the \textbf{used} count of $b$. +Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input. The only noteworthy difference +is the use of the logical shift operator on line 52 to perform a single precision doubling. + +\subsection{Division by Two} +A division by two can just as easily be accomplished with a logical shift right as multiplication by two can be with a logical shift left. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_div\_2}. \\ +\textbf{Input}. One mp\_int $a$ \\ +\textbf{Output}. $b = a/2$. \\ +\hline \\ +1. If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits. (\textit{mp\_grow}) \\ +2. If the reallocation failed return(\textit{MP\_MEM}). \\ +3. $oldused \leftarrow b.used$ \\ +4. $b.used \leftarrow a.used$ \\ +5. $r \leftarrow 0$ \\ +6. for $n$ from $b.used - 1$ to $0$ do \\ +\hspace{3mm}6.1 $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\ +\hspace{3mm}6.2 $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}6.3 $r \leftarrow rr$ \\ +7. If $b.used < oldused - 1$ then do \\ +\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\ +\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\ +8. $b.sign \leftarrow a.sign$ \\ +9. Clamp excess digits of $b$. (\textit{mp\_clamp}) \\ +10. Return(\textit{MP\_OKAY}).\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_div\_2} +\end{figure} + +\textbf{Algorithm mp\_div\_2.} +This algorithm will divide an mp\_int by two using logical shifts to the right. Like mp\_mul\_2 it uses a modified low level addition +core as the basis of the algorithm. Unlike mp\_mul\_2 the shift operations work from the leading digit to the trailing digit. The algorithm +could be written to work from the trailing digit to the leading digit however, it would have to stop one short of $a.used - 1$ digits to prevent +reading past the end of the array of digits. + +Essentially the loop at step 6 is similar to that of mp\_mul\_2 except the logical shifts go in the opposite direction and the carry is at the +least significant bit not the most significant bit. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\section{Polynomial Basis Operations} +Recall from section 4.3 that any integer can be represented as a polynomial in $x$ as $y = f(\beta)$. Such a representation is also known as +the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single +place. The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer +division and Karatsuba multiplication. + +Converting from an array of digits to polynomial basis is very simple. Consider the integer $y \equiv (a_2, a_1, a_0)_{\beta}$ and recall that +$y = \sum_{i=0}^{2} a_i \beta^i$. Simply replace $\beta$ with $x$ and the expression is in polynomial basis. For example, $f(x) = 8x + 9$ is the +polynomial basis representation for $89$ using radix ten. That is, $f(10) = 8(10) + 9 = 89$. + +\subsection{Multiplication by $x$} + +Given a polynomial in $x$ such as $f(x) = a_n x^n + a_{n-1} x^{n-1} + ... + a_0$ multiplying by $x$ amounts to shifting the coefficients up one +degree. In this case $f(x) \cdot x = a_n x^{n+1} + a_{n-1} x^n + ... + a_0 x$. From a scalar basis point of view multiplying by $x$ is equivalent to +multiplying by the integer $\beta$. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_lshd}. \\ +\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ +\textbf{Output}. $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\ +\hline \\ +1. If $b \le 0$ then return(\textit{MP\_OKAY}). \\ +2. If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits. (\textit{mp\_grow}). \\ +3. If the reallocation failed return(\textit{MP\_MEM}). \\ +4. $a.used \leftarrow a.used + b$ \\ +5. $i \leftarrow a.used - 1$ \\ +6. $j \leftarrow a.used - 1 - b$ \\ +7. for $n$ from $a.used - 1$ to $b$ do \\ +\hspace{3mm}7.1 $a_{i} \leftarrow a_{j}$ \\ +\hspace{3mm}7.2 $i \leftarrow i - 1$ \\ +\hspace{3mm}7.3 $j \leftarrow j - 1$ \\ +8. for $n$ from 0 to $b - 1$ do \\ +\hspace{3mm}8.1 $a_n \leftarrow 0$ \\ +9. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_lshd} +\end{figure} + +\textbf{Algorithm mp\_lshd.} +This algorithm multiplies an mp\_int by the $b$'th power of $x$. This is equivalent to multiplying by $\beta^b$. The algorithm differs +from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location. The +motivation behind this change is due to the way this function is typically used. Algorithms such as mp\_add store the result in an optionally +different third mp\_int because the original inputs are often still required. Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is +typically used on values where the original value is no longer required. The algorithm will return success immediately if +$b \le 0$ since the rest of algorithm is only valid when $b > 0$. + +First the destination $a$ is grown as required to accomodate the result. The counters $i$ and $j$ are used to form a \textit{sliding window} over +the digits of $a$ of length $b$. The head of the sliding window is at $i$ (\textit{the leading digit}) and the tail at $j$ (\textit{the trailing digit}). +The loop on step 7 copies the digit from the tail to the head. In each iteration the window is moved down one digit. The last loop on +step 8 sets the lower $b$ digits to zero. + +\newpage +\begin{center} +\begin{figure}[here] +\includegraphics{pics/sliding_window.ps} +\caption{Sliding Window Movement} +\label{pic:sliding_window} +\end{figure} +\end{center} + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_lshd.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The if statement (line 24) ensures that the $b$ variable is greater than zero since we do not interpret negative +shift counts properly. The \textbf{used} count is incremented by $b$ before the copy loop begins. This elminates +the need for an additional variable in the for loop. The variable $top$ (line 42) is an alias +for the leading digit while $bottom$ (line 45) is an alias for the trailing edge. The aliases form a +window of exactly $b$ digits over the input. + +\subsection{Division by $x$} + +Division by powers of $x$ is easily achieved by shifting the digits right and removing any that will end up to the right of the zero'th digit. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_rshd}. \\ +\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ +\textbf{Output}. $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\ +\hline \\ +1. If $b \le 0$ then return. \\ +2. If $a.used \le b$ then do \\ +\hspace{3mm}2.1 Zero $a$. (\textit{mp\_zero}). \\ +\hspace{3mm}2.2 Return. \\ +3. $i \leftarrow 0$ \\ +4. $j \leftarrow b$ \\ +5. for $n$ from 0 to $a.used - b - 1$ do \\ +\hspace{3mm}5.1 $a_i \leftarrow a_j$ \\ +\hspace{3mm}5.2 $i \leftarrow i + 1$ \\ +\hspace{3mm}5.3 $j \leftarrow j + 1$ \\ +6. for $n$ from $a.used - b$ to $a.used - 1$ do \\ +\hspace{3mm}6.1 $a_n \leftarrow 0$ \\ +7. $a.used \leftarrow a.used - b$ \\ +8. Return. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_rshd} +\end{figure} + +\textbf{Algorithm mp\_rshd.} +This algorithm divides the input in place by the $b$'th power of $x$. It is analogous to dividing by a $\beta^b$ but much quicker since +it does not require single precision division. This algorithm does not actually return an error code as it cannot fail. + +If the input $b$ is less than one the algorithm quickly returns without performing any work. If the \textbf{used} count is less than or equal +to the shift count $b$ then it will simply zero the input and return. + +After the trivial cases of inputs have been handled the sliding window is setup. Much like the case of algorithm mp\_lshd a sliding window that +is $b$ digits wide is used to copy the digits. Unlike mp\_lshd the window slides in the opposite direction from the trailing to the leading digit. +Also the digits are copied from the leading to the trailing edge. + +Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_rshd.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The only noteworthy element of this routine is the lack of a return type since it cannot fail. Like mp\_lshd() we +form a sliding window except we copy in the other direction. After the window (line 60) we then zero +the upper digits of the input to make sure the result is correct. + +\section{Powers of Two} + +Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required. For +example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful. Instead of performing single +shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed. + +\subsection{Multiplication by Power of Two} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_mul\_2d}. \\ +\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ +\textbf{Output}. $c \leftarrow a \cdot 2^b$. \\ +\hline \\ +1. $c \leftarrow a$. (\textit{mp\_copy}) \\ +2. If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\ +3. If the reallocation failed return(\textit{MP\_MEM}). \\ +4. If $b \ge lg(\beta)$ then \\ +\hspace{3mm}4.1 $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\ +\hspace{3mm}4.2 If step 4.1 failed return(\textit{MP\_MEM}). \\ +5. $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ +6. If $d \ne 0$ then do \\ +\hspace{3mm}6.1 $mask \leftarrow 2^d$ \\ +\hspace{3mm}6.2 $r \leftarrow 0$ \\ +\hspace{3mm}6.3 for $n$ from $0$ to $c.used - 1$ do \\ +\hspace{6mm}6.3.1 $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\ +\hspace{6mm}6.3.2 $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{6mm}6.3.3 $r \leftarrow rr$ \\ +\hspace{3mm}6.4 If $r > 0$ then do \\ +\hspace{6mm}6.4.1 $c_{c.used} \leftarrow r$ \\ +\hspace{6mm}6.4.2 $c.used \leftarrow c.used + 1$ \\ +7. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_mul\_2d} +\end{figure} + +\textbf{Algorithm mp\_mul\_2d.} +This algorithm multiplies $a$ by $2^b$ and stores the result in $c$. The algorithm uses algorithm mp\_lshd and a derivative of algorithm mp\_mul\_2 to +quickly compute the product. + +First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than +$\beta$. For example, if $b = 37$ and $\beta = 2^{28}$ then this step will multiply by $x$ leaving a multiplication by $2^{37 - 28} = 2^{9}$ +left. + +After the digits have been shifted appropriately at most $lg(\beta) - 1$ shifts are left to perform. Step 5 calculates the number of remaining shifts +required. If it is non-zero a modified shift loop is used to calculate the remaining product. +Essentially the loop is a generic version of algorithm mp\_mul\_2 designed to handle any shift count in the range $1 \le x < lg(\beta)$. The $mask$ +variable is used to extract the upper $d$ bits to form the carry for the next iteration. + +This algorithm is loosely measured as a $O(2n)$ algorithm which means that if the input is $n$-digits that it takes $2n$ ``time'' to +complete. It is possible to optimize this algorithm down to a $O(n)$ algorithm at a cost of making the algorithm slightly harder to follow. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2d.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The shifting is performed in--place which means the first step (line 25) is to copy the input to the +destination. We avoid calling mp\_copy() by making sure the mp\_ints are different. The destination then +has to be grown (line 32) to accomodate the result. + +If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples +of $lg(\beta)$. Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left. Inside the actual shift +loop (lines 46 to 76) we make use of pre--computed values $shift$ and $mask$. These are used to +extract the carry bit(s) to pass into the next iteration of the loop. The $r$ and $rr$ variables form a +chain between consecutive iterations to propagate the carry. + +\subsection{Division by Power of Two} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_div\_2d}. \\ +\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ +\textbf{Output}. $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\ +\hline \\ +1. If $b \le 0$ then do \\ +\hspace{3mm}1.1 $c \leftarrow a$ (\textit{mp\_copy}) \\ +\hspace{3mm}1.2 $d \leftarrow 0$ (\textit{mp\_zero}) \\ +\hspace{3mm}1.3 Return(\textit{MP\_OKAY}). \\ +2. $c \leftarrow a$ \\ +3. $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\ +4. If $b \ge lg(\beta)$ then do \\ +\hspace{3mm}4.1 $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\ +5. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ +6. If $k \ne 0$ then do \\ +\hspace{3mm}6.1 $mask \leftarrow 2^k$ \\ +\hspace{3mm}6.2 $r \leftarrow 0$ \\ +\hspace{3mm}6.3 for $n$ from $c.used - 1$ to $0$ do \\ +\hspace{6mm}6.3.1 $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\ +\hspace{6mm}6.3.2 $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\ +\hspace{6mm}6.3.3 $r \leftarrow rr$ \\ +7. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\ +8. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_div\_2d} +\end{figure} + +\textbf{Algorithm mp\_div\_2d.} +This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder. The algorithm is designed much like algorithm +mp\_mul\_2d by first using whole digit shifts then single precision shifts. This algorithm will also produce the remainder of the division +by using algorithm mp\_mod\_2d. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2d.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies. The remainder $d$ may be optionally +ignored by passing \textbf{NULL} as the pointer to the mp\_int variable. The temporary mp\_int variable $t$ is used to hold the +result of the remainder operation until the end. This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before +the quotient is obtained. + +The remainder of the source code is essentially the same as the source code for mp\_mul\_2d. The only significant difference is +the direction of the shifts. + +\subsection{Remainder of Division by Power of Two} + +The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$. This +algorithm benefits from the fact that in twos complement arithmetic $a \mbox{ (mod }2^b\mbox{)}$ is the same as $a$ AND $2^b - 1$. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_mod\_2d}. \\ +\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ +\textbf{Output}. $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\ +\hline \\ +1. If $b \le 0$ then do \\ +\hspace{3mm}1.1 $c \leftarrow 0$ (\textit{mp\_zero}) \\ +\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ +2. If $b > a.used \cdot lg(\beta)$ then do \\ +\hspace{3mm}2.1 $c \leftarrow a$ (\textit{mp\_copy}) \\ +\hspace{3mm}2.2 Return the result of step 2.1. \\ +3. $c \leftarrow a$ \\ +4. If step 3 failed return(\textit{MP\_MEM}). \\ +5. for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\ +\hspace{3mm}5.1 $c_n \leftarrow 0$ \\ +6. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ +7. $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\ +8. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\ +9. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_mod\_2d} +\end{figure} + +\textbf{Algorithm mp\_mod\_2d.} +This algorithm will quickly calculate the value of $a \mbox{ (mod }2^b\mbox{)}$. First if $b$ is less than or equal to zero the +result is set to zero. If $b$ is greater than the number of bits in $a$ then it simply copies $a$ to $c$ and returns. Otherwise, $a$ +is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_mod\_2d.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases. Next if $2^b$ is larger +than the input we just mp\_copy() the input and return right away. After this point we know we must actually +perform some work to produce the remainder. + +Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce +the number. First we zero any digits above the last digit in $2^b$ (line 42). Next we reduce the +leading digit of both (line 46) and then mp\_clamp(). + +\section*{Exercises} +\begin{tabular}{cl} +$\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\ + & in $O(n)$ time. \\ + &\\ +$\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming \\ + & weight values such as $3$, $5$ and $9$. Extend it to handle all values \\ + & upto $64$ with a hamming weight less than three. \\ + &\\ +$\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\ + & $2^k - 1$ as well. \\ + &\\ +$\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\ + & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\ + & any $n$-bit input. Note that the time of addition is ignored in the \\ + & calculation. \\ + & \\ +$\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\ + & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$. Again ignore \\ + & the cost of addition. \\ + & \\ +$\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\ + & for $n = 64 \ldots 1024$ in steps of $64$. \\ + & \\ +$\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\ + & calculating the result of a signed comparison. \\ + & +\end{tabular} + +\chapter{Multiplication and Squaring} +\section{The Multipliers} +For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of +algorithms of any multiple precision integer package. The set of multiplier algorithms include integer multiplication, squaring and modular reduction +where in each of the algorithms single precision multiplication is the dominant operation performed. This chapter will discuss integer multiplication +and squaring, leaving modular reductions for the subsequent chapter. + +The importance of the multiplier algorithms is for the most part driven by the fact that certain popular public key algorithms are based on modular +exponentiation, that is computing $d \equiv a^b \mbox{ (mod }c\mbox{)}$ for some arbitrary choice of $a$, $b$, $c$ and $d$. During a modular +exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions, +35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision +multiplications. + +For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied +against every digit of the other multiplicand. Traditional long-hand multiplication is based on this process; while the techniques can differ the +overall algorithm used is essentially the same. Only ``recently'' have faster algorithms been studied. First Karatsuba multiplication was discovered in +1962. This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach. +This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions. + +\section{Multiplication} +\subsection{The Baseline Multiplication} +\label{sec:basemult} +\index{baseline multiplication} +Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication +algorithm that school children are taught. The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision +multiplications are required. More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required. To +simplify most discussions, it will be assumed that the inputs have comparable number of digits. + +The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be +used. This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible. One important +facet of this algorithm, is that it has been modified to only produce a certain amount of output digits as resolution. The importance of this +modification will become evident during the discussion of Barrett modular reduction. Recall that for a $n$ and $m$ digit input the product +will be at most $n + m$ digits. Therefore, this algorithm can be reduced to a full multiplier by having it produce $n + m$ digits of the product. + +Recall from sub-section 4.2.2 the definition of $\gamma$ as the number of bits in the type \textbf{mp\_digit}. We shall now extend the variable set to +include $\alpha$ which shall represent the number of bits in the type \textbf{mp\_word}. This implies that $2^{\alpha} > 2 \cdot \beta^2$. The +constant $\delta = 2^{\alpha - 2lg(\beta)}$ will represent the maximal weight of any column in a product (\textit{see sub-section 5.2.2 for more information}). + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_mul\_digs}. \\ +\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\ +\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\ +\hline \\ +1. If min$(a.used, b.used) < \delta$ then do \\ +\hspace{3mm}1.1 Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}). \\ +\hspace{3mm}1.2 Return the result of step 1.1 \\ +\\ +Allocate and initialize a temporary mp\_int. \\ +2. Init $t$ to be of size $digs$ \\ +3. If step 2 failed return(\textit{MP\_MEM}). \\ +4. $t.used \leftarrow digs$ \\ +\\ +Compute the product. \\ +5. for $ix$ from $0$ to $a.used - 1$ do \\ +\hspace{3mm}5.1 $u \leftarrow 0$ \\ +\hspace{3mm}5.2 $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\ +\hspace{3mm}5.3 If $pb < 1$ then goto step 6. \\ +\hspace{3mm}5.4 for $iy$ from $0$ to $pb - 1$ do \\ +\hspace{6mm}5.4.1 $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\ +\hspace{6mm}5.4.2 $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{6mm}5.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +\hspace{3mm}5.5 if $ix + pb < digs$ then do \\ +\hspace{6mm}5.5.1 $t_{ix + pb} \leftarrow u$ \\ +6. Clamp excess digits of $t$. \\ +7. Swap $c$ with $t$ \\ +8. Clear $t$ \\ +9. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm s\_mp\_mul\_digs} +\end{figure} + +\textbf{Algorithm s\_mp\_mul\_digs.} +This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits. While it may seem +a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent +algorithm. The algorithm is loosely based on algorithm 14.12 from \cite[pp. 595]{HAC} and is similar to Algorithm M of Knuth \cite[pp. 268]{TAOCPV2}. +Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the +inputs. + +The first thing this algorithm checks for is whether a Comba multiplier can be used instead. If the minimum digit count of either +input is less than $\delta$, then the Comba method may be used instead. After the Comba method is ruled out, the baseline algorithm begins. A +temporary mp\_int variable $t$ is used to hold the intermediate result of the product. This allows the algorithm to be used to +compute products when either $a = c$ or $b = c$ without overwriting the inputs. + +All of step 5 is the infamous $O(n^2)$ multiplication loop slightly modified to only produce upto $digs$ digits of output. The $pb$ variable +is given the count of digits to read from $b$ inside the nested loop. If $pb \le 1$ then no more output digits can be produced and the algorithm +will exit the loop. The best way to think of the loops are as a series of $pb \times 1$ multiplications. That is, in each pass of the +innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$. + +For example, consider multiplying $576$ by $241$. That is equivalent to computing $10^0(1)(576) + 10^1(4)(576) + 10^2(2)(576)$ which is best +visualized in the following table. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{|c|c|c|c|c|c|l|} +\hline && & 5 & 7 & 6 & \\ +\hline $\times$&& & 2 & 4 & 1 & \\ +\hline &&&&&&\\ + && & 5 & 7 & 6 & $10^0(1)(576)$ \\ + &2 & 3 & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\ + 1 & 3 & 8 & 8 & 1 & 6 & $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\ +\hline +\end{tabular} +\end{center} +\caption{Long-Hand Multiplication Diagram} +\end{figure} + +Each row of the product is added to the result after being shifted to the left (\textit{multiplied by a power of the radix}) by the appropriate +count. That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult. + +Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable. The multiplication on that step +is assumed to be a double wide output single precision multiplication. That is, two single precision variables are multiplied to produce a +double precision result. The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step +5.4.1 is propagated through the nested loop. If the carry was not propagated immediately it would overflow the single precision digit +$t_{ix+iy}$ and the result would be lost. + +At step 5.5 the nested loop is finished and any carry that was left over should be forwarded. The carry does not have to be added to the $ix+pb$'th +digit since that digit is assumed to be zero at this point. However, if $ix + pb \ge digs$ the carry is not set as it would make the result +exceed the precision requested. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_mul\_digs.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +First we determine (line 31) if the Comba method can be used first since it's faster. The conditions for +sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than +\textbf{MP\_WARRAY}. This new constant is used to control the stack usage in the Comba routines. By default it is +set to $\delta$ but can be reduced when memory is at a premium. + +If we cannot use the Comba method we proceed to setup the baseline routine. We allocate the the destination mp\_int +$t$ (line 37) to the exact size of the output to avoid further re--allocations. At this point we now +begin the $O(n^2)$ loop. + +This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of +digits as output. In each iteration of the outer loop the $pb$ variable is set (line 49) to the maximum +number of inner loop iterations. + +Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the +carry from the previous iteration. A particularly important observation is that most modern optimizing +C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that +is required for the product. In x86 terms for example, this means using the MUL instruction. + +Each digit of the product is stored in turn (line 69) and the carry propagated (line 72) to the +next iteration. + +\subsection{Faster Multiplication by the ``Comba'' Method} + +One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be +computed and propagated upwards. This makes the nested loop very sequential and hard to unroll and implement +in parallel. The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G. +Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations. As an +interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written +five years before. + +At the heart of the Comba technique is once again the long-hand algorithm. Except in this case a slight +twist is placed on how the columns of the result are produced. In the standard long-hand algorithm rows of products +are produced then added together to form the final result. In the baseline algorithm the columns are added together +after each iteration to get the result instantaneously. + +In the Comba algorithm the columns of the result are produced entirely independently of each other. That is at +the $O(n^2)$ level a simple multiplication and addition step is performed. The carries of the columns are propagated +after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute +the product vector $\vec x$ as follows. + +\begin{equation} +\vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace +\end{equation} + +Where $\vec x_n$ is the $n'th$ column of the output vector. Consider the following example which computes the vector $\vec x$ for the multiplication +of $576$ and $241$. + +\newpage\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{|c|c|c|c|c|c|} + \hline & & 5 & 7 & 6 & First Input\\ + \hline $\times$ & & 2 & 4 & 1 & Second Input\\ +\hline & & $1 \cdot 5 = 5$ & $1 \cdot 7 = 7$ & $1 \cdot 6 = 6$ & First pass \\ + & $4 \cdot 5 = 20$ & $4 \cdot 7+5=33$ & $4 \cdot 6+7=31$ & 6 & Second pass \\ + $2 \cdot 5 = 10$ & $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31 & 6 & Third pass \\ +\hline 10 & 34 & 45 & 31 & 6 & Final Result \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Comba Multiplication Diagram} +\end{figure} + +At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler. +Now the columns must be fixed by propagating the carry upwards. The resultant vector will have one extra dimension over the input vector which is +congruent to adding a leading zero digit. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Comba Fixup}. \\ +\textbf{Input}. Vector $\vec x$ of dimension $k$ \\ +\textbf{Output}. Vector $\vec x$ such that the carries have been propagated. \\ +\hline \\ +1. for $n$ from $0$ to $k - 1$ do \\ +\hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\ +\hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\ +2. Return($\vec x$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Comba Fixup} +\end{figure} + +With that algorithm and $k = 5$ and $\beta = 10$ the following vector is produced $\vec x= \left < 1, 3, 8, 8, 1, 6 \right >$. In this case +$241 \cdot 576$ is in fact $138816$ and the procedure succeeded. If the algorithm is correct and as will be demonstrated shortly more +efficient than the baseline algorithm why not simply always use this algorithm? + +\subsubsection{Column Weight.} +At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output +independently. A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix +the carries. For example, in the multiplication of two three-digit numbers the third column of output will be the sum of +three single precision multiplications. If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then +an overflow can occur and the carry information will be lost. For any $m$ and $n$ digit inputs the maximum weight of any column is +min$(m, n)$ which is fairly obvious. + +The maximum number of terms in any column of a product is known as the ``column weight'' and strictly governs when the algorithm can be used. Recall +from earlier that a double precision type has $\alpha$ bits of resolution and a single precision digit has $lg(\beta)$ bits of precision. Given these +two quantities we must not violate the following + +\begin{equation} +k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha} +\end{equation} + +Which reduces to + +\begin{equation} +k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha} +\end{equation} + +Let $\rho = lg(\beta)$ represent the number of bits in a single precision digit. By further re-arrangement of the equation the final solution is +found. + +\begin{equation} +k < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}} +\end{equation} + +The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$. In this configuration +the smaller input may not have more than $256$ digits if the Comba method is to be used. This is quite satisfactory for most applications since +$256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, is much larger than most public key cryptographic algorithms require. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\ +\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\ +\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\ +\hline \\ +Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\ +1. If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\ +2. If step 1 failed return(\textit{MP\_MEM}).\\ +\\ +3. $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\ +\\ +4. $\_ \hat W \leftarrow 0$ \\ +5. for $ix$ from 0 to $pa - 1$ do \\ +\hspace{3mm}5.1 $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\ +\hspace{3mm}5.2 $tx \leftarrow ix - ty$ \\ +\hspace{3mm}5.3 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\ +\hspace{3mm}5.4 for $iz$ from 0 to $iy - 1$ do \\ +\hspace{6mm}5.4.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\ +\hspace{3mm}5.5 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\ +\hspace{3mm}5.6 $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\ +\\ +6. $oldused \leftarrow c.used$ \\ +7. $c.used \leftarrow digs$ \\ +8. for $ix$ from $0$ to $pa$ do \\ +\hspace{3mm}8.1 $c_{ix} \leftarrow W_{ix}$ \\ +9. for $ix$ from $pa + 1$ to $oldused - 1$ do \\ +\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\ +\\ +10. Clamp $c$. \\ +11. Return MP\_OKAY. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm fast\_s\_mp\_mul\_digs} +\label{fig:COMBAMULT} +\end{figure} + +\textbf{Algorithm fast\_s\_mp\_mul\_digs.} +This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision. + +The outer loop of this algorithm is more complicated than that of the baseline multiplier. This is because on the inside of the +loop we want to produce one column per pass. This allows the accumulator $\_ \hat W$ to be placed in CPU registers and +reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration. + +The $ty$ variable is set to the minimum count of $ix$ or the number of digits in $b$. That way if $a$ has more digits than +$b$ this will be limited to $b.used - 1$. The $tx$ variable is set to the to the distance past $b.used$ the variable +$ix$ is. This is used for the immediately subsequent statement where we find $iy$. + +The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out. Computing one column at a time +means we have to scan one integer upwards and the other downwards. $a$ starts at $tx$ and $b$ starts at $ty$. In each +pass we are producing the $ix$'th output column and we note that $tx + ty = ix$. As we move $tx$ upwards we have to +move $ty$ downards so the equality remains valid. The $iy$ variable is the number of iterations until +$tx \ge a.used$ or $ty < 0$ occurs. + +After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator +into the next round by dividing $\_ \hat W$ by $\beta$. + +To measure the benefits of the Comba method over the baseline method consider the number of operations that are required. If the +cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require +$O \left ((p + q)n^2 \right )$ time to multiply two $n$-digit numbers. The Comba method requires only $O(pn^2 + qn)$ time, however in practice, +the speed increase is actually much more. With $O(n)$ space the algorithm can be reduced to $O(pn + qn)$ time by implementing the $n$ multiply +and addition operations in the nested loop in parallel. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_mul\_digs.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +As per the pseudo--code we first calculate $pa$ (line 48) as the number of digits to output. Next we begin the outer loop +to produce the individual columns of the product. We use the two aliases $tmpx$ and $tmpy$ (lines 62, 63) to point +inside the two multiplicands quickly. + +The inner loop (lines 71 to 74) of this implementation is where the tradeoff come into play. Originally this comba +implementation was ``row--major'' which means it adds to each of the columns in each pass. After the outer loop it would then fix +the carries. This was very fast except it had an annoying drawback. You had to read a mp\_word and two mp\_digits and write +one mp\_word per iteration. On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth +is very high and it can keep the ALU fed with data. It did, however, matter on older and embedded cpus where cache is often +slower and also often doesn't exist. This new algorithm only performs two reads per iteration under the assumption that the +compiler has aliased $\_ \hat W$ to a CPU register. + +After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines 77, 80) to forward it as +a carry for the next pass. After the outer loop we use the final carry (line 77) as the last digit of the product. + +\subsection{Polynomial Basis Multiplication} +To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication. In the following algorithms +the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and +$g(x) = \sum_{i=0}^{n} b_i x^i$ respectively, is required. In this system both $f(x)$ and $g(x)$ have $n + 1$ terms and are of the $n$'th degree. + +The product $a \cdot b \equiv f(x)g(x)$ is the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$. The coefficients $w_i$ will +directly yield the desired product when $\beta$ is substituted for $x$. The direct solution to solve for the $2n + 1$ coefficients +requires $O(n^2)$ time and would in practice be slower than the Comba technique. + +However, numerical analysis theory indicates that only $2n + 1$ distinct points in $W(x)$ are required to determine the values of the $2n + 1$ unknown +coefficients. This means by finding $\zeta_y = W(y)$ for $2n + 1$ small values of $y$ the coefficients of $W(x)$ can be found with +Gaussian elimination. This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in +effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$. + +The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible. However, since +$W(x) = f(x)g(x)$ the equivalent $\zeta_y = f(y) g(y)$ can be used in its place. The benefit of this technique stems from the +fact that $f(y)$ and $g(y)$ are much smaller than either $a$ or $b$ respectively. As a result finding the $2n + 1$ relations required +by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs. + +When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$. The $\zeta_0$ term +is simply the product $W(0) = w_0 = a_0 \cdot b_0$. The $\zeta_1$ term is the product +$W(1) = \left (\sum_{i = 0}^{n} a_i \right ) \left (\sum_{i = 0}^{n} b_i \right )$. The third point $\zeta_{\infty}$ is less obvious but rather +simple to explain. The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication. +The point at $\infty$ is used symbolically to represent the most significant column, that is $W(\infty) = w_{2n} = a_nb_n$. Note that the +points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly. + +If more points are required they should be of small values and powers of two such as $2^q$ and the related \textit{mirror points} +$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ for small values of $q$. The term ``mirror point'' stems from the fact that +$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$. For +example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror. + +\begin{eqnarray} +\zeta_{2} = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\ +16 \cdot \zeta_{1 \over 2} = 4f({1\over 2}) \cdot 4g({1 \over 2}) = (a_2 + 2a_1 + 4a_0)(b_2 + 2b_1 + 4b_0) +\end{eqnarray} + +Using such points will allow the values of $f(y)$ and $g(y)$ to be independently calculated using only left shifts. For example, when $n = 2$ the +polynomial $f(2^q)$ is equal to $2^q((2^qa_2) + a_1) + a_0$. This technique of polynomial representation is known as Horner's method. + +As a general rule of the algorithm when the inputs are split into $n$ parts each there are $2n - 1$ multiplications. Each multiplication is of +multiplicands that have $n$ times fewer digits than the inputs. The asymptotic running time of this algorithm is +$O \left ( k^{lg_n(2n - 1)} \right )$ for $k$ digit inputs (\textit{assuming they have the same number of digits}). Figure~\ref{fig:exponent} +summarizes the exponents for various values of $n$. + +\begin{figure} +\begin{center} +\begin{tabular}{|c|c|c|} +\hline \textbf{Split into $n$ Parts} & \textbf{Exponent} & \textbf{Notes}\\ +\hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\ +\hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\ +\hline $4$ & $1.403677461$ &\\ +\hline $5$ & $1.365212389$ &\\ +\hline $10$ & $1.278753601$ &\\ +\hline $100$ & $1.149426538$ &\\ +\hline $1000$ & $1.100270931$ &\\ +\hline $10000$ & $1.075252070$ &\\ +\hline +\end{tabular} +\end{center} +\caption{Asymptotic Running Time of Polynomial Basis Multiplication} +\label{fig:exponent} +\end{figure} + +At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$. However, the overhead +of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large +numbers. + +\subsubsection{Cutoff Point} +The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach. However, +the algorithms incur an overhead (\textit{at the $O(n)$ work level}) since they require a system of equations to be solved. This makes the +polynomial basis approach more costly to use with small inputs. + +Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}). There exists a +point $y$ such that when $m < y$ the polynomial basis algorithms are more costly than Comba, when $m = y$ they are roughly the same cost and +when $m > y$ the Comba methods are slower than the polynomial basis algorithms. + +The exact location of $y$ depends on several key architectural elements of the computer platform in question. + +\begin{enumerate} +\item The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc. For example +on the AMD Athlon the ratio is roughly $17 : 1$ while on the Intel P4 it is $29 : 1$. The higher the ratio in favour of multiplication the lower +the cutoff point $y$ will be. + +\item The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is. Generally speaking as the number of splits +grows the complexity grows substantially. Ideally solving the system will only involve addition, subtraction and shifting of integers. This +directly reflects on the ratio previous mentioned. + +\item To a lesser extent memory bandwidth and function call overheads. Provided the values are in the processor cache this is less of an +influence over the cutoff point. + +\end{enumerate} + +A clean cutoff point separation occurs when a point $y$ is found such that all of the cutoff point conditions are met. For example, if the point +is too low then there will be values of $m$ such that $m > y$ and the Comba method is still faster. Finding the cutoff points is fairly simple when +a high resolution timer is available. + +\subsection{Karatsuba Multiplication} +Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for +general purpose multiplication. Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with +light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent. + +\begin{equation} +f(x) \cdot g(x) = acx^2 + ((a + b)(c + d) - (ac + bd))x + bd +\end{equation} + +Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product. Applying +this algorithm recursively, the work factor becomes $O(n^{lg(3)})$ which is substantially better than the work factor $O(n^2)$ of the Comba technique. It turns +out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points +$\zeta_0$, $\zeta_{\infty}$ and $\zeta_{1}$. Consider the resultant system of equations. + +\begin{center} +\begin{tabular}{rcrcrcrc} +$\zeta_{0}$ & $=$ & & & & & $w_0$ \\ +$\zeta_{1}$ & $=$ & $w_2$ & $+$ & $w_1$ & $+$ & $w_0$ \\ +$\zeta_{\infty}$ & $=$ & $w_2$ & & & & \\ +\end{tabular} +\end{center} + +By adding the first and last equation to the equation in the middle the term $w_1$ can be isolated and all three coefficients solved for. The simplicity +of this system of equations has made Karatsuba fairly popular. In fact the cutoff point is often fairly low\footnote{With LibTomMath 0.18 it is 70 and 109 digits for the Intel P4 and AMD Athlon respectively.} +making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_karatsuba\_mul}. \\ +\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ +\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\ +\hline \\ +1. Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\ +2. If step 2 failed then return(\textit{MP\_MEM}). \\ +\\ +Split the input. e.g. $a = x1 \cdot \beta^B + x0$ \\ +3. $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\ +4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\ +5. $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\ +6. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\ +7. $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\ +\\ +Calculate the three products. \\ +8. $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\ +9. $x1y1 \leftarrow x1 \cdot y1$ \\ +10. $t1 \leftarrow x1 + x0$ (\textit{mp\_add}) \\ +11. $x0 \leftarrow y1 + y0$ \\ +12. $t1 \leftarrow t1 \cdot x0$ \\ +\\ +Calculate the middle term. \\ +13. $x0 \leftarrow x0y0 + x1y1$ \\ +14. $t1 \leftarrow t1 - x0$ (\textit{s\_mp\_sub}) \\ +\\ +Calculate the final product. \\ +15. $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\ +16. $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\ +17. $t1 \leftarrow x0y0 + t1$ \\ +18. $c \leftarrow t1 + x1y1$ \\ +19. Clear all of the temporary variables. \\ +20. Return(\textit{MP\_OKAY}).\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_karatsuba\_mul} +\end{figure} + +\textbf{Algorithm mp\_karatsuba\_mul.} +This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm. It is loosely based on the description +from Knuth \cite[pp. 294-295]{TAOCPV2}. + +\index{radix point} +In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen. The radix point chosen must +be used for both of the inputs meaning that it must be smaller than the smallest input. Step 3 chooses the radix point $B$ as half of the +smallest input \textbf{used} count. After the radix point is chosen the inputs are split into lower and upper halves. Step 4 and 5 +compute the lower halves. Step 6 and 7 computer the upper halves. + +After the halves have been computed the three intermediate half-size products must be computed. Step 8 and 9 compute the trivial products +$x0 \cdot y0$ and $x1 \cdot y1$. The mp\_int $x0$ is used as a temporary variable after $x1 + x0$ has been computed. By using $x0$ instead +of an additional temporary variable, the algorithm can avoid an addition memory allocation operation. + +The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_mul.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The new coding element in this routine, not seen in previous routines, is the usage of goto statements. The conventional +wisdom is that goto statements should be avoided. This is generally true, however when every single function call can fail, it makes sense +to handle error recovery with a single piece of code. Lines 62 to 76 handle initializing all of the temporary variables +required. Note how each of the if statements goes to a different label in case of failure. This allows the routine to correctly free only +the temporaries that have been successfully allocated so far. + +The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large. This saves the +additional reallocation that would have been necessary. Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective +number of digits for the next section of code. + +The first algebraic portion of the algorithm is to split the two inputs into their halves. However, instead of using mp\_mod\_2d and mp\_rshd +to extract the halves, the respective code has been placed inline within the body of the function. To initialize the halves, the \textbf{used} and +\textbf{sign} members are copied first. The first for loop on line 96 copies the lower halves. Since they are both the same magnitude it +is simpler to calculate both lower halves in a single loop. The for loop on lines 102 and 107 calculate the upper halves $x1$ and +$y1$ respectively. + +By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs. + +When line 151 is reached, the algorithm has completed succesfully. The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that +the same code that handles errors can be used to clear the temporary variables and return. + +\subsection{Toom-Cook $3$-Way Multiplication} +Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points are +chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce. Here, the points $\zeta_{0}$, +$16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients +of the $W(x)$. + +With the five relations that Toom-Cook specifies, the following system of equations is formed. + +\begin{center} +\begin{tabular}{rcrcrcrcrcr} +$\zeta_0$ & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$ \\ +$16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$ \\ +$\zeta_1$ & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$ \\ +$\zeta_2$ & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$ \\ +$\zeta_{\infty}$ & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$ \\ +\end{tabular} +\end{center} + +A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power +of two, two divisions by three and one multiplication by three. All of these $19$ sub-operations require less than quadratic time, meaning that +the algorithm can be faster than a baseline multiplication. However, the greater complexity of this algorithm places the cutoff point +(\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_toom\_mul}. \\ +\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ +\textbf{Output}. $c \leftarrow a \cdot b $ \\ +\hline \\ +Split $a$ and $b$ into three pieces. E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\ +1. $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\ +2. $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +3. $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +4. $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +5. $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +6. $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +7. $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ +\\ +Find the five equations for $w_0, w_1, ..., w_4$. \\ +8. $w_0 \leftarrow a_0 \cdot b_0$ \\ +9. $w_4 \leftarrow a_2 \cdot b_2$ \\ +10. $tmp_1 \leftarrow 2 \cdot a_0$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_2$ \\ +11. $tmp_2 \leftarrow 2 \cdot b_0$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_2$ \\ +12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\ +13. $tmp_1 \leftarrow 2 \cdot a_2$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_0$ \\ +14. $tmp_2 \leftarrow 2 \cdot b_2$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_0$ \\ +15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\ +16. $tmp_1 \leftarrow a_0 + a_1$, $tmp_1 \leftarrow tmp_1 + a_2$, $tmp_2 \leftarrow b_0 + b_1$, $tmp_2 \leftarrow tmp_2 + b_2$ \\ +17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\ +\\ +Continued on the next page.\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_toom\_mul} +\end{figure} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_toom\_mul} (continued). \\ +\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ +\textbf{Output}. $c \leftarrow a \cdot b $ \\ +\hline \\ +Now solve the system of equations. \\ +18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\ +19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\ +20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\ +21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\ +22. $tmp_1 \leftarrow 8 \cdot w_0$, $w_1 \leftarrow w_1 - tmp_1$, $tmp_1 \leftarrow 8 \cdot w_4$, $w_3 \leftarrow w_3 - tmp_1$ \\ +23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\ +24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\ +25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\ +\\ +Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\ +26. for $n$ from $1$ to $4$ do \\ +\hspace{3mm}26.1 $w_n \leftarrow w_n \cdot \beta^{nk}$ \\ +27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\ +28. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_toom\_mul (continued)} +\end{figure} + +\textbf{Algorithm mp\_toom\_mul.} +This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach. Compared to the Karatsuba multiplication, this +algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead. In this +description, several statements have been compounded to save space. The intention is that the statements are executed from left to right across +any given step. + +The two inputs $a$ and $b$ are first split into three $k$-digit integers $a_0, a_1, a_2$ and $b_0, b_1, b_2$ respectively. From these smaller +integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required. + +The first two relations $w_0$ and $w_4$ are the points $\zeta_{0}$ and $\zeta_{\infty}$ respectively. The relation $w_1, w_2$ and $w_3$ correspond +to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively. These are found using logical shifts to independently find +$f(y)$ and $g(y)$ which significantly speeds up the algorithm. + +After the five relations $w_0, w_1, \ldots, w_4$ have been computed, the system they represent must be solved in order for the unknown coefficients +$w_1, w_2$ and $w_3$ to be isolated. The steps 18 through 25 perform the system reduction required as previously described. Each step of +the reduction represents the comparable matrix operation that would be performed had this been performed by pencil. For example, step 18 indicates +that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$. + +Once the coeffients have been isolated, the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$ is known. By substituting $\beta^{k}$ for $x$, the integer +result $a \cdot b$ is produced. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_toom\_mul.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The first obvious thing to note is that this algorithm is complicated. The complexity is worth it if you are multiplying very +large numbers. For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with +Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$). For most ``crypto'' sized numbers this +algorithm is not practical as Karatsuba has a much lower cutoff point. + +First we split $a$ and $b$ into three roughly equal portions. This has been accomplished (lines 41 to 70) with +combinations of mp\_rshd() and mp\_mod\_2d() function calls. At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly +for $b$. + +Next we compute the five points $w0, w1, w2, w3$ and $w4$. Recall that $w0$ and $w4$ can be computed directly from the portions so +we get those out of the way first (lines 73 and 78). Next we compute $w1, w2$ and $w3$ using Horners method. + +After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively +straight forward. + +\subsection{Signed Multiplication} +Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required. So far all +of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_mul}. \\ +\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ +\textbf{Output}. $c \leftarrow a \cdot b$ \\ +\hline \\ +1. If $a.sign = b.sign$ then \\ +\hspace{3mm}1.1 $sign = MP\_ZPOS$ \\ +2. else \\ +\hspace{3mm}2.1 $sign = MP\_ZNEG$ \\ +3. If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then \\ +\hspace{3mm}3.1 $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\ +4. else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\ +\hspace{3mm}4.1 $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\ +5. else \\ +\hspace{3mm}5.1 $digs \leftarrow a.used + b.used + 1$ \\ +\hspace{3mm}5.2 If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\ +\hspace{6mm}5.2.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs. \\ +\hspace{3mm}5.3 else \\ +\hspace{6mm}5.3.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs. \\ +6. $c.sign \leftarrow sign$ \\ +7. Return the result of the unsigned multiplication performed. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_mul} +\end{figure} + +\textbf{Algorithm mp\_mul.} +This algorithm performs the signed multiplication of two inputs. It will make use of any of the three unsigned multiplication algorithms +available when the input is of appropriate size. The \textbf{sign} of the result is not set until the end of the algorithm since algorithm +s\_mp\_mul\_digs will clear it. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_mul.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The implementation is rather simplistic and is not particularly noteworthy. Line 22 computes the sign of the result using the ``?'' +operator from the C programming language. Line 48 computes $\delta$ using the fact that $1 << k$ is equal to $2^k$. + +\section{Squaring} +\label{sec:basesquare} + +Squaring is a special case of multiplication where both multiplicands are equal. At first it may seem like there is no significant optimization +available but in fact there is. Consider the multiplication of $576$ against $241$. In total there will be nine single precision multiplications +performed which are $1\cdot 6$, $1 \cdot 7$, $1 \cdot 5$, $4 \cdot 6$, $4 \cdot 7$, $4 \cdot 5$, $2 \cdot 6$, $2 \cdot 7$ and $2 \cdot 5$. Now consider +the multiplication of $123$ against $123$. The nine products are $3 \cdot 3$, $3 \cdot 2$, $3 \cdot 1$, $2 \cdot 3$, $2 \cdot 2$, $2 \cdot 1$, +$1 \cdot 3$, $1 \cdot 2$ and $1 \cdot 1$. On closer inspection some of the products are equivalent. For example, $3 \cdot 2 = 2 \cdot 3$ +and $3 \cdot 1 = 1 \cdot 3$. + +For any $n$-digit input, there are ${{\left (n^2 + n \right)}\over 2}$ possible unique single precision multiplications required compared to the $n^2$ +required for multiplication. The following diagram gives an example of the operations required. + +\begin{figure}[here] +\begin{center} +\begin{tabular}{ccccc|c} +&&1&2&3&\\ +$\times$ &&1&2&3&\\ +\hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\ + & $2 \cdot 1$ & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\ + $1 \cdot 1$ & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\ +\end{tabular} +\end{center} +\caption{Squaring Optimization Diagram} +\end{figure} + +Starting from zero and numbering the columns from right to left a very simple pattern becomes obvious. For the purposes of this discussion let $x$ +represent the number being squared. The first observation is that in row $k$ the $2k$'th column of the product has a $\left (x_k \right)^2$ term in it. + +The second observation is that every column $j$ in row $k$ where $j \ne 2k$ is part of a double product. Every non-square term of a column will +appear twice hence the name ``double product''. Every odd column is made up entirely of double products. In fact every column is made up of double +products and at most one square (\textit{see the exercise section}). + +The third and final observation is that for row $k$ the first unique non-square term, that is, one that hasn't already appeared in an earlier row, +occurs at column $2k + 1$. For example, on row $1$ of the previous squaring, column one is part of the double product with column one from row zero. +Column two of row one is a square and column three is the first unique column. + +\subsection{The Baseline Squaring Algorithm} +The baseline squaring algorithm is meant to be a catch-all squaring algorithm. It will handle any of the input sizes that the faster routines +will not handle. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_sqr}. \\ +\textbf{Input}. mp\_int $a$ \\ +\textbf{Output}. $b \leftarrow a^2$ \\ +\hline \\ +1. Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits. (\textit{mp\_init\_size}) \\ +2. If step 1 failed return(\textit{MP\_MEM}) \\ +3. $t.used \leftarrow 2 \cdot a.used + 1$ \\ +4. For $ix$ from 0 to $a.used - 1$ do \\ +\hspace{3mm}Calculate the square. \\ +\hspace{3mm}4.1 $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\ +\hspace{3mm}4.2 $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}Calculate the double products after the square. \\ +\hspace{3mm}4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +\hspace{3mm}4.4 For $iy$ from $ix + 1$ to $a.used - 1$ do \\ +\hspace{6mm}4.4.1 $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\ +\hspace{6mm}4.4.2 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{6mm}4.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +\hspace{3mm}Set the last carry. \\ +\hspace{3mm}4.5 While $u > 0$ do \\ +\hspace{6mm}4.5.1 $iy \leftarrow iy + 1$ \\ +\hspace{6mm}4.5.2 $\hat r \leftarrow t_{ix + iy} + u$ \\ +\hspace{6mm}4.5.3 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{6mm}4.5.4 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +5. Clamp excess digits of $t$. (\textit{mp\_clamp}) \\ +6. Exchange $b$ and $t$. \\ +7. Clear $t$ (\textit{mp\_clear}) \\ +8. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm s\_mp\_sqr} +\end{figure} + +\textbf{Algorithm s\_mp\_sqr.} +This algorithm computes the square of an input using the three observations on squaring. It is based fairly faithfully on algorithm 14.16 of HAC +\cite[pp.596-597]{HAC}. Similar to algorithm s\_mp\_mul\_digs, a temporary mp\_int is allocated to hold the result of the squaring. This allows the +destination mp\_int to be the same as the source mp\_int. + +The outer loop of this algorithm begins on step 4. It is best to think of the outer loop as walking down the rows of the partial results, while +the inner loop computes the columns of the partial result. Step 4.1 and 4.2 compute the square term for each row, and step 4.3 and 4.4 propagate +the carry and compute the double products. + +The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this +very algorithm. The product $a_{ix}a_{iy}$ will lie in the range $0 \le x \le \beta^2 - 2\beta + 1$ which is obviously less than $\beta^2$ meaning that +when it is multiplied by two, it can be properly represented by a mp\_word. + +Similar to algorithm s\_mp\_mul\_digs, after every pass of the inner loop, the destination is correctly set to the sum of all of the partial +results calculated so far. This involves expensive carry propagation which will be eliminated in the next algorithm. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sqr.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Inside the outer loop (line 34) the square term is calculated on line 37. The carry (line 44) has been +extracted from the mp\_word accumulator using a right shift. Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized +(lines 47 and 50) to simplify the inner loop. The doubling is performed using two +additions (line 59) since it is usually faster than shifting, if not at least as fast. + +The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication. As such the inner loops +get progressively shorter as the algorithm proceeds. This is what leads to the savings compared to using a multiplication to +square a number. + +\subsection{Faster Squaring by the ``Comba'' Method} +A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop. Squaring has an additional +drawback that it must double the product inside the inner loop as well. As for multiplication, the Comba technique can be used to eliminate these +performance hazards. + +The first obvious solution is to make an array of mp\_words which will hold all of the columns. This will indeed eliminate all of the carry +propagation operations from the inner loop. However, the inner product must still be doubled $O(n^2)$ times. The solution stems from the simple fact +that $2a + 2b + 2c = 2(a + b + c)$. That is the sum of all of the double products is equal to double the sum of all the products. For example, +$ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$. + +However, we cannot simply double all of the columns, since the squares appear only once per row. The most practical solution is to have two +mp\_word arrays. One array will hold the squares and the other array will hold the double products. With both arrays the doubling and +carry propagation can be moved to a $O(n)$ work level outside the $O(n^2)$ level. In this case, we have an even simpler solution in mind. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\ +\textbf{Input}. mp\_int $a$ \\ +\textbf{Output}. $b \leftarrow a^2$ \\ +\hline \\ +Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\ +1. If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits. (\textit{mp\_grow}). \\ +2. If step 1 failed return(\textit{MP\_MEM}). \\ +\\ +3. $pa \leftarrow 2 \cdot a.used$ \\ +4. $\hat W1 \leftarrow 0$ \\ +5. for $ix$ from $0$ to $pa - 1$ do \\ +\hspace{3mm}5.1 $\_ \hat W \leftarrow 0$ \\ +\hspace{3mm}5.2 $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\ +\hspace{3mm}5.3 $tx \leftarrow ix - ty$ \\ +\hspace{3mm}5.4 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\ +\hspace{3mm}5.5 $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\ +\hspace{3mm}5.6 for $iz$ from $0$ to $iz - 1$ do \\ +\hspace{6mm}5.6.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\ +\hspace{3mm}5.7 $\_ \hat W \leftarrow 2 \cdot \_ \hat W + \hat W1$ \\ +\hspace{3mm}5.8 if $ix$ is even then \\ +\hspace{6mm}5.8.1 $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\ +\hspace{3mm}5.9 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\ +\hspace{3mm}5.10 $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\ +\\ +6. $oldused \leftarrow b.used$ \\ +7. $b.used \leftarrow 2 \cdot a.used$ \\ +8. for $ix$ from $0$ to $pa - 1$ do \\ +\hspace{3mm}8.1 $b_{ix} \leftarrow W_{ix}$ \\ +9. for $ix$ from $pa$ to $oldused - 1$ do \\ +\hspace{3mm}9.1 $b_{ix} \leftarrow 0$ \\ +10. Clamp excess digits from $b$. (\textit{mp\_clamp}) \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm fast\_s\_mp\_sqr} +\end{figure} + +\textbf{Algorithm fast\_s\_mp\_sqr.} +This algorithm computes the square of an input using the Comba technique. It is designed to be a replacement for algorithm +s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$. +This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of. + +First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively. This is because the inner loop +products are to be doubled. If we had added the previous carry in we would be doubling too much. Next we perform an +addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits. For example, $a_3 \cdot a_5$ is equal +$a_5 \cdot a_3$. Whereas in the multiplication case we would have $5 < a.used$ and $3 \ge 0$ is maintained since we double the sum +of the products just outside the inner loop we have to avoid doing this. This is also a good thing since we perform +fewer multiplications and the routine ends up being faster. + +Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8). We add in the square +only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_sqr.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for +the special case of squaring. + +\subsection{Polynomial Basis Squaring} +The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring. The minor exception +is that $\zeta_y = f(y)g(y)$ is actually equivalent to $\zeta_y = f(y)^2$ since $f(y) = g(y)$. Instead of performing $2n + 1$ +multiplications to find the $\zeta$ relations, squaring operations are performed instead. + +\subsection{Karatsuba Squaring} +Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square. +Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial. The Karatsuba equation can be modified to square a +number with the following equation. + +\begin{equation} +h(x) = a^2x^2 + \left ((a + b)^2 - (a^2 + b^2) \right )x + b^2 +\end{equation} + +Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a + b)^2$. As in +Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of +$O \left ( n^{lg(3)} \right )$. + +If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm +instead? The answer to this arises from the cutoff point for squaring. As in multiplication there exists a cutoff point, at which the +time required for a Comba based squaring and a Karatsuba based squaring meet. Due to the overhead inherent in the Karatsuba method, the cutoff +point is fairly high. For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits. + +Consider squaring a 200 digit number with this technique. It will be split into two 100 digit halves which are subsequently squared. +The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm. If Karatsuba multiplication +were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\ +\textbf{Input}. mp\_int $a$ \\ +\textbf{Output}. $b \leftarrow a^2$ \\ +\hline \\ +1. Initialize the following temporary mp\_ints: $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\ +2. If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\ +\\ +Split the input. e.g. $a = x1\beta^B + x0$ \\ +3. $B \leftarrow \lfloor a.used / 2 \rfloor$ \\ +4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\ +5. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\ +\\ +Calculate the three squares. \\ +6. $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\ +7. $x1x1 \leftarrow x1^2$ \\ +8. $t1 \leftarrow x1 + x0$ (\textit{s\_mp\_add}) \\ +9. $t1 \leftarrow t1^2$ \\ +\\ +Compute the middle term. \\ +10. $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\ +11. $t1 \leftarrow t1 - t2$ \\ +\\ +Compute final product. \\ +12. $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\ +13. $x1x1 \leftarrow x1x1\beta^{2B}$ \\ +14. $t1 \leftarrow t1 + x0x0$ \\ +15. $b \leftarrow t1 + x1x1$ \\ +16. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_karatsuba\_sqr} +\end{figure} + +\textbf{Algorithm mp\_karatsuba\_sqr.} +This algorithm computes the square of an input $a$ using the Karatsuba technique. This algorithm is very similar to the Karatsuba based +multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings. + +The radix point for squaring is simply placed exactly in the middle of the digits when the input has an odd number of digits, otherwise it is +placed just below the middle. Step 3, 4 and 5 compute the two halves required using $B$ +as the radix point. The first two squares in steps 6 and 7 are rather straightforward while the last square is of a more compact form. + +By expanding $\left (x1 + x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $(x0 - x1)^2 - (x1^2 + x0^2) = 2 \cdot x0 \cdot x1$. +Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then +this method is faster. Assuming no further recursions occur, the difference can be estimated with the following inequality. + +Let $p$ represent the cost of a single precision addition and $q$ the cost of a single precision multiplication both in terms of time\footnote{Or +machine clock cycles.}. + +\begin{equation} +5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2 +\end{equation} + +For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$. This implies that the following inequality should hold. +\begin{center} +\begin{tabular}{rcl} +${5n \over 3} + 3n^2 + 3n$ & $<$ & ${n \over 3} + 6n^2$ \\ +${5 \over 3} + 3n + 3$ & $<$ & ${1 \over 3} + 6n$ \\ +${13 \over 9}$ & $<$ & $n$ \\ +\end{tabular} +\end{center} + +This results in a cutoff point around $n = 2$. As a consequence it is actually faster to compute the middle term the ``long way'' on processors +where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication. On +the Intel P4 processor this ratio is 1:29 making this method even more beneficial. The only common exception is the ARMv4 processor which has a +ratio of 1:7. } than simpler operations such as addition. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_sqr.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul. It uses the same inline style to copy and +shift the input into the two halves. The loop from line 54 to line 70 has been modified since only one input exists. The \textbf{used} +count of both $x0$ and $x1$ is fixed up and $x0$ is clamped before the calculations begin. At this point $x1$ and $x0$ are valid equivalents +to the respective halves as if mp\_rshd and mp\_mod\_2d had been used. + +By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered. On the Athlon the cutoff point +is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}). On slower processors such as the Intel P4 +it is actually below the Comba limit (\textit{at 110 digits}). + +This routine uses the same error trap coding style as mp\_karatsuba\_sqr. As the temporary variables are initialized errors are +redirected to the error trap higher up. If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and +mp\_clears are executed normally. + +\subsection{Toom-Cook Squaring} +The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used +instead of multiplication to find the five relations. The reader is encouraged to read the description of the latter algorithm and try to +derive their own Toom-Cook squaring algorithm. + +\subsection{High Level Squaring} +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_sqr}. \\ +\textbf{Input}. mp\_int $a$ \\ +\textbf{Output}. $b \leftarrow a^2$ \\ +\hline \\ +1. If $a.used \ge TOOM\_SQR\_CUTOFF$ then \\ +\hspace{3mm}1.1 $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\ +2. else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\ +\hspace{3mm}2.1 $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\ +3. else \\ +\hspace{3mm}3.1 $digs \leftarrow a.used + b.used + 1$ \\ +\hspace{3mm}3.2 If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\ +\hspace{6mm}3.2.1 $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr. \\ +\hspace{3mm}3.3 else \\ +\hspace{6mm}3.3.1 $b \leftarrow a^2$ using algorithm s\_mp\_sqr. \\ +4. $b.sign \leftarrow MP\_ZPOS$ \\ +5. Return the result of the unsigned squaring performed. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_sqr} +\end{figure} + +\textbf{Algorithm mp\_sqr.} +This algorithm computes the square of the input using one of four different algorithms. If the input is very large and has at least +\textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used. If +neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_sqr.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\section*{Exercises} +\begin{tabular}{cl} +$\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\ + & that have different number of digits in Karatsuba multiplication. \\ + & \\ +$\left [ 2 \right ] $ & In section 5.3 the fact that every column of a squaring is made up \\ + & of double products and at most one square is stated. Prove this statement. \\ + & \\ +$\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\ + & \\ +$\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\ + & \\ +$\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\ + & required for equation $6.7$ to be true. \\ + & \\ +$\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\ + & compute subsets of the columns in each thread. Determine a cutoff point where \\ + & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\ + &\\ +$\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook. You must \\ + & increase the throughput of mp\_exptmod() for random odd moduli in the range \\ + & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\ + & \\ +\end{tabular} + +\chapter{Modular Reduction} +\section{Basics of Modular Reduction} +\index{modular residue} +Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms, +such as factoring. Modular reduction algorithms are the third class of algorithms of the ``multipliers'' set. A number $a$ is said to be \textit{reduced} +modulo another number $b$ by finding the remainder of the division $a/b$. Full integer division with remainder is a topic to be covered +in~\ref{sec:division}. + +Modular reduction is equivalent to solving for $r$ in the following equation. $a = bq + r$ where $q = \lfloor a/b \rfloor$. The result +$r$ is said to be ``congruent to $a$ modulo $b$'' which is also written as $r \equiv a \mbox{ (mod }b\mbox{)}$. In other vernacular $r$ is known as the +``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and +other forms of residues. + +Modular reductions are normally used to create either finite groups, rings or fields. The most common usage for performance driven modular reductions +is in modular exponentiation algorithms. That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible. This operation is used in the +RSA and Diffie-Hellman public key algorithms, for example. Modular multiplication and squaring also appears as a fundamental operation in +elliptic curve cryptographic algorithms. As will be discussed in the subsequent chapter there exist fast algorithms for computing modular +exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications. These algorithms will produce partial results in the +range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms. They have also been used to create redundancy check +algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems. + +\section{The Barrett Reduction} +The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate +division. Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to + +\begin{equation} +c = a - b \cdot \lfloor a/b \rfloor +\end{equation} + +Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper +targeted the DSP56K processor.} intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal. However, +DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types. +It would take another common optimization to optimize the algorithm. + +\subsection{Fixed Point Arithmetic} +The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers. Fixed +point arithmetic would become very popular as it greatly optimize the ``3d-shooter'' genre of games in the mid 1990s when floating point units were +fairly slow if not unavailable. The idea behind fixed point arithmetic is to take a normal $k$-bit integer data type and break it into $p$-bit +integer and a $q$-bit fraction part (\textit{where $p+q = k$}). + +In this system a $k$-bit integer $n$ would actually represent $n/2^q$. For example, with $q = 4$ the integer $n = 37$ would actually represent the +value $2.3125$. To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by +moving the implied decimal point back to where it should be. For example, with $q = 4$ to multiply the integers $9$ and $5$ they must be converted +to fixed point first by multiplying by $2^q$. Let $a = 9(2^q)$ represent the fixed point representation of $9$ and $b = 5(2^q)$ represent the +fixed point representation of $5$. The product $ab$ is equal to $45(2^{2q})$ which when normalized by dividing by $2^q$ produces $45(2^q)$. + +This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication +of two fixed point numbers. Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal. If $2^q$ is +equivalent to one than $2^q/b$ is equivalent to the fixed point approximation of $1/b$ using real arithmetic. Using this fact dividing an integer +$a$ by another integer $b$ can be achieved with the following expression. + +\begin{equation} +\lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor +\end{equation} + +The precision of the division is proportional to the value of $q$. If the divisor $b$ is used frequently as is the case with +modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift. Both operations +are considerably faster than division on most processors. + +Consider dividing $19$ by $5$. The correct result is $\lfloor 19/5 \rfloor = 3$. With $q = 3$ the reciprocal is $\lfloor 2^q/5 \rfloor = 1$ which +leads to a product of $19$ which when divided by $2^q$ produces $2$. However, with $q = 4$ the reciprocal is $\lfloor 2^q/5 \rfloor = 3$ and +the result of the emulated division is $\lfloor 3 \cdot 19 / 2^q \rfloor = 3$ which is correct. The value of $2^q$ must be close to or ideally +larger than the dividend. In effect if $a$ is the dividend then $q$ should allow $0 \le \lfloor a/2^q \rfloor \le 1$ in order for this approach +to work correctly. Plugging this form of divison into the original equation the following modular residue equation arises. + +\begin{equation} +c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor +\end{equation} + +Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol. Using the $\mu$ +variable also helps re-inforce the idea that it is meant to be computed once and re-used. + +\begin{equation} +c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor +\end{equation} + +Provided that $2^q \ge a$ this algorithm will produce a quotient that is either exactly correct or off by a value of one. In the context of Barrett +reduction the value of $a$ is bound by $0 \le a \le (b - 1)^2$ meaning that $2^q \ge b^2$ is sufficient to ensure the reciprocal will have enough +precision. + +Let $n$ represent the number of digits in $b$. This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and +another $n^2$ single precision multiplications to find the residue. In total $3n^2$ single precision multiplications are required to +reduce the number. + +For example, if $b = 1179677$ and $q = 41$ ($2^q > b^2$), then the reciprocal $\mu$ is equal to $\lfloor 2^q / b \rfloor = 1864089$. Consider reducing +$a = 180388626447$ modulo $b$ using the above reduction equation. The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$. +By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found. + +\subsection{Choosing a Radix Point} +Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications. If that were the best +that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$. +See~\ref{sec:division} for further details.} might as well be used in its place. The key to optimizing the reduction is to reduce the precision of +the initial multiplication that finds the quotient. + +Let $a$ represent the number of which the residue is sought. Let $b$ represent the modulus used to find the residue. Let $m$ represent +the number of digits in $b$. For the purposes of this discussion we will assume that the number of digits in $a$ is $2m$, which is generally true if +two $m$-digit numbers have been multiplied. Dividing $a$ by $b$ is the same as dividing a $2m$ digit integer by a $m$ digit integer. Digits below the +$m - 1$'th digit of $a$ will contribute at most a value of $1$ to the quotient because $\beta^k < b$ for any $0 \le k \le m - 1$. Another way to +express this is by re-writing $a$ as two parts. If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then +${a \over b} \equiv {{a' + a''} \over b}$ which is equivalent to ${a' \over b} + {a'' \over b}$. Since $a'$ is bound to be less than $b$ the quotient +is bound by $0 \le {a' \over b} < 1$. + +Since the digits of $a'$ do not contribute much to the quotient the observation is that they might as well be zero. However, if the digits +``might as well be zero'' they might as well not be there in the first place. Let $q_0 = \lfloor a/\beta^{m-1} \rfloor$ represent the input +with the irrelevant digits trimmed. Now the modular reduction is trimmed to the almost equivalent equation + +\begin{equation} +c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor +\end{equation} + +Note that the original divisor $2^q$ has been replaced with $\beta^{m+1}$ where in this case $q$ is a multiple of $lg(\beta)$. Also note that the +exponent on the divisor when added to the amount $q_0$ was shifted by equals $2m$. If the optimization had not been performed the divisor +would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient +$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ can be off from the true quotient by at most two. The original fixed point quotient can be off +by as much as one (\textit{provided the radix point is chosen suitably}) and now that the lower irrelevent digits have been trimmed the quotient +can be off by an additional value of one for a total of at most two. This implies that +$0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. By first subtracting $b$ times the quotient and then conditionally subtracting +$b$ once or twice the residue is found. + +The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single +precision multiplications, ignoring the subtractions required. In total $2m^2 + m$ single precision multiplications are required to find the residue. +This is considerably faster than the original attempt. + +For example, let $\beta = 10$ represent the radix of the digits. Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$ +represent the value of which the residue is desired. In this case $q = 8$ since $10^7 < 9999^2$ meaning that $\mu = \lfloor \beta^{q}/b \rfloor = 10001$. +With the new observation the multiplicand for the quotient is equal to $q_0 = \lfloor a / \beta^{m - 1} \rfloor = 99929$. The quotient is then +$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor = 9993$. Subtracting $9993b$ from $a$ and the correct residue $a \equiv 9871 \mbox{ (mod }b\mbox{)}$ +is found. + +\subsection{Trimming the Quotient} +So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications. As +it stands now the algorithm is already fairly fast compared to a full integer division algorithm. However, there is still room for +optimization. + +After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower +half of the product. It would be nice to be able to remove those digits from the product to effectively cut down the number of single precision +multiplications. If the number of digits in the modulus $m$ is far less than $\beta$ a full product is not required for the algorithm to work properly. +In fact the lower $m - 2$ digits will not affect the upper half of the product at all and do not need to be computed. + +The value of $\mu$ is a $m$-digit number and $q_0$ is a $m + 1$ digit number. Using a full multiplier $(m + 1)(m) = m^2 + m$ single precision +multiplications would be required. Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number +of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications. + +\subsection{Trimming the Residue} +After the quotient has been calculated it is used to reduce the input. As previously noted the algorithm is not exact and it can be off by a small +multiple of the modulus, that is $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. If $b$ is $m$ digits than the +result of reduction equation is a value of at most $m + 1$ digits (\textit{provided $3 < \beta$}) implying that the upper $m - 1$ digits are +implicitly zero. + +The next optimization arises from this very fact. Instead of computing $b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ using a full +$O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed. Similarly the value of $a$ can +be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well. A multiplication that produces +only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications. + +With both optimizations in place the algorithm is the algorithm Barrett proposed. It requires $m^2 + 2m - 1$ single precision multiplications which +is considerably faster than the straightforward $3m^2$ method. + +\subsection{The Barrett Algorithm} +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_reduce}. \\ +\textbf{Input}. mp\_int $a$, mp\_int $b$ and $\mu = \lfloor \beta^{2m}/b \rfloor, m = \lceil lg_{\beta}(b) \rceil, (0 \le a < b^2, b > 1)$ \\ +\textbf{Output}. $a \mbox{ (mod }b\mbox{)}$ \\ +\hline \\ +Let $m$ represent the number of digits in $b$. \\ +1. Make a copy of $a$ and store it in $q$. (\textit{mp\_init\_copy}) \\ +2. $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\ +\\ +Produce the quotient. \\ +3. $q \leftarrow q \cdot \mu$ (\textit{note: only produce digits at or above $m-1$}) \\ +4. $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\ +\\ +Subtract the multiple of modulus from the input. \\ +5. $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\ +6. $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\ +7. $a \leftarrow a - q$ (\textit{mp\_sub}) \\ +\\ +Add $\beta^{m+1}$ if a carry occured. \\ +8. If $a < 0$ then (\textit{mp\_cmp\_d}) \\ +\hspace{3mm}8.1 $q \leftarrow 1$ (\textit{mp\_set}) \\ +\hspace{3mm}8.2 $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\ +\hspace{3mm}8.3 $a \leftarrow a + q$ \\ +\\ +Now subtract the modulus if the residue is too large (e.g. quotient too small). \\ +9. While $a \ge b$ do (\textit{mp\_cmp}) \\ +\hspace{3mm}9.1 $c \leftarrow a - b$ \\ +10. Clear $q$. \\ +11. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_reduce} +\end{figure} + +\textbf{Algorithm mp\_reduce.} +This algorithm will reduce the input $a$ modulo $b$ in place using the Barrett algorithm. It is loosely based on algorithm 14.42 of HAC +\cite[pp. 602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}. The algorithm has several restrictions and assumptions which must +be adhered to for the algorithm to work. + +First the modulus $b$ is assumed to be positive and greater than one. If the modulus were less than or equal to one than subtracting +a multiple of it would either accomplish nothing or actually enlarge the input. The input $a$ must be in the range $0 \le a < b^2$ in order +for the quotient to have enough precision. If $a$ is the product of two numbers that were already reduced modulo $b$, this will not be a problem. +Technically the algorithm will still work if $a \ge b^2$ but it will take much longer to finish. The value of $\mu$ is passed as an argument to this +algorithm and is assumed to be calculated and stored before the algorithm is used. + +Recall that the multiplication for the quotient on step 3 must only produce digits at or above the $m-1$'th position. An algorithm called +$s\_mp\_mul\_high\_digs$ which has not been presented is used to accomplish this task. The algorithm is based on $s\_mp\_mul\_digs$ except that +instead of stopping at a given level of precision it starts at a given level of precision. This optimal algorithm can only be used if the number +of digits in $b$ is very much smaller than $\beta$. + +While it is known that +$a \ge b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ only the lower $m+1$ digits are being used to compute the residue, so an implied +``borrow'' from the higher digits might leave a negative result. After the multiple of the modulus has been subtracted from $a$ the residue must be +fixed up in case it is negative. The invariant $\beta^{m+1}$ must be added to the residue to make it positive again. + +The while loop at step 9 will subtract $b$ until the residue is less than $b$. If the algorithm is performed correctly this step is +performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up. This essentially halves +the number of single precision multiplications required. However, the optimization is only safe if $\beta$ is much larger than the number of digits +in the modulus. In the source code this is evaluated on lines 36 to 44 where algorithm s\_mp\_mul\_high\_digs is used when it is +safe to do so. + +\subsection{The Barrett Setup Algorithm} +In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance. Ideally this value should be computed once and stored for +future use so that the Barrett algorithm can be used without delay. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_reduce\_setup}. \\ +\textbf{Input}. mp\_int $a$ ($a > 1$) \\ +\textbf{Output}. $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\ +\hline \\ +1. $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot m}$ (\textit{mp\_2expt}) \\ +2. $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\ +3. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_reduce\_setup} +\end{figure} + +\textbf{Algorithm mp\_reduce\_setup.} +This algorithm computes the reciprocal $\mu$ required for Barrett reduction. First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot m}$ which +is equivalent and much faster. The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_setup.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This simple routine calculates the reciprocal $\mu$ required by Barrett reduction. Note the extended usage of algorithm mp\_div where the variable +which would received the remainder is passed as NULL. As will be discussed in~\ref{sec:division} the division routine allows both the quotient and the +remainder to be passed as NULL meaning to ignore the value. + +\section{The Montgomery Reduction} +Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting +form of reduction in common use. It computes a modular residue which is not actually equal to the residue of the input yet instead equal to a +residue times a constant. However, as perplexing as this may sound the algorithm is relatively simple and very efficient. + +Throughout this entire section the variable $n$ will represent the modulus used to form the residue. As will be discussed shortly the value of +$n$ must be odd. The variable $x$ will represent the quantity of which the residue is sought. Similar to the Barrett algorithm the input +is restricted to $0 \le x < n^2$. To begin the description some simple number theory facts must be established. + +\textbf{Fact 1.} Adding $n$ to $x$ does not change the residue since in effect it adds one to the quotient $\lfloor x / n \rfloor$. Another way +to explain this is that $n$ is (\textit{or multiples of $n$ are}) congruent to zero modulo $n$. Adding zero will not change the value of the residue. + +\textbf{Fact 2.} If $x$ is even then performing a division by two in $\Z$ is congruent to $x \cdot 2^{-1} \mbox{ (mod }n\mbox{)}$. Actually +this is an application of the fact that if $x$ is evenly divisible by any $k \in \Z$ then division in $\Z$ will be congruent to +multiplication by $k^{-1}$ modulo $n$. + +From these two simple facts the following simple algorithm can be derived. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Montgomery Reduction}. \\ +\textbf{Input}. Integer $x$, $n$ and $k$ \\ +\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\ +\hline \\ +1. for $t$ from $1$ to $k$ do \\ +\hspace{3mm}1.1 If $x$ is odd then \\ +\hspace{6mm}1.1.1 $x \leftarrow x + n$ \\ +\hspace{3mm}1.2 $x \leftarrow x/2$ \\ +2. Return $x$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Montgomery Reduction} +\end{figure} + +The algorithm reduces the input one bit at a time using the two congruencies stated previously. Inside the loop $n$, which is odd, is +added to $x$ if $x$ is odd. This forces $x$ to be even which allows the division by two in $\Z$ to be congruent to a modular division by two. Since +$x$ is assumed to be initially much larger than $n$ the addition of $n$ will contribute an insignificant magnitude to $x$. Let $r$ represent the +final result of the Montgomery algorithm. If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to +$0 \le r < \lfloor x/2^k \rfloor + n$. As a result at most a single subtraction is required to get the residue desired. + +\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{|c|l|} +\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\ +\hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\ +\hline $2$ & $x/2 = 1453$ \\ +\hline $3$ & $x + n = 1710$, $x/2 = 855$ \\ +\hline $4$ & $x + n = 1112$, $x/2 = 556$ \\ +\hline $5$ & $x/2 = 278$ \\ +\hline $6$ & $x/2 = 139$ \\ +\hline $7$ & $x + n = 396$, $x/2 = 198$ \\ +\hline $8$ & $x/2 = 99$ \\ +\hline $9$ & $x + n = 356$, $x/2 = 178$ \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Example of Montgomery Reduction (I)} +\label{fig:MONT1} +\end{figure} + +Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 9$ (note $\beta^k = 512$ which is larger than $n$). The result of +the algorithm $r = 178$ is congruent to the value of $2^{-9} \cdot 5555 \mbox{ (mod }257\mbox{)}$. When $r$ is multiplied by $2^9$ modulo $257$ the correct residue +$r \equiv 158$ is produced. + +Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$. The current algorithm requires $2k^2$ single precision shifts +and $k^2$ single precision additions. At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful. +Fortunately there exists an alternative representation of the algorithm. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Montgomery Reduction} (modified I). \\ +\textbf{Input}. Integer $x$, $n$ and $k$ ($2^k > n$) \\ +\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\ +\hline \\ +1. for $t$ from $1$ to $k$ do \\ +\hspace{3mm}1.1 If the $t$'th bit of $x$ is one then \\ +\hspace{6mm}1.1.1 $x \leftarrow x + 2^tn$ \\ +2. Return $x/2^k$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Montgomery Reduction (modified I)} +\end{figure} + +This algorithm is equivalent since $2^tn$ is a multiple of $n$ and the lower $k$ bits of $x$ are zero by step 2. The number of single +precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement. + +\begin{figure}[here] +\begin{small} +\begin{center} +\begin{tabular}{|c|l|r|} +\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\ +\hline -- & $5555$ & $1010110110011$ \\ +\hline $1$ & $x + 2^{0}n = 5812$ & $1011010110100$ \\ +\hline $2$ & $5812$ & $1011010110100$ \\ +\hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\ +\hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\ +\hline $5$ & $8896$ & $10001011000000$ \\ +\hline $6$ & $8896$ & $10001011000000$ \\ +\hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\ +\hline $8$ & $25344$ & $110001100000000$ \\ +\hline $9$ & $x + 2^{7}n = 91136$ & $10110010000000000$ \\ +\hline -- & $x/2^k = 178$ & \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Example of Montgomery Reduction (II)} +\label{fig:MONT2} +\end{figure} + +Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 9$. +With this algorithm a single shift right at the end is the only right shift required to reduce the input instead of $k$ right shifts inside the +loop. Note that for the iterations $t = 2, 5, 6$ and $8$ where the result $x$ is not changed. In those iterations the $t$'th bit of $x$ is +zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero. + +\subsection{Digit Based Montgomery Reduction} +Instead of computing the reduction on a bit-by-bit basis it is actually much faster to compute it on digit-by-digit basis. Consider the +previous algorithm re-written to compute the Montgomery reduction in this new fashion. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Montgomery Reduction} (modified II). \\ +\textbf{Input}. Integer $x$, $n$ and $k$ ($\beta^k > n$) \\ +\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ +\hline \\ +1. for $t$ from $0$ to $k - 1$ do \\ +\hspace{3mm}1.1 $x \leftarrow x + \mu n \beta^t$ \\ +2. Return $x/\beta^k$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Montgomery Reduction (modified II)} +\end{figure} + +The value $\mu n \beta^t$ is a multiple of the modulus $n$ meaning that it will not change the residue. If the first digit of +the value $\mu n \beta^t$ equals the negative (modulo $\beta$) of the $t$'th digit of $x$ then the addition will result in a zero digit. This +problem breaks down to solving the following congruency. + +\begin{center} +\begin{tabular}{rcl} +$x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\ +$\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\ +$\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\ +\end{tabular} +\end{center} + +In each iteration of the loop on step 1 a new value of $\mu$ must be calculated. The value of $-1/n_0 \mbox{ (mod }\beta\mbox{)}$ is used +extensively in this algorithm and should be precomputed. Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$. + +For example, let $\beta = 10$ represent the radix. Let $n = 17$ represent the modulus which implies $k = 2$ and $\rho \equiv 7$. Let $x = 33$ +represent the value to reduce. + +\newpage\begin{figure} +\begin{center} +\begin{tabular}{|c|c|c|} +\hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\ +\hline -- & $33$ & --\\ +\hline $0$ & $33 + \mu n = 50$ & $1$ \\ +\hline $1$ & $50 + \mu n \beta = 900$ & $5$ \\ +\hline +\end{tabular} +\end{center} +\caption{Example of Montgomery Reduction} +\end{figure} + +The final result $900$ is then divided by $\beta^k$ to produce the final result $9$. The first observation is that $9 \nequiv x \mbox{ (mod }n\mbox{)}$ +which implies the result is not the modular residue of $x$ modulo $n$. However, recall that the residue is actually multiplied by $\beta^{-k}$ in +the algorithm. To get the true residue the value must be multiplied by $\beta^k$. In this case $\beta^k \equiv 15 \mbox{ (mod }n\mbox{)}$ and +the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$. + +\subsection{Baseline Montgomery Reduction} +The baseline Montgomery reduction algorithm will produce the residue for any size input. It is designed to be a catch-all algororithm for +Montgomery reductions. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_montgomery\_reduce}. \\ +\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\ +\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\ +\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ +\hline \\ +1. $digs \leftarrow 2n.used + 1$ \\ +2. If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\ +\hspace{3mm}2.1 Use algorithm fast\_mp\_montgomery\_reduce instead. \\ +\\ +Setup $x$ for the reduction. \\ +3. If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\ +4. $x.used \leftarrow digs$ \\ +\\ +Eliminate the lower $k$ digits. \\ +5. For $ix$ from $0$ to $k - 1$ do \\ +\hspace{3mm}5.1 $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}5.2 $u \leftarrow 0$ \\ +\hspace{3mm}5.3 For $iy$ from $0$ to $k - 1$ do \\ +\hspace{6mm}5.3.1 $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\ +\hspace{6mm}5.3.2 $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{6mm}5.3.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +\hspace{3mm}5.4 While $u > 0$ do \\ +\hspace{6mm}5.4.1 $iy \leftarrow iy + 1$ \\ +\hspace{6mm}5.4.2 $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\ +\hspace{6mm}5.4.3 $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\ +\hspace{6mm}5.4.4 $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\ +\\ +Divide by $\beta^k$ and fix up as required. \\ +6. $x \leftarrow \lfloor x / \beta^k \rfloor$ \\ +7. If $x \ge n$ then \\ +\hspace{3mm}7.1 $x \leftarrow x - n$ \\ +8. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_montgomery\_reduce} +\end{figure} + +\textbf{Algorithm mp\_montgomery\_reduce.} +This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm. The algorithm is loosely based +on algorithm 14.32 of \cite[pp.601]{HAC} except it merges the multiplication of $\mu n \beta^t$ with the addition in the inner loop. The +restrictions on this algorithm are fairly easy to adapt to. First $0 \le x < n^2$ bounds the input to numbers in the same range as +for the Barrett algorithm. Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$. $\rho$ must be calculated in +advance of this algorithm. Finally the variable $k$ is fixed and a pseudonym for $n.used$. + +Step 2 decides whether a faster Montgomery algorithm can be used. It is based on the Comba technique meaning that there are limits on +the size of the input. This algorithm is discussed in sub-section 6.3.3. + +Step 5 is the main reduction loop of the algorithm. The value of $\mu$ is calculated once per iteration in the outer loop. The inner loop +calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits. Both the addition and +multiplication are performed in the same loop to save time and memory. Step 5.4 will handle any additional carries that escape the inner loop. + +Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications +in the inner loop. In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision +multiplications. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_reduce.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This is the baseline implementation of the Montgomery reduction algorithm. Lines 31 to 36 determine if the Comba based +routine can be used instead. Line 47 computes the value of $\mu$ for that particular iteration of the outer loop. + +The multiplication $\mu n \beta^{ix}$ is performed in one step in the inner loop. The alias $tmpx$ refers to the $ix$'th digit of $x$ and +the alias $tmpn$ refers to the modulus $n$. + +\subsection{Faster ``Comba'' Montgomery Reduction} + +The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial +nature of the inner loop. The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba +technique. The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates +a $k \times 1$ product $k$ times. + +The biggest obstacle is that at the $ix$'th iteration of the outer loop the value of $x_{ix}$ is required to calculate $\mu$. This means the +carries from $0$ to $ix - 1$ must have been propagated upwards to form a valid $ix$'th digit. The solution as it turns out is very simple. +Perform a Comba like multiplier and inside the outer loop just after the inner loop fix up the $ix + 1$'th digit by forwarding the carry. + +With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases +the speed of the algorithm. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\ +\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\ +\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\ +\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ +\hline \\ +Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\ +1. if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\ +Copy the digits of $x$ into the array $\hat W$ \\ +2. For $ix$ from $0$ to $x.used - 1$ do \\ +\hspace{3mm}2.1 $\hat W_{ix} \leftarrow x_{ix}$ \\ +3. For $ix$ from $x.used$ to $2n.used - 1$ do \\ +\hspace{3mm}3.1 $\hat W_{ix} \leftarrow 0$ \\ +Elimiate the lower $k$ digits. \\ +4. for $ix$ from $0$ to $n.used - 1$ do \\ +\hspace{3mm}4.1 $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}4.2 For $iy$ from $0$ to $n.used - 1$ do \\ +\hspace{6mm}4.2.1 $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\ +\hspace{3mm}4.3 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\ +Propagate carries upwards. \\ +5. for $ix$ from $n.used$ to $2n.used + 1$ do \\ +\hspace{3mm}5.1 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\ +Shift right and reduce modulo $\beta$ simultaneously. \\ +6. for $ix$ from $0$ to $n.used + 1$ do \\ +\hspace{3mm}6.1 $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\ +Zero excess digits and fixup $x$. \\ +7. if $x.used > n.used + 1$ then do \\ +\hspace{3mm}7.1 for $ix$ from $n.used + 1$ to $x.used - 1$ do \\ +\hspace{6mm}7.1.1 $x_{ix} \leftarrow 0$ \\ +8. $x.used \leftarrow n.used + 1$ \\ +9. Clamp excessive digits of $x$. \\ +10. If $x \ge n$ then \\ +\hspace{3mm}10.1 $x \leftarrow x - n$ \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm fast\_mp\_montgomery\_reduce} +\end{figure} + +\textbf{Algorithm fast\_mp\_montgomery\_reduce.} +This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique. It is on most computer platforms significantly +faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}). The algorithm has the same restrictions +on the input as the baseline reduction algorithm. An additional two restrictions are imposed on this algorithm. The number of digits $k$ in the +the modulus $n$ must not violate $MP\_WARRAY > 2k +1$ and $n < \delta$. When $\beta = 2^{28}$ this algorithm can be used to reduce modulo +a modulus of at most $3,556$ bits in length. + +As in the other Comba reduction algorithms there is a $\hat W$ array which stores the columns of the product. It is initially filled with the +contents of $x$ with the excess digits zeroed. The reduction loop is very similar the to the baseline loop at heart. The multiplication on step +4.1 can be single precision only since $ab \mbox{ (mod }\beta\mbox{)} \equiv (a \mbox{ mod }\beta)(b \mbox{ mod }\beta)$. Some multipliers such +as those on the ARM processors take a variable length time to complete depending on the number of bytes of result it must produce. By performing +a single precision multiplication instead half the amount of time is spent. + +Also note that digit $\hat W_{ix}$ must have the carry from the $ix - 1$'th digit propagated upwards in order for this to work. That is what step +4.3 will do. In effect over the $n.used$ iterations of the outer loop the $n.used$'th lower columns all have the their carries propagated forwards. Note +how the upper bits of those same words are not reduced modulo $\beta$. This is because those values will be discarded shortly and there is no +point. + +Step 5 will propagate the remainder of the carries upwards. On step 6 the columns are reduced modulo $\beta$ and shifted simultaneously as they are +stored in the destination $x$. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_fast\_mp\_montgomery\_reduce.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The $\hat W$ array is first filled with digits of $x$ on line 48 then the rest of the digits are zeroed on line 55. Both loops share +the same alias variables to make the code easier to read. + +The value of $\mu$ is calculated in an interesting fashion. First the value $\hat W_{ix}$ is reduced modulo $\beta$ and cast to a mp\_digit. This +forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision. Line 110 fixes the carry +for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$. + +The for loop on line 109 propagates the rest of the carries upwards through the columns. The for loop on line 126 reduces the columns +modulo $\beta$ and shifts them $k$ places at the same time. The alias $\_ \hat W$ actually refers to the array $\hat W$ starting at the $n.used$'th +digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$. + +\subsection{Montgomery Setup} +To calculate the variable $\rho$ a relatively simple algorithm will be required. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_montgomery\_setup}. \\ +\textbf{Input}. mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\ +\textbf{Output}. $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\ +\hline \\ +1. $b \leftarrow n_0$ \\ +2. If $b$ is even return(\textit{MP\_VAL}) \\ +3. $x \leftarrow (((b + 2) \mbox{ AND } 4) << 1) + b$ \\ +4. for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\ +\hspace{3mm}4.1 $x \leftarrow x \cdot (2 - bx)$ \\ +5. $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\ +6. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_montgomery\_setup} +\end{figure} + +\textbf{Algorithm mp\_montgomery\_setup.} +This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms. It uses a very interesting trick +to calculate $1/n_0$ when $\beta$ is a power of two. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_setup.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This source code computes the value of $\rho$ required to perform Montgomery reduction. It has been modified to avoid performing excess +multiplications when $\beta$ is not the default 28-bits. + +\section{The Diminished Radix Algorithm} +The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett +or Montgomery methods for certain forms of moduli. The technique is based on the following simple congruence. + +\begin{equation} +(x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)} +\end{equation} + +This observation was used in the MMB \cite{MMB} block cipher to create a diffusion primitive. It used the fact that if $n = 2^{31}$ and $k=1$ that +then a x86 multiplier could produce the 62-bit product and use the ``shrd'' instruction to perform a double-precision right shift. The proof +of the above equation is very simple. First write $x$ in the product form. + +\begin{equation} +x = qn + r +\end{equation} + +Now reduce both sides modulo $(n - k)$. + +\begin{equation} +x \equiv qk + r \mbox{ (mod }(n-k)\mbox{)} +\end{equation} + +The variable $n$ reduces modulo $n - k$ to $k$. By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$ +into the equation the original congruence is reproduced, thus concluding the proof. The following algorithm is based on this observation. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Diminished Radix Reduction}. \\ +\textbf{Input}. Integer $x$, $n$, $k$ \\ +\textbf{Output}. $x \mbox{ mod } (n - k)$ \\ +\hline \\ +1. $q \leftarrow \lfloor x / n \rfloor$ \\ +2. $q \leftarrow k \cdot q$ \\ +3. $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\ +4. $x \leftarrow x + q$ \\ +5. If $x \ge (n - k)$ then \\ +\hspace{3mm}5.1 $x \leftarrow x - (n - k)$ \\ +\hspace{3mm}5.2 Goto step 1. \\ +6. Return $x$ \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Diminished Radix Reduction} +\label{fig:DR} +\end{figure} + +This algorithm will reduce $x$ modulo $n - k$ and return the residue. If $0 \le x < (n - k)^2$ then the algorithm will loop almost always +once or twice and occasionally three times. For simplicity sake the value of $x$ is bounded by the following simple polynomial. + +\begin{equation} +0 \le x < n^2 + k^2 - 2nk +\end{equation} + +The true bound is $0 \le x < (n - k - 1)^2$ but this has quite a few more terms. The value of $q$ after step 1 is bounded by the following. + +\begin{equation} +q < n - 2k - k^2/n +\end{equation} + +Since $k^2$ is going to be considerably smaller than $n$ that term will always be zero. The value of $x$ after step 3 is bounded trivially as +$0 \le x < n$. By step four the sum $x + q$ is bounded by + +\begin{equation} +0 \le q + x < (k + 1)n - 2k^2 - 1 +\end{equation} + +With a second pass $q$ will be loosely bounded by $0 \le q < k^2$ after step 2 while $x$ will still be loosely bounded by $0 \le x < n$ after step 3. After the second pass it is highly unlike that the +sum in step 4 will exceed $n - k$. In practice fewer than three passes of the algorithm are required to reduce virtually every input in the +range $0 \le x < (n - k - 1)^2$. + +\begin{figure} +\begin{small} +\begin{center} +\begin{tabular}{|l|} +\hline +$x = 123456789, n = 256, k = 3$ \\ +\hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\ +$q \leftarrow q*k = 1446759$ \\ +$x \leftarrow x \mbox{ mod } n = 21$ \\ +$x \leftarrow x + q = 1446780$ \\ +$x \leftarrow x - (n - k) = 1446527$ \\ +\hline +$q \leftarrow \lfloor x/n \rfloor = 5650$ \\ +$q \leftarrow q*k = 16950$ \\ +$x \leftarrow x \mbox{ mod } n = 127$ \\ +$x \leftarrow x + q = 17077$ \\ +$x \leftarrow x - (n - k) = 16824$ \\ +\hline +$q \leftarrow \lfloor x/n \rfloor = 65$ \\ +$q \leftarrow q*k = 195$ \\ +$x \leftarrow x \mbox{ mod } n = 184$ \\ +$x \leftarrow x + q = 379$ \\ +$x \leftarrow x - (n - k) = 126$ \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Example Diminished Radix Reduction} +\label{fig:EXDR} +\end{figure} + +Figure~\ref{fig:EXDR} demonstrates the reduction of $x = 123456789$ modulo $n - k = 253$ when $n = 256$ and $k = 3$. Note that even while $x$ +is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast. In this case only +three passes were required to find the residue $x \equiv 126$. + + +\subsection{Choice of Moduli} +On the surface this algorithm looks like a very expensive algorithm. It requires a couple of subtractions followed by multiplication and other +modular reductions. The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen. + +Division in general is a very expensive operation to perform. The one exception is when the division is by a power of the radix of representation used. +Division by ten for example is simple for pencil and paper mathematics since it amounts to shifting the decimal place to the right. Similarly division +by two (\textit{or powers of two}) is very simple for binary computers to perform. It would therefore seem logical to choose $n$ of the form $2^p$ +which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits. + +However, there is one operation related to division of power of twos that is even faster than this. If $n = \beta^p$ then the division may be +performed by moving whole digits to the right $p$ places. In practice division by $\beta^p$ is much faster than division by $2^p$ for any $p$. +Also with the choice of $n = \beta^p$ reducing $x$ modulo $n$ merely requires zeroing the digits above the $p-1$'th digit of $x$. + +Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted +modulus'' will refer to a modulus of the form $2^p - k$. The word ``restricted'' in this case refers to the fact that it is based on the +$2^p$ logic except $p$ must be a multiple of $lg(\beta)$. + +\subsection{Choice of $k$} +Now that division and reduction (\textit{step 1 and 3 of figure~\ref{fig:DR}}) have been optimized to simple digit operations the multiplication by $k$ +in step 2 is the most expensive operation. Fortunately the choice of $k$ is not terribly limited. For all intents and purposes it might +as well be a single digit. The smaller the value of $k$ is the faster the algorithm will be. + +\subsection{Restricted Diminished Radix Reduction} +The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$. This algorithm can reduce +an input $x$ within the range $0 \le x < n^2$ using only a couple passes of the algorithm demonstrated in figure~\ref{fig:DR}. The implementation +of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition +of $x$ and $q$. The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular +exponentiations are performed. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_dr\_reduce}. \\ +\textbf{Input}. mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\ +\hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\ +\textbf{Output}. $x \mbox{ mod } n$ \\ +\hline \\ +1. $m \leftarrow n.used$ \\ +2. If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\ +3. $\mu \leftarrow 0$ \\ +4. for $i$ from $0$ to $m - 1$ do \\ +\hspace{3mm}4.1 $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\ +\hspace{3mm}4.2 $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}4.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +5. $x_{m} \leftarrow \mu$ \\ +6. for $i$ from $m + 1$ to $x.used - 1$ do \\ +\hspace{3mm}6.1 $x_{i} \leftarrow 0$ \\ +7. Clamp excess digits of $x$. \\ +8. If $x \ge n$ then \\ +\hspace{3mm}8.1 $x \leftarrow x - n$ \\ +\hspace{3mm}8.2 Goto step 3. \\ +9. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_dr\_reduce} +\end{figure} + +\textbf{Algorithm mp\_dr\_reduce.} +This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$. It has similar restrictions to that of the Barrett reduction +with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$. + +This algorithm essentially implements the pseudo-code in figure~\ref{fig:DR} except with a slight optimization. The division by $\beta^m$, multiplication by $k$ +and addition of $x \mbox{ mod }\beta^m$ are all performed simultaneously inside the loop on step 4. The division by $\beta^m$ is emulated by accessing +the term at the $m+i$'th position which is subsequently multiplied by $k$ and added to the term at the $i$'th position. After the loop the $m$'th +digit is set to the carry and the upper digits are zeroed. Steps 5 and 6 emulate the reduction modulo $\beta^m$ that should have happend to +$x$ before the addition of the multiple of the upper half. + +At step 8 if $x$ is still larger than $n$ another pass of the algorithm is required. First $n$ is subtracted from $x$ and then the algorithm resumes +at step 3. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_reduce.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The first step is to grow $x$ as required to $2m$ digits since the reduction is performed in place on $x$. The label on line 52 is where +the algorithm will resume if further reduction passes are required. In theory it could be placed at the top of the function however, the size of +the modulus and question of whether $x$ is large enough are invariant after the first pass meaning that it would be a waste of time. + +The aliases $tmpx1$ and $tmpx2$ refer to the digits of $x$ where the latter is offset by $m$ digits. By reading digits from $x$ offset by $m$ digits +a division by $\beta^m$ can be simulated virtually for free. The loop on line 64 performs the bulk of the work (\textit{corresponds to step 4 of algorithm 7.11}) +in this algorithm. + +By line 67 the pointer $tmpx1$ points to the $m$'th digit of $x$ which is where the final carry will be placed. Similarly by line 74 the +same pointer will point to the $m+1$'th digit where the zeroes will be placed. + +Since the algorithm is only valid if both $x$ and $n$ are greater than zero an unsigned comparison suffices to determine if another pass is required. +With the same logic at line 81 the value of $x$ is known to be greater than or equal to $n$ meaning that an unsigned subtraction can be used +as well. Since the destination of the subtraction is the larger of the inputs the call to algorithm s\_mp\_sub cannot fail and the return code +does not need to be checked. + +\subsubsection{Setup} +To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required. This algorithm is not really complicated but provided for +completeness. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_dr\_setup}. \\ +\textbf{Input}. mp\_int $n$ \\ +\textbf{Output}. $k = \beta - n_0$ \\ +\hline \\ +1. $k \leftarrow \beta - n_0$ \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_dr\_setup} +\end{figure} + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_setup.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\subsubsection{Modulus Detection} +Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus. An integer is said to be +of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\ +\textbf{Input}. mp\_int $n$ \\ +\textbf{Output}. $1$ if $n$ is in D.R form, $0$ otherwise \\ +\hline +1. If $n.used < 2$ then return($0$). \\ +2. for $ix$ from $1$ to $n.used - 1$ do \\ +\hspace{3mm}2.1 If $n_{ix} \ne \beta - 1$ return($0$). \\ +3. Return($1$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_dr\_is\_modulus} +\end{figure} + +\textbf{Algorithm mp\_dr\_is\_modulus.} +This algorithm determines if a value is in Diminished Radix form. Step 1 rejects obvious cases where fewer than two digits are +in the mp\_int. Step 2 tests all but the first digit to see if they are equal to $\beta - 1$. If the algorithm manages to get to +step 3 then $n$ must be of Diminished Radix form. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_is\_modulus.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\subsection{Unrestricted Diminished Radix Reduction} +The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$. This algorithm +is a straightforward adaptation of algorithm~\ref{fig:DR}. + +In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead. However, this new +algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_reduce\_2k}. \\ +\textbf{Input}. mp\_int $a$ and $n$. mp\_digit $k$ \\ +\hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\ +\textbf{Output}. $a \mbox{ (mod }n\mbox{)}$ \\ +\hline +1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ +2. While $a \ge n$ do \\ +\hspace{3mm}2.1 $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\ +\hspace{3mm}2.2 $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\ +\hspace{3mm}2.3 $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\ +\hspace{3mm}2.4 $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\ +\hspace{3mm}2.5 If $a \ge n$ then do \\ +\hspace{6mm}2.5.1 $a \leftarrow a - n$ \\ +3. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_reduce\_2k} +\end{figure} + +\textbf{Algorithm mp\_reduce\_2k.} +This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$. Division by $2^p$ is emulated with a right +shift which makes the algorithm fairly inexpensive to use. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The algorithm mp\_count\_bits calculates the number of bits in an mp\_int which is used to find the initial value of $p$. The call to mp\_div\_2d +on line 31 calculates both the quotient $q$ and the remainder $a$ required. By doing both in a single function call the code size +is kept fairly small. The multiplication by $k$ is only performed if $k > 1$. This allows reductions modulo $2^p - 1$ to be performed without +any multiplications. + +The unsigned s\_mp\_add, mp\_cmp\_mag and s\_mp\_sub are used in place of their full sign counterparts since the inputs are only valid if they are +positive. By using the unsigned versions the overhead is kept to a minimum. + +\subsubsection{Unrestricted Setup} +To setup this reduction algorithm the value of $k = 2^p - n$ is required. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\ +\textbf{Input}. mp\_int $n$ \\ +\textbf{Output}. $k = 2^p - n$ \\ +\hline +1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ +2. $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\ +3. $x \leftarrow x - n$ (\textit{mp\_sub}) \\ +4. $k \leftarrow x_0$ \\ +5. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_reduce\_2k\_setup} +\end{figure} + +\textbf{Algorithm mp\_reduce\_2k\_setup.} +This algorithm computes the value of $k$ required for the algorithm mp\_reduce\_2k. By making a temporary variable $x$ equal to $2^p$ a subtraction +is sufficient to solve for $k$. Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k\_setup.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\subsubsection{Unrestricted Detection} +An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true. + +\begin{enumerate} +\item The number has only one digit. +\item The number has more than one digit and every bit from the $\beta$'th to the most significant is one. +\end{enumerate} + +If either condition is true than there is a power of two $2^p$ such that $0 < 2^p - n < \beta$. If the input is only +one digit than it will always be of the correct form. Otherwise all of the bits above the first digit must be one. This arises from the fact +that there will be value of $k$ that when added to the modulus causes a carry in the first digit which propagates all the way to the most +significant bit. The resulting sum will be a power of two. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\ +\textbf{Input}. mp\_int $n$ \\ +\textbf{Output}. $1$ if of proper form, $0$ otherwise \\ +\hline +1. If $n.used = 0$ then return($0$). \\ +2. If $n.used = 1$ then return($1$). \\ +3. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ +4. for $x$ from $lg(\beta)$ to $p$ do \\ +\hspace{3mm}4.1 If the ($x \mbox{ mod }lg(\beta)$)'th bit of the $\lfloor x / lg(\beta) \rfloor$ of $n$ is zero then return($0$). \\ +5. Return($1$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_reduce\_is\_2k} +\end{figure} + +\textbf{Algorithm mp\_reduce\_is\_2k.} +This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_is\_2k.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + + + +\section{Algorithm Comparison} +So far three very different algorithms for modular reduction have been discussed. Each of the algorithms have their own strengths and weaknesses +that makes having such a selection very useful. The following table sumarizes the three algorithms along with comparisons of work factors. Since +all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table. + +\begin{center} +\begin{small} +\begin{tabular}{|c|c|c|c|c|c|} +\hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\ +\hline Barrett & $m^2 + 2m - 1$ & None & $79$ & $1087$ & $4223$ \\ +\hline Montgomery & $m^2 + m$ & $n$ must be odd & $72$ & $1056$ & $4160$ \\ +\hline D.R. & $2m$ & $n = \beta^m - k$ & $16$ & $64$ & $128$ \\ +\hline +\end{tabular} +\end{small} +\end{center} + +In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete. However, in practice since Montgomery +reduction can be written as a single function with the Comba technique it is much faster. Barrett reduction suffers from the overhead of +calling the half precision multipliers, addition and division by $\beta$ algorithms. + +For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice. The one set of algorithms where Diminished Radix reduction truly +shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}. In these algorithms +primes of the form $\beta^m - k$ can be found and shared amongst users. These primes will allow the Diminished Radix algorithm to be used in +modular exponentiation to greatly speed up the operation. + + + +\section*{Exercises} +\begin{tabular}{cl} +$\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\ + & calculates the correct value of $\rho$. \\ + & \\ +$\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly. \\ + & \\ +$\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\ + & (\textit{figure~\ref{fig:DR}}) terminates. Also prove the probability that it will \\ + & terminate within $1 \le k \le 10$ iterations. \\ + & \\ +\end{tabular} + + +\chapter{Exponentiation} +Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$. A variant of exponentiation, computed +in a finite field or ring, is called modular exponentiation. This latter style of operation is typically used in public key +cryptosystems such as RSA and Diffie-Hellman. The ability to quickly compute modular exponentiations is of great benefit to any +such cryptosystem and many methods have been sought to speed it up. + +\section{Exponentiation Basics} +A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired. However, as $b$ grows in size +the number of multiplications becomes prohibitive. Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature +with a $1024$-bit key. Such a calculation could never be completed as it would take simply far too long. + +Fortunately there is a very simple algorithm based on the laws of exponents. Recall that $lg_a(a^b) = b$ and that $lg_a(a^ba^c) = b + c$ which +are two trivial relationships between the base and the exponent. Let $b_i$ represent the $i$'th bit of $b$ starting from the least +significant bit. If $b$ is a $k$-bit integer than the following equation is true. + +\begin{equation} +a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i} +\end{equation} + +By taking the base $a$ logarithm of both sides of the equation the following equation is the result. + +\begin{equation} +b = \sum_{i=0}^{k-1}2^i \cdot b_i +\end{equation} + +The term $a^{2^i}$ can be found from the $i - 1$'th term by squaring the term since $\left ( a^{2^i} \right )^2$ is equal to +$a^{2^{i+1}}$. This observation forms the basis of essentially all fast exponentiation algorithms. It requires $k$ squarings and on average +$k \over 2$ multiplications to compute the result. This is indeed quite an improvement over simply multiplying by $a$ a total of $b-1$ times. + +While this current method is a considerable speed up there are further improvements to be made. For example, the $a^{2^i}$ term does not need to +be computed in an auxilary variable. Consider the following equivalent algorithm. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Left to Right Exponentiation}. \\ +\textbf{Input}. Integer $a$, $b$ and $k$ \\ +\textbf{Output}. $c = a^b$ \\ +\hline \\ +1. $c \leftarrow 1$ \\ +2. for $i$ from $k - 1$ to $0$ do \\ +\hspace{3mm}2.1 $c \leftarrow c^2$ \\ +\hspace{3mm}2.2 $c \leftarrow c \cdot a^{b_i}$ \\ +3. Return $c$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Left to Right Exponentiation} +\label{fig:LTOR} +\end{figure} + +This algorithm starts from the most significant bit and works towards the least significant bit. When the $i$'th bit of $b$ is set $a$ is +multiplied against the current product. In each iteration the product is squared which doubles the exponent of the individual terms of the +product. + +For example, let $b = 101100_2 \equiv 44_{10}$. The following chart demonstrates the actions of the algorithm. + +\newpage\begin{figure} +\begin{center} +\begin{tabular}{|c|c|} +\hline \textbf{Value of $i$} & \textbf{Value of $c$} \\ +\hline - & $1$ \\ +\hline $5$ & $a$ \\ +\hline $4$ & $a^2$ \\ +\hline $3$ & $a^4 \cdot a$ \\ +\hline $2$ & $a^8 \cdot a^2 \cdot a$ \\ +\hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\ +\hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\ +\hline +\end{tabular} +\end{center} +\caption{Example of Left to Right Exponentiation} +\end{figure} + +When the product $a^{32} \cdot a^8 \cdot a^4$ is simplified it is equal $a^{44}$ which is the desired exponentiation. This particular algorithm is +called ``Left to Right'' because it reads the exponent in that order. All of the exponentiation algorithms that will be presented are of this nature. + +\subsection{Single Digit Exponentiation} +The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit. It is intended +to be used when a small power of an input is required (\textit{e.g. $a^5$}). It is faster than simply multiplying $b - 1$ times for all values of +$b$ that are greater than three. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_expt\_d}. \\ +\textbf{Input}. mp\_int $a$ and mp\_digit $b$ \\ +\textbf{Output}. $c = a^b$ \\ +\hline \\ +1. $g \leftarrow a$ (\textit{mp\_init\_copy}) \\ +2. $c \leftarrow 1$ (\textit{mp\_set}) \\ +3. for $x$ from 1 to $lg(\beta)$ do \\ +\hspace{3mm}3.1 $c \leftarrow c^2$ (\textit{mp\_sqr}) \\ +\hspace{3mm}3.2 If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\ +\hspace{6mm}3.2.1 $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\ +\hspace{3mm}3.3 $b \leftarrow b << 1$ \\ +4. Clear $g$. \\ +5. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_expt\_d} +\end{figure} + +\textbf{Algorithm mp\_expt\_d.} +This algorithm computes the value of $a$ raised to the power of a single digit $b$. It uses the left to right exponentiation algorithm to +quickly compute the exponentiation. It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the +exponent is a fixed width. + +A copy of $a$ is made first to allow destination variable $c$ be the same as the source variable $a$. The result is set to the initial value of +$1$ in the subsequent step. + +Inside the loop the exponent is read from the most significant bit first down to the least significant bit. First $c$ is invariably squared +on step 3.1. In the following step if the most significant bit of $b$ is one the copy of $a$ is multiplied against $c$. The value +of $b$ is shifted left one bit to make the next bit down from the most signficant bit the new most significant bit. In effect each +iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_expt\_d.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Line 29 sets the initial value of the result to $1$. Next the loop on line 31 steps through each bit of the exponent starting from +the most significant down towards the least significant. The invariant squaring operation placed on line 33 is performed first. After +the squaring the result $c$ is multiplied by the base $g$ if and only if the most significant bit of the exponent is set. The shift on line +47 moves all of the bits of the exponent upwards towards the most significant location. + +\section{$k$-ary Exponentiation} +When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor +slower than squaring. Recall from the previous algorithm that $b_{i}$ refers to the $i$'th bit of the exponent $b$. Suppose instead it referred to +the $i$'th $k$-bit digit of the exponent of $b$. For $k = 1$ the definitions are synonymous and for $k > 1$ algorithm~\ref{fig:KARY} +computes the same exponentiation. A group of $k$ bits from the exponent is called a \textit{window}. That is it is a small window on only a +portion of the entire exponent. Consider the following modification to the basic left to right exponentiation algorithm. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{$k$-ary Exponentiation}. \\ +\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\ +\textbf{Output}. $c = a^b$ \\ +\hline \\ +1. $c \leftarrow 1$ \\ +2. for $i$ from $t - 1$ to $0$ do \\ +\hspace{3mm}2.1 $c \leftarrow c^{2^k} $ \\ +\hspace{3mm}2.2 Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\ +\hspace{3mm}2.3 $c \leftarrow c \cdot a^g$ \\ +3. Return $c$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{$k$-ary Exponentiation} +\label{fig:KARY} +\end{figure} + +The squaring on step 2.1 can be calculated by squaring the value $c$ successively $k$ times. If the values of $a^g$ for $0 < g < 2^k$ have been +precomputed this algorithm requires only $t$ multiplications and $tk$ squarings. The table can be generated with $2^{k - 1} - 1$ squarings and +$2^{k - 1} + 1$ multiplications. This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$. +However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}. + +Suppose $k = 4$ and $t = 100$. This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation. The +original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value. The total number of squarings +has increased slightly but the number of multiplications has nearly halved. + +\subsection{Optimal Values of $k$} +An optimal value of $k$ will minimize $2^{k} + \lceil n / k \rceil + n - 1$ for a fixed number of bits in the exponent $n$. The simplest +approach is to brute force search amongst the values $k = 2, 3, \ldots, 8$ for the lowest result. Table~\ref{fig:OPTK} lists optimal values of $k$ +for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}. + +\begin{figure}[here] +\begin{center} +\begin{small} +\begin{tabular}{|c|c|c|c|c|c|} +\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\ +\hline $16$ & $2$ & $27$ & $24$ \\ +\hline $32$ & $3$ & $49$ & $48$ \\ +\hline $64$ & $3$ & $92$ & $96$ \\ +\hline $128$ & $4$ & $175$ & $192$ \\ +\hline $256$ & $4$ & $335$ & $384$ \\ +\hline $512$ & $5$ & $645$ & $768$ \\ +\hline $1024$ & $6$ & $1257$ & $1536$ \\ +\hline $2048$ & $6$ & $2452$ & $3072$ \\ +\hline $4096$ & $7$ & $4808$ & $6144$ \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Optimal Values of $k$ for $k$-ary Exponentiation} +\label{fig:OPTK} +\end{figure} + +\subsection{Sliding-Window Exponentiation} +A simple modification to the previous algorithm is only generate the upper half of the table in the range $2^{k-1} \le g < 2^k$. Essentially +this is a table for all values of $g$ where the most significant bit of $g$ is a one. However, in order for this to be allowed in the +algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided. + +Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}. + +\begin{figure}[here] +\begin{center} +\begin{small} +\begin{tabular}{|c|c|c|c|c|c|} +\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\ +\hline $16$ & $3$ & $24$ & $27$ \\ +\hline $32$ & $3$ & $45$ & $49$ \\ +\hline $64$ & $4$ & $87$ & $92$ \\ +\hline $128$ & $4$ & $167$ & $175$ \\ +\hline $256$ & $5$ & $322$ & $335$ \\ +\hline $512$ & $6$ & $628$ & $645$ \\ +\hline $1024$ & $6$ & $1225$ & $1257$ \\ +\hline $2048$ & $7$ & $2403$ & $2452$ \\ +\hline $4096$ & $8$ & $4735$ & $4808$ \\ +\hline +\end{tabular} +\end{small} +\end{center} +\caption{Optimal Values of $k$ for Sliding Window Exponentiation} +\label{fig:OPTK2} +\end{figure} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\ +\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\ +\textbf{Output}. $c = a^b$ \\ +\hline \\ +1. $c \leftarrow 1$ \\ +2. for $i$ from $t - 1$ to $0$ do \\ +\hspace{3mm}2.1 If the $i$'th bit of $b$ is a zero then \\ +\hspace{6mm}2.1.1 $c \leftarrow c^2$ \\ +\hspace{3mm}2.2 else do \\ +\hspace{6mm}2.2.1 $c \leftarrow c^{2^k}$ \\ +\hspace{6mm}2.2.2 Extract the $k$ bits from $(b_{i}b_{i-1}\ldots b_{i-(k-1)})$ and store it in $g$. \\ +\hspace{6mm}2.2.3 $c \leftarrow c \cdot a^g$ \\ +\hspace{6mm}2.2.4 $i \leftarrow i - k$ \\ +3. Return $c$. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Sliding Window $k$-ary Exponentiation} +\end{figure} + +Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent. While this +algorithm requires the same number of squarings it can potentially have fewer multiplications. The pre-computed table $a^g$ is also half +the size as the previous table. + +Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms. The first algorithm will divide the exponent up as +the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$. The second algorithm will break the +exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$. The single digit $0$ in the second representation are where +a single squaring took place instead of a squaring and multiplication. In total the first method requires $10$ multiplications and $18$ +squarings. The second method requires $8$ multiplications and $18$ squarings. + +In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster. + +\section{Modular Exponentiation} + +Modular exponentiation is essentially computing the power of a base within a finite field or ring. For example, computing +$d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation. Instead of first computing $a^b$ and then reducing it +modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation. + +This guarantees that any intermediate result is bounded by $0 \le d \le c^2 - 2c + 1$ and can be reduced modulo $c$ quickly using +one of the algorithms presented in chapter six. + +Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first. This algorithm +will allow the exponent $b$ to be negative which is computed as $c \equiv \left (1 / a \right )^{\vert b \vert} \mbox{(mod }d\mbox{)}$. The +value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}). If no inverse exists the algorithm +terminates with an error. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_exptmod}. \\ +\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ +\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ +\hline \\ +1. If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\ +2. If $b.sign = MP\_NEG$ then \\ +\hspace{3mm}2.1 $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\ +\hspace{3mm}2.2 $x' \leftarrow \vert x \vert$ \\ +\hspace{3mm}2.3 Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\ +3. if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\ +\hspace{3mm}3.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\ +4. else \\ +\hspace{3mm}4.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_exptmod} +\end{figure} + +\textbf{Algorithm mp\_exptmod.} +The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod. It is a sliding window $k$-ary algorithm +which uses Barrett reduction to reduce the product modulo $p$. The second algorithm mp\_exptmod\_fast performs the same operation +except it uses either Montgomery or Diminished Radix reduction. The two latter reduction algorithms are clumped in the same exponentiation +algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}). + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_exptmod.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +In order to keep the algorithms in a known state the first step on line 29 is to reject any negative modulus as input. If the exponent is +negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$. The temporary variable $tmpG$ is assigned +the modular inverse of $G$ and $tmpX$ is assigned the absolute value of $X$. The algorithm will recuse with these new values with a positive +exponent. + +If the exponent is positive the algorithm resumes the exponentiation. Line 77 determines if the modulus is of the restricted Diminished Radix +form. If it is not line 70 attempts to determine if it is of a unrestricted Diminished Radix form. The integer $dr$ will take on one +of three values. + +\begin{enumerate} +\item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form. +\item $dr = 1$ means that the modulus is of restricted Diminished Radix form. +\item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form. +\end{enumerate} + +Line 69 determines if the fast modular exponentiation algorithm can be used. It is allowed if $dr \ne 0$ or if the modulus is odd. Otherwise, +the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction. + +\subsection{Barrett Modular Exponentiation} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_exptmod}. \\ +\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ +\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ +\hline \\ +1. $k \leftarrow lg(x)$ \\ +2. $winsize \leftarrow \left \lbrace \begin{array}{ll} + 2 & \mbox{if }k \le 7 \\ + 3 & \mbox{if }7 < k \le 36 \\ + 4 & \mbox{if }36 < k \le 140 \\ + 5 & \mbox{if }140 < k \le 450 \\ + 6 & \mbox{if }450 < k \le 1303 \\ + 7 & \mbox{if }1303 < k \le 3529 \\ + 8 & \mbox{if }3529 < k \\ + \end{array} \right .$ \\ +3. Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\ +4. Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\ +5. $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\ +\\ +Setup the table of small powers of $g$. First find $g^{2^{winsize}}$ and then all multiples of it. \\ +6. $k \leftarrow 2^{winsize - 1}$ \\ +7. $M_{k} \leftarrow M_1$ \\ +8. for $ix$ from 0 to $winsize - 2$ do \\ +\hspace{3mm}8.1 $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr}) \\ +\hspace{3mm}8.2 $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\ +9. for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\ +\hspace{3mm}9.1 $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\ +\hspace{3mm}9.2 $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\ +10. $res \leftarrow 1$ \\ +\\ +Start Sliding Window. \\ +11. $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\ +12. Loop \\ +\hspace{3mm}12.1 $bitcnt \leftarrow bitcnt - 1$ \\ +\hspace{3mm}12.2 If $bitcnt = 0$ then do \\ +\hspace{6mm}12.2.1 If $digidx = -1$ goto step 13. \\ +\hspace{6mm}12.2.2 $buf \leftarrow x_{digidx}$ \\ +\hspace{6mm}12.2.3 $digidx \leftarrow digidx - 1$ \\ +\hspace{6mm}12.2.4 $bitcnt \leftarrow lg(\beta)$ \\ +Continued on next page. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm s\_mp\_exptmod} +\end{figure} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\ +\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ +\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ +\hline \\ +\hspace{3mm}12.3 $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\ +\hspace{3mm}12.4 $buf \leftarrow buf << 1$ \\ +\hspace{3mm}12.5 if $mode = 0$ and $y = 0$ then goto step 12. \\ +\hspace{3mm}12.6 if $mode = 1$ and $y = 0$ then do \\ +\hspace{6mm}12.6.1 $res \leftarrow res^2$ \\ +\hspace{6mm}12.6.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ +\hspace{6mm}12.6.3 Goto step 12. \\ +\hspace{3mm}12.7 $bitcpy \leftarrow bitcpy + 1$ \\ +\hspace{3mm}12.8 $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\ +\hspace{3mm}12.9 $mode \leftarrow 2$ \\ +\hspace{3mm}12.10 If $bitcpy = winsize$ then do \\ +\hspace{6mm}Window is full so perform the squarings and single multiplication. \\ +\hspace{6mm}12.10.1 for $ix$ from $0$ to $winsize -1$ do \\ +\hspace{9mm}12.10.1.1 $res \leftarrow res^2$ \\ +\hspace{9mm}12.10.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ +\hspace{6mm}12.10.2 $res \leftarrow res \cdot M_{bitbuf}$ \\ +\hspace{6mm}12.10.3 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ +\hspace{6mm}Reset the window. \\ +\hspace{6mm}12.10.4 $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\ +\\ +No more windows left. Check for residual bits of exponent. \\ +13. If $mode = 2$ and $bitcpy > 0$ then do \\ +\hspace{3mm}13.1 for $ix$ form $0$ to $bitcpy - 1$ do \\ +\hspace{6mm}13.1.1 $res \leftarrow res^2$ \\ +\hspace{6mm}13.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ +\hspace{6mm}13.1.3 $bitbuf \leftarrow bitbuf << 1$ \\ +\hspace{6mm}13.1.4 If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\ +\hspace{9mm}13.1.4.1 $res \leftarrow res \cdot M_{1}$ \\ +\hspace{9mm}13.1.4.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ +14. $y \leftarrow res$ \\ +15. Clear $res$, $mu$ and the $M$ array. \\ +16. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm s\_mp\_exptmod (continued)} +\end{figure} + +\textbf{Algorithm s\_mp\_exptmod.} +This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$. It takes advantage of the Barrett reduction +algorithm to keep the product small throughout the algorithm. + +The first two steps determine the optimal window size based on the number of bits in the exponent. The larger the exponent the +larger the window size becomes. After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated. This +table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$. + +After the table is allocated the first power of $g$ is found. Since $g \ge p$ is allowed it must be first reduced modulo $p$ to make +the rest of the algorithm more efficient. The first element of the table at $2^{winsize - 1}$ is found by squaring $M_1$ successively $winsize - 2$ +times. The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$. + +Now that the table is available the sliding window may begin. The following list describes the functions of all the variables in the window. +\begin{enumerate} +\item The variable $mode$ dictates how the bits of the exponent are interpreted. +\begin{enumerate} + \item When $mode = 0$ the bits are ignored since no non-zero bit of the exponent has been seen yet. For example, if the exponent were simply + $1$ then there would be $lg(\beta) - 1$ zero bits before the first non-zero bit. In this case bits are ignored until a non-zero bit is found. + \item When $mode = 1$ a non-zero bit has been seen before and a new $winsize$-bit window has not been formed yet. In this mode leading $0$ bits + are read and a single squaring is performed. If a non-zero bit is read a new window is created. + \item When $mode = 2$ the algorithm is in the middle of forming a window and new bits are appended to the window from the most significant bit + downwards. +\end{enumerate} +\item The variable $bitcnt$ indicates how many bits are left in the current digit of the exponent left to be read. When it reaches zero a new digit + is fetched from the exponent. +\item The variable $buf$ holds the currently read digit of the exponent. +\item The variable $digidx$ is an index into the exponents digits. It starts at the leading digit $x.used - 1$ and moves towards the trailing digit. +\item The variable $bitcpy$ indicates how many bits are in the currently formed window. When it reaches $winsize$ the window is flushed and + the appropriate operations performed. +\item The variable $bitbuf$ holds the current bits of the window being formed. +\end{enumerate} + +All of step 12 is the window processing loop. It will iterate while there are digits available form the exponent to read. The first step +inside this loop is to extract a new digit if no more bits are available in the current digit. If there are no bits left a new digit is +read and if there are no digits left than the loop terminates. + +After a digit is made available step 12.3 will extract the most significant bit of the current digit and move all other bits in the digit +upwards. In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to +trailing edges the entire exponent is read from most significant bit to least significant bit. + +At step 12.5 if the $mode$ and currently extracted bit $y$ are both zero the bit is ignored and the next bit is read. This prevents the +algorithm from having to perform trivial squaring and reduction operations before the first non-zero bit is read. Step 12.6 and 12.7-10 handle +the two cases of $mode = 1$ and $mode = 2$ respectively. + +\begin{center} +\begin{figure}[here] +\includegraphics{pics/expt_state.ps} +\caption{Sliding Window State Diagram} +\label{pic:expt_state} +\end{figure} +\end{center} + +By step 13 there are no more digits left in the exponent. However, there may be partial bits in the window left. If $mode = 2$ then +a Left-to-Right algorithm is used to process the remaining few bits. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_exptmod.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Lines 32 through 46 determine the optimal window size based on the length of the exponent in bits. The window divisions are sorted +from smallest to greatest so that in each \textbf{if} statement only one condition must be tested. For example, by the \textbf{if} statement +on line 38 the value of $x$ is already known to be greater than $140$. + +The conditional piece of code beginning on line 48 allows the window size to be restricted to five bits. This logic is used to ensure +the table of precomputed powers of $G$ remains relatively small. + +The for loop on line 61 initializes the $M$ array while lines 72 and 77 through 86 initialize the reduction +function that will be used for this modulus. + +-- More later. + +\section{Quick Power of Two} +Calculating $b = 2^a$ can be performed much quicker than with any of the previous algorithms. Recall that a logical shift left $m << k$ is +equivalent to $m \cdot 2^k$. By this logic when $m = 1$ a quick power of two can be achieved. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_2expt}. \\ +\textbf{Input}. integer $b$ \\ +\textbf{Output}. $a \leftarrow 2^b$ \\ +\hline \\ +1. $a \leftarrow 0$ \\ +2. If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\ +3. $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\ +4. $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\ +5. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_2expt} +\end{figure} + +\textbf{Algorithm mp\_2expt.} + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_2expt.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\chapter{Higher Level Algorithms} + +This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package. These +routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important. + +The first section describes a method of integer division with remainder that is universally well known. It provides the signed division logic +for the package. The subsequent section discusses a set of algorithms which allow a single digit to be the 2nd operand for a variety of operations. +These algorithms serve mostly to simplify other algorithms where small constants are required. The last two sections discuss how to manipulate +various representations of integers. For example, converting from an mp\_int to a string of character. + +\section{Integer Division with Remainder} +\label{sec:division} + +Integer division aside from modular exponentiation is the most intensive algorithm to compute. Like addition, subtraction and multiplication +the basis of this algorithm is the long-hand division algorithm taught to school children. Throughout this discussion several common variables +will be used. Let $x$ represent the divisor and $y$ represent the dividend. Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and +let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$. The following simple algorithm will be used to start the discussion. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\ +\textbf{Input}. integer $x$ and $y$ \\ +\textbf{Output}. $q = \lfloor y/x\rfloor, r = y - xq$ \\ +\hline \\ +1. $q \leftarrow 0$ \\ +2. $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\ +3. for $t$ from $n$ down to $0$ do \\ +\hspace{3mm}3.1 Maximize $k$ such that $kx\beta^t$ is less than or equal to $y$ and $(k + 1)x\beta^t$ is greater. \\ +\hspace{3mm}3.2 $q \leftarrow q + k\beta^t$ \\ +\hspace{3mm}3.3 $y \leftarrow y - kx\beta^t$ \\ +4. $r \leftarrow y$ \\ +5. Return($q, r$) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Radix-$\beta$ Integer Division} +\label{fig:raddiv} +\end{figure} + +As children we are taught this very simple algorithm for the case of $\beta = 10$. Almost instinctively several optimizations are taught for which +their reason of existing are never explained. For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor. + +To find the first digit of the quotient the value of $k$ must be maximized such that $kx\beta^t$ is less than or equal to $y$ and +simultaneously $(k + 1)x\beta^t$ is greater than $y$. Implicitly $k$ is the maximum value the $t$'th digit of the quotient may have. The habitual method +used to find the maximum is to ``eyeball'' the two numbers, typically only the leading digits and quickly estimate a quotient. By only using leading +digits a much simpler division may be used to form an educated guess at what the value must be. In this case $k = \lfloor 54/23\rfloor = 2$ quickly +arises as a possible solution. Indeed $2x\beta^2 = 4600$ is less than $y = 5471$ and simultaneously $(k + 1)x\beta^2 = 6900$ is larger than $y$. +As a result $k\beta^2$ is added to the quotient which now equals $q = 200$ and $4600$ is subtracted from $y$ to give a remainder of $y = 841$. + +Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder +$y = 841 - 3x\beta = 181$. Finally the last iteration of the loop produces $k = 7$ which leads to the quotient $q = 230 + 7 = 237$ and the +remainder $y = 181 - 7x = 20$. The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since +$237 \cdot 23 + 20 = 5471$ is true. + +\subsection{Quotient Estimation} +\label{sec:divest} +As alluded to earlier the quotient digit $k$ can be estimated from only the leading digits of both the divisor and dividend. When $p$ leading +digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows. Technically +speaking the estimation is based on assuming the lower $\vert \vert y \vert \vert - p$ and $\vert \vert x \vert \vert - p$ lower digits of the +dividend and divisor are zero. + +The value of the estimation may off by a few values in either direction and in general is fairly correct. A simplification \cite[pp. 271]{TAOCPV2} +of the estimation technique is to use $t + 1$ digits of the dividend and $t$ digits of the divisor, in particularly when $t = 1$. The estimate +using this technique is never too small. For the following proof let $t = \vert \vert y \vert \vert - 1$ and $s = \vert \vert x \vert \vert - 1$ +represent the most significant digits of the dividend and divisor respectively. + +\textbf{Proof.}\textit{ The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to +$k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. } +The first obvious case is when $\hat k = \beta - 1$ in which case the proof is concluded since the real quotient cannot be larger. For all other +cases $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ and $\hat k x_s \ge y_t\beta + y_{t-1} - x_s + 1$. The latter portion of the inequalility +$-x_s + 1$ arises from the fact that a truncated integer division will give the same quotient for at most $x_s - 1$ values. Next a series of +inequalities will prove the hypothesis. + +\begin{equation} +y - \hat k x \le y - \hat k x_s\beta^s +\end{equation} + +This is trivially true since $x \ge x_s\beta^s$. Next we replace $\hat kx_s\beta^s$ by the previous inequality for $\hat kx_s$. + +\begin{equation} +y - \hat k x \le y_t\beta^t + \ldots + y_0 - (y_t\beta^t + y_{t-1}\beta^{t-1} - x_s\beta^t + \beta^s) +\end{equation} + +By simplifying the previous inequality the following inequality is formed. + +\begin{equation} +y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s +\end{equation} + +Subsequently, + +\begin{equation} +y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s < x_s\beta^s \le x +\end{equation} + +Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof. \textbf{QED} + + +\subsection{Normalized Integers} +For the purposes of division a normalized input is when the divisors leading digit $x_n$ is greater than or equal to $\beta / 2$. By multiplying both +$x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original +remainder. The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will +lie in the domain of a single digit. Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$. + +\begin{equation} +{{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta} +\end{equation} + +At most the quotient approaches $2\beta$, however, in practice this will not occur since that would imply the previous quotient digit was too small. + +\subsection{Radix-$\beta$ Division with Remainder} +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_div}. \\ +\textbf{Input}. mp\_int $a, b$ \\ +\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\ +\hline \\ +1. If $b = 0$ return(\textit{MP\_VAL}). \\ +2. If $\vert a \vert < \vert b \vert$ then do \\ +\hspace{3mm}2.1 $d \leftarrow a$ \\ +\hspace{3mm}2.2 $c \leftarrow 0$ \\ +\hspace{3mm}2.3 Return(\textit{MP\_OKAY}). \\ +\\ +Setup the quotient to receive the digits. \\ +3. Grow $q$ to $a.used + 2$ digits. \\ +4. $q \leftarrow 0$ \\ +5. $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\ +6. $sign \leftarrow \left \lbrace \begin{array}{ll} + MP\_ZPOS & \mbox{if }a.sign = b.sign \\ + MP\_NEG & \mbox{otherwise} \\ + \end{array} \right .$ \\ +\\ +Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\ +7. $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\ +8. $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\ +\\ +Find the leading digit of the quotient. \\ +9. $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\ +10. $y \leftarrow y \cdot \beta^{n - t}$ \\ +11. While ($x \ge y$) do \\ +\hspace{3mm}11.1 $q_{n - t} \leftarrow q_{n - t} + 1$ \\ +\hspace{3mm}11.2 $x \leftarrow x - y$ \\ +12. $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\ +\\ +Continued on the next page. \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_div} +\end{figure} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_div} (continued). \\ +\textbf{Input}. mp\_int $a, b$ \\ +\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\ +\hline \\ +Now find the remainder fo the digits. \\ +13. for $i$ from $n$ down to $(t + 1)$ do \\ +\hspace{3mm}13.1 If $i > x.used$ then jump to the next iteration of this loop. \\ +\hspace{3mm}13.2 If $x_{i} = y_{t}$ then \\ +\hspace{6mm}13.2.1 $q_{i - t - 1} \leftarrow \beta - 1$ \\ +\hspace{3mm}13.3 else \\ +\hspace{6mm}13.3.1 $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\ +\hspace{6mm}13.3.2 $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\ +\hspace{6mm}13.3.3 $q_{i - t - 1} \leftarrow \hat r$ \\ +\hspace{3mm}13.4 $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\ +\\ +Fixup quotient estimation. \\ +\hspace{3mm}13.5 Loop \\ +\hspace{6mm}13.5.1 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\ +\hspace{6mm}13.5.2 t$1 \leftarrow 0$ \\ +\hspace{6mm}13.5.3 t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\ +\hspace{6mm}13.5.4 $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\ +\hspace{6mm}13.5.5 t$2_0 \leftarrow x_{i - 2}, $ t$2_1 \leftarrow x_{i - 1}, $ t$2_2 \leftarrow x_i, $ t$2.used \leftarrow 3$ \\ +\hspace{6mm}13.5.6 If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\ +\hspace{3mm}13.6 t$1 \leftarrow y \cdot q_{i - t - 1}$ \\ +\hspace{3mm}13.7 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\ +\hspace{3mm}13.8 $x \leftarrow x - $ t$1$ \\ +\hspace{3mm}13.9 If $x.sign = MP\_NEG$ then \\ +\hspace{6mm}13.10 t$1 \leftarrow y$ \\ +\hspace{6mm}13.11 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\ +\hspace{6mm}13.12 $x \leftarrow x + $ t$1$ \\ +\hspace{6mm}13.13 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\ +\\ +Finalize the result. \\ +14. Clamp excess digits of $q$ \\ +15. $c \leftarrow q, c.sign \leftarrow sign$ \\ +16. $x.sign \leftarrow a.sign$ \\ +17. $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\ +18. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_div (continued)} +\end{figure} +\textbf{Algorithm mp\_div.} +This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor. The algorithm is a signed +division and will produce a fully qualified quotient and remainder. + +First the divisor $b$ must be non-zero which is enforced in step one. If the divisor is larger than the dividend than the quotient is implicitly +zero and the remainder is the dividend. + +After the first two trivial cases of inputs are handled the variable $q$ is setup to receive the digits of the quotient. Two unsigned copies of the +divisor $y$ and dividend $x$ are made as well. The core of the division algorithm is an unsigned division and will only work if the values are +positive. Now the two values $x$ and $y$ must be normalized such that the leading digit of $y$ is greater than or equal to $\beta / 2$. +This is performed by shifting both to the left by enough bits to get the desired normalization. + +At this point the division algorithm can begin producing digits of the quotient. Recall that maximum value of the estimation used is +$2\beta - {2 \over \beta}$ which means that a digit of the quotient must be first produced by another means. In this case $y$ is shifted +to the left (\textit{step ten}) so that it has the same number of digits as $x$. The loop on step eleven will subtract multiples of the +shifted copy of $y$ until $x$ is smaller. Since the leading digit of $y$ is greater than or equal to $\beta/2$ this loop will iterate at most two +times to produce the desired leading digit of the quotient. + +Now the remainder of the digits can be produced. The equation $\hat q = \lfloor {{x_i \beta + x_{i-1}}\over y_t} \rfloor$ is used to fairly +accurately approximate the true quotient digit. The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by +induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$. + +Recall from section~\ref{sec:divest} that the estimation is never too low but may be too high. The next step of the estimation process is +to refine the estimation. The loop on step 13.5 uses $x_i\beta^2 + x_{i-1}\beta + x_{i-2}$ and $q_{i - t - 1}(y_t\beta + y_{t-1})$ as a higher +order approximation to adjust the quotient digit. + +After both phases of estimation the quotient digit may still be off by a value of one\footnote{This is similar to the error introduced +by optimizing Barrett reduction.}. Steps 13.6 and 13.7 subtract the multiple of the divisor from the dividend (\textit{Similar to step 3.3 of +algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large. + +Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the +remainder. An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC} +is that when the estimations are being made (\textit{inside the loop on step 13.5}) that the digits $y_{t-1}$, $x_{i-2}$ and $x_{i-1}$ may lie +outside their respective boundaries. For example, if $t = 0$ or $i \le 1$ then the digits would be undefined. In those cases the digits should +respectively be replaced with a zero. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_div.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The implementation of this algorithm differs slightly from the pseudo code presented previously. In this algorithm either of the quotient $c$ or +remainder $d$ may be passed as a \textbf{NULL} pointer which indicates their value is not desired. For example, the C code to call the division +algorithm with only the quotient is + +\begin{verbatim} +mp_div(&a, &b, &c, NULL); /* c = [a/b] */ +\end{verbatim} + +Lines 109 and 113 handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor +respectively. After the two trivial cases all of the temporary variables are initialized. Line 148 determines the sign of +the quotient and line 148 ensures that both $x$ and $y$ are positive. + +The number of bits in the leading digit is calculated on line 151. Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits +of precision which when reduced modulo $lg(\beta)$ produces the value of $k$. In this case $k$ is the number of bits in the leading digit which is +exactly what is required. For the algorithm to operate $k$ must equal $lg(\beta) - 1$ and when it does not the inputs must be normalized by shifting +them to the left by $lg(\beta) - 1 - k$ bits. + +Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively. These are first used to produce the +leading digit of the quotient. The loop beginning on line 184 will produce the remainder of the quotient digits. + +The conditional ``continue'' on line 187 is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the +algorithm eliminates multiple non-zero digits in a single iteration. This ensures that $x_i$ is always non-zero since by definition the digits +above the $i$'th position $x$ must be zero in order for the quotient to be precise\footnote{Precise as far as integer division is concerned.}. + +Lines 214, 216 and 223 through 225 manually construct the high accuracy estimations by setting the digits of the two mp\_int +variables directly. + +\section{Single Digit Helpers} + +This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants. All of +the helper functions assume the single digit input is positive and will treat them as such. + +\subsection{Single Digit Addition and Subtraction} + +Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction +algorithms. As a result these algorithms are subtantially simpler with a slight cost in performance. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_add\_d}. \\ +\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ +\textbf{Output}. $c = a + b$ \\ +\hline \\ +1. $t \leftarrow b$ (\textit{mp\_set}) \\ +2. $c \leftarrow a + t$ \\ +3. Return(\textit{MP\_OKAY}) \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_add\_d} +\end{figure} + +\textbf{Algorithm mp\_add\_d.} +This algorithm initiates a temporary mp\_int with the value of the single digit and uses algorithm mp\_add to add the two values together. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_add\_d.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Clever use of the letter 't'. + +\subsubsection{Subtraction} +The single digit subtraction algorithm mp\_sub\_d is essentially the same except it uses mp\_sub to subtract the digit from the mp\_int. + +\subsection{Single Digit Multiplication} +Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline +multiplication algorithm. Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands +only has one digit. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_mul\_d}. \\ +\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ +\textbf{Output}. $c = ab$ \\ +\hline \\ +1. $pa \leftarrow a.used$ \\ +2. Grow $c$ to at least $pa + 1$ digits. \\ +3. $oldused \leftarrow c.used$ \\ +4. $c.used \leftarrow pa + 1$ \\ +5. $c.sign \leftarrow a.sign$ \\ +6. $\mu \leftarrow 0$ \\ +7. for $ix$ from $0$ to $pa - 1$ do \\ +\hspace{3mm}7.1 $\hat r \leftarrow \mu + a_{ix}b$ \\ +\hspace{3mm}7.2 $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ +\hspace{3mm}7.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\ +8. $c_{pa} \leftarrow \mu$ \\ +9. for $ix$ from $pa + 1$ to $oldused$ do \\ +\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\ +10. Clamp excess digits of $c$. \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_mul\_d} +\end{figure} +\textbf{Algorithm mp\_mul\_d.} +This algorithm quickly multiplies an mp\_int by a small single digit value. It is specially tailored to the job and has a minimal of overhead. +Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_d.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +In this implementation the destination $c$ may point to the same mp\_int as the source $a$ since the result is written after the digit is +read from the source. This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively. + +\subsection{Single Digit Division} +Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion. Since the +divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_div\_d}. \\ +\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ +\textbf{Output}. $c = \lfloor a / b \rfloor, d = a - cb$ \\ +\hline \\ +1. If $b = 0$ then return(\textit{MP\_VAL}).\\ +2. If $b = 3$ then use algorithm mp\_div\_3 instead. \\ +3. Init $q$ to $a.used$ digits. \\ +4. $q.used \leftarrow a.used$ \\ +5. $q.sign \leftarrow a.sign$ \\ +6. $\hat w \leftarrow 0$ \\ +7. for $ix$ from $a.used - 1$ down to $0$ do \\ +\hspace{3mm}7.1 $\hat w \leftarrow \hat w \beta + a_{ix}$ \\ +\hspace{3mm}7.2 If $\hat w \ge b$ then \\ +\hspace{6mm}7.2.1 $t \leftarrow \lfloor \hat w / b \rfloor$ \\ +\hspace{6mm}7.2.2 $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\ +\hspace{3mm}7.3 else\\ +\hspace{6mm}7.3.1 $t \leftarrow 0$ \\ +\hspace{3mm}7.4 $q_{ix} \leftarrow t$ \\ +8. $d \leftarrow \hat w$ \\ +9. Clamp excess digits of $q$. \\ +10. $c \leftarrow q$ \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_div\_d} +\end{figure} +\textbf{Algorithm mp\_div\_d.} +This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach. Essentially in every iteration of the +algorithm another digit of the dividend is reduced and another digit of quotient produced. Provided $b < \beta$ the value of $\hat w$ +after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$. + +If the divisor $b$ is equal to three a variant of this algorithm is used which is called mp\_div\_3. It replaces the division by three with +a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup. In essence it is much like the Barrett reduction +from chapter seven. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_d.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Like the implementation of algorithm mp\_div this algorithm allows either of the quotient or remainder to be passed as a \textbf{NULL} pointer to +indicate the respective value is not required. This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created. + +The division and remainder on lines 44 and @45,%@ can be replaced often by a single division on most processors. For example, the 32-bit x86 based +processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously. Unfortunately the GCC +compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively. + +\subsection{Single Digit Root Extraction} + +Finding the $n$'th root of an integer is fairly easy as far as numerical analysis is concerned. Algorithms such as the Newton-Raphson approximation +(\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$. + +\begin{equation} +x_{i+1} = x_i - {f(x_i) \over f'(x_i)} +\label{eqn:newton} +\end{equation} + +In this case the $n$'th root is desired and $f(x) = x^n - a$ where $a$ is the integer of which the root is desired. The derivative of $f(x)$ is +simply $f'(x) = nx^{n - 1}$. Of particular importance is that this algorithm will be used over the integers not over the a more continuous domain +such as the real numbers. As a result the root found can be above the true root by few and must be manually adjusted. Ideally at the end of the +algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_n\_root}. \\ +\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ +\textbf{Output}. $c^b \le a$ \\ +\hline \\ +1. If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\ +2. $sign \leftarrow a.sign$ \\ +3. $a.sign \leftarrow MP\_ZPOS$ \\ +4. t$2 \leftarrow 2$ \\ +5. Loop \\ +\hspace{3mm}5.1 t$1 \leftarrow $ t$2$ \\ +\hspace{3mm}5.2 t$3 \leftarrow $ t$1^{b - 1}$ \\ +\hspace{3mm}5.3 t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\ +\hspace{3mm}5.4 t$2 \leftarrow $ t$2 - a$ \\ +\hspace{3mm}5.5 t$3 \leftarrow $ t$3 \cdot b$ \\ +\hspace{3mm}5.6 t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\ +\hspace{3mm}5.7 t$2 \leftarrow $ t$1 - $ t$3$ \\ +\hspace{3mm}5.8 If t$1 \ne $ t$2$ then goto step 5. \\ +6. Loop \\ +\hspace{3mm}6.1 t$2 \leftarrow $ t$1^b$ \\ +\hspace{3mm}6.2 If t$2 > a$ then \\ +\hspace{6mm}6.2.1 t$1 \leftarrow $ t$1 - 1$ \\ +\hspace{6mm}6.2.2 Goto step 6. \\ +7. $a.sign \leftarrow sign$ \\ +8. $c \leftarrow $ t$1$ \\ +9. $c.sign \leftarrow sign$ \\ +10. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_n\_root} +\end{figure} +\textbf{Algorithm mp\_n\_root.} +This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach. It is partially optimized based on the observation +that the numerator of ${f(x) \over f'(x)}$ can be derived from a partial denominator. That is at first the denominator is calculated by finding +$x^{b - 1}$. This value can then be multiplied by $x$ and have $a$ subtracted from it to find the numerator. This saves a total of $b - 1$ +multiplications by t$1$ inside the loop. + +The initial value of the approximation is t$2 = 2$ which allows the algorithm to start with very small values and quickly converge on the +root. Ideally this algorithm is meant to find the $n$'th root of an input where $n$ is bounded by $2 \le n \le 5$. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_n\_root.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\section{Random Number Generation} + +Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms. Pollard-Rho +factoring for example, can make use of random values as starting points to find factors of a composite integer. In this case the algorithm presented +is solely for simulations and not intended for cryptographic use. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_rand}. \\ +\textbf{Input}. An integer $b$ \\ +\textbf{Output}. A pseudo-random number of $b$ digits \\ +\hline \\ +1. $a \leftarrow 0$ \\ +2. If $b \le 0$ return(\textit{MP\_OKAY}) \\ +3. Pick a non-zero random digit $d$. \\ +4. $a \leftarrow a + d$ \\ +5. for $ix$ from 1 to $d - 1$ do \\ +\hspace{3mm}5.1 $a \leftarrow a \cdot \beta$ \\ +\hspace{3mm}5.2 Pick a random digit $d$. \\ +\hspace{3mm}5.3 $a \leftarrow a + d$ \\ +6. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_rand} +\end{figure} +\textbf{Algorithm mp\_rand.} +This algorithm produces a pseudo-random integer of $b$ digits. By ensuring that the first digit is non-zero the algorithm also guarantees that the +final result has at least $b$ digits. It relies heavily on a third-part random number generator which should ideally generate uniformly all of +the integers from $0$ to $\beta - 1$. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_rand.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\section{Formatted Representations} +The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties. For example, the ability to +be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers +into a program. + +\subsection{Reading Radix-n Input} +For the purposes of this text we will assume that a simple lower ASCII map (\ref{fig:ASC}) is used for the values of from $0$ to $63$ to +printable characters. For example, when the character ``N'' is read it represents the integer $23$. The first $16$ characters of the +map are for the common representations up to hexadecimal. After that they match the ``base64'' encoding scheme which are suitable chosen +such that they are printable. While outputting as base64 may not be too helpful for human operators it does allow communication via non binary +mediums. + +\newpage\begin{figure}[here] +\begin{center} +\begin{tabular}{cc|cc|cc|cc} +\hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} \\ +\hline +0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\ +4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\ +8 & 8 & 9 & 9 & 10 & A & 11 & B \\ +12 & C & 13 & D & 14 & E & 15 & F \\ +16 & G & 17 & H & 18 & I & 19 & J \\ +20 & K & 21 & L & 22 & M & 23 & N \\ +24 & O & 25 & P & 26 & Q & 27 & R \\ +28 & S & 29 & T & 30 & U & 31 & V \\ +32 & W & 33 & X & 34 & Y & 35 & Z \\ +36 & a & 37 & b & 38 & c & 39 & d \\ +40 & e & 41 & f & 42 & g & 43 & h \\ +44 & i & 45 & j & 46 & k & 47 & l \\ +48 & m & 49 & n & 50 & o & 51 & p \\ +52 & q & 53 & r & 54 & s & 55 & t \\ +56 & u & 57 & v & 58 & w & 59 & x \\ +60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\ +\hline +\end{tabular} +\end{center} +\caption{Lower ASCII Map} +\label{fig:ASC} +\end{figure} + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_read\_radix}. \\ +\textbf{Input}. A string $str$ of length $sn$ and radix $r$. \\ +\textbf{Output}. The radix-$\beta$ equivalent mp\_int. \\ +\hline \\ +1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\ +2. $ix \leftarrow 0$ \\ +3. If $str_0 =$ ``-'' then do \\ +\hspace{3mm}3.1 $ix \leftarrow ix + 1$ \\ +\hspace{3mm}3.2 $sign \leftarrow MP\_NEG$ \\ +4. else \\ +\hspace{3mm}4.1 $sign \leftarrow MP\_ZPOS$ \\ +5. $a \leftarrow 0$ \\ +6. for $iy$ from $ix$ to $sn - 1$ do \\ +\hspace{3mm}6.1 Let $y$ denote the position in the map of $str_{iy}$. \\ +\hspace{3mm}6.2 If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\ +\hspace{3mm}6.3 $a \leftarrow a \cdot r$ \\ +\hspace{3mm}6.4 $a \leftarrow a + y$ \\ +7. If $a \ne 0$ then $a.sign \leftarrow sign$ \\ +8. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_read\_radix} +\end{figure} +\textbf{Algorithm mp\_read\_radix.} +This algorithm will read an ASCII string and produce the radix-$\beta$ mp\_int representation of the same integer. A minus symbol ``-'' may precede the +string to indicate the value is negative, otherwise it is assumed to be positive. The algorithm will read up to $sn$ characters from the input +and will stop when it reads a character it cannot map the algorithm stops reading characters from the string. This allows numbers to be embedded +as part of larger input without any significant problem. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_read\_radix.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\subsection{Generating Radix-$n$ Output} +Generating radix-$n$ output is fairly trivial with a division and remainder algorithm. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_toradix}. \\ +\textbf{Input}. A mp\_int $a$ and an integer $r$\\ +\textbf{Output}. The radix-$r$ representation of $a$ \\ +\hline \\ +1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\ +2. If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}). \\ +3. $t \leftarrow a$ \\ +4. $str \leftarrow$ ``'' \\ +5. if $t.sign = MP\_NEG$ then \\ +\hspace{3mm}5.1 $str \leftarrow str + $ ``-'' \\ +\hspace{3mm}5.2 $t.sign = MP\_ZPOS$ \\ +6. While ($t \ne 0$) do \\ +\hspace{3mm}6.1 $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\ +\hspace{3mm}6.2 $t \leftarrow \lfloor t / r \rfloor$ \\ +\hspace{3mm}6.3 Look up $d$ in the map and store the equivalent character in $y$. \\ +\hspace{3mm}6.4 $str \leftarrow str + y$ \\ +7. If $str_0 = $``$-$'' then \\ +\hspace{3mm}7.1 Reverse the digits $str_1, str_2, \ldots str_n$. \\ +8. Otherwise \\ +\hspace{3mm}8.1 Reverse the digits $str_0, str_1, \ldots str_n$. \\ +9. Return(\textit{MP\_OKAY}).\\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_toradix} +\end{figure} +\textbf{Algorithm mp\_toradix.} +This algorithm computes the radix-$r$ representation of an mp\_int $a$. The ``digits'' of the representation are extracted by reducing +successive powers of $\lfloor a / r^k \rfloor$ the input modulo $r$ until $r^k > a$. Note that instead of actually dividing by $r^k$ in +each iteration the quotient $\lfloor a / r \rfloor$ is saved for the next iteration. As a result a series of trivial $n \times 1$ divisions +are required instead of a series of $n \times k$ divisions. One design flaw of this approach is that the digits are produced in the reverse order +(see~\ref{fig:mpradix}). To remedy this flaw the digits must be swapped or simply ``reversed''. + +\begin{figure} +\begin{center} +\begin{tabular}{|c|c|c|} +\hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\ +\hline $1234$ & -- & -- \\ +\hline $123$ & $4$ & ``4'' \\ +\hline $12$ & $3$ & ``43'' \\ +\hline $1$ & $2$ & ``432'' \\ +\hline $0$ & $1$ & ``4321'' \\ +\hline +\end{tabular} +\end{center} +\caption{Example of Algorithm mp\_toradix.} +\label{fig:mpradix} +\end{figure} + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_toradix.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\chapter{Number Theoretic Algorithms} +This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi +symbol computation. These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and +various Sieve based factoring algorithms. + +\section{Greatest Common Divisor} +The greatest common divisor of two integers $a$ and $b$, often denoted as $(a, b)$ is the largest integer $k$ that is a proper divisor of +both $a$ and $b$. That is, $k$ is the largest integer such that $0 \equiv a \mbox{ (mod }k\mbox{)}$ and $0 \equiv b \mbox{ (mod }k\mbox{)}$ occur +simultaneously. + +The most common approach (cite) is to reduce one input modulo another. That is if $a$ and $b$ are divisible by some integer $k$ and if $qa + r = b$ then +$r$ is also divisible by $k$. The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Greatest Common Divisor (I)}. \\ +\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ +\textbf{Output}. The greatest common divisor $(a, b)$. \\ +\hline \\ +1. While ($b > 0$) do \\ +\hspace{3mm}1.1 $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\ +\hspace{3mm}1.2 $a \leftarrow b$ \\ +\hspace{3mm}1.3 $b \leftarrow r$ \\ +2. Return($a$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Greatest Common Divisor (I)} +\label{fig:gcd1} +\end{figure} + +This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly. However, divisions are +relatively expensive operations to perform and should ideally be avoided. There is another approach based on a similar relationship of +greatest common divisors. The faster approach is based on the observation that if $k$ divides both $a$ and $b$ it will also divide $a - b$. +In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Greatest Common Divisor (II)}. \\ +\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ +\textbf{Output}. The greatest common divisor $(a, b)$. \\ +\hline \\ +1. While ($b > 0$) do \\ +\hspace{3mm}1.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\ +\hspace{3mm}1.2 $b \leftarrow b - a$ \\ +2. Return($a$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Greatest Common Divisor (II)} +\label{fig:gcd2} +\end{figure} + +\textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.} +The algorithm in figure~\ref{fig:gcd2} will eventually terminate since $b \ge a$ the subtraction in step 1.2 will be a value less than $b$. In other +words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$. Since both $a$ and $b$ are always +divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the +second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof. \textbf{QED}. + +As a matter of practicality algorithm \ref{fig:gcd1} decreases far too slowly to be useful. Specially if $b$ is much larger than $a$ such that +$b - a$ is still very much larger than $a$. A simple addition to the algorithm is to divide $b - a$ by a power of some integer $p$ which does +not divide the greatest common divisor but will divide $b - a$. In this case ${b - a} \over p$ is also an integer and still divisible by +the greatest common divisor. + +However, instead of factoring $b - a$ to find a suitable value of $p$ the powers of $p$ can be removed from $a$ and $b$ that are in common first. +Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{Greatest Common Divisor (III)}. \\ +\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ +\textbf{Output}. The greatest common divisor $(a, b)$. \\ +\hline \\ +1. $k \leftarrow 0$ \\ +2. While $a$ and $b$ are both divisible by $p$ do \\ +\hspace{3mm}2.1 $a \leftarrow \lfloor a / p \rfloor$ \\ +\hspace{3mm}2.2 $b \leftarrow \lfloor b / p \rfloor$ \\ +\hspace{3mm}2.3 $k \leftarrow k + 1$ \\ +3. While $a$ is divisible by $p$ do \\ +\hspace{3mm}3.1 $a \leftarrow \lfloor a / p \rfloor$ \\ +4. While $b$ is divisible by $p$ do \\ +\hspace{3mm}4.1 $b \leftarrow \lfloor b / p \rfloor$ \\ +5. While ($b > 0$) do \\ +\hspace{3mm}5.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\ +\hspace{3mm}5.2 $b \leftarrow b - a$ \\ +\hspace{3mm}5.3 While $b$ is divisible by $p$ do \\ +\hspace{6mm}5.3.1 $b \leftarrow \lfloor b / p \rfloor$ \\ +6. Return($a \cdot p^k$). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm Greatest Common Divisor (III)} +\label{fig:gcd3} +\end{figure} + +This algorithm is based on the first except it removes powers of $p$ first and inside the main loop to ensure the tuple $\left < a, b \right >$ +decreases more rapidly. The first loop on step two removes powers of $p$ that are in common. A count, $k$, is kept which will present a common +divisor of $p^k$. After step two the remaining common divisor of $a$ and $b$ cannot be divisible by $p$. This means that $p$ can be safely +divided out of the difference $b - a$ so long as the division leaves no remainder. + +In particular the value of $p$ should be chosen such that the division on step 5.3.1 occur often. It also helps that division by $p$ be easy +to compute. The ideal choice of $p$ is two since division by two amounts to a right logical shift. Another important observation is that by +step five both $a$ and $b$ are odd. Therefore, the diffrence $b - a$ must be even which means that each iteration removes one bit from the +largest of the pair. + +\subsection{Complete Greatest Common Divisor} +The algorithms presented so far cannot handle inputs which are zero or negative. The following algorithm can handle all input cases properly +and will produce the greatest common divisor. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_gcd}. \\ +\textbf{Input}. mp\_int $a$ and $b$ \\ +\textbf{Output}. The greatest common divisor $c = (a, b)$. \\ +\hline \\ +1. If $a = 0$ then \\ +\hspace{3mm}1.1 $c \leftarrow \vert b \vert $ \\ +\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ +2. If $b = 0$ then \\ +\hspace{3mm}2.1 $c \leftarrow \vert a \vert $ \\ +\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\ +3. $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\ +4. $k \leftarrow 0$ \\ +5. While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}5.1 $k \leftarrow k + 1$ \\ +\hspace{3mm}5.2 $u \leftarrow \lfloor u / 2 \rfloor$ \\ +\hspace{3mm}5.3 $v \leftarrow \lfloor v / 2 \rfloor$ \\ +6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\ +7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ +8. While $v.used > 0$ \\ +\hspace{3mm}8.1 If $\vert u \vert > \vert v \vert$ then \\ +\hspace{6mm}8.1.1 Swap $u$ and $v$. \\ +\hspace{3mm}8.2 $v \leftarrow \vert v \vert - \vert u \vert$ \\ +\hspace{3mm}8.3 While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{6mm}8.3.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ +9. $c \leftarrow u \cdot 2^k$ \\ +10. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_gcd} +\end{figure} +\textbf{Algorithm mp\_gcd.} +This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$. The algorithm was originally based on Algorithm B of +Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain. In theory it achieves the same asymptotic working time as +Algorithm B and in practice this appears to be true. + +The first two steps handle the cases where either one of or both inputs are zero. If either input is zero the greatest common divisor is the +largest input or zero if they are both zero. If the inputs are not trivial than $u$ and $v$ are assigned the absolute values of +$a$ and $b$ respectively and the algorithm will proceed to reduce the pair. + +Step five will divide out any common factors of two and keep track of the count in the variable $k$. After this step, two is no longer a +factor of the remaining greatest common divisor between $u$ and $v$ and can be safely evenly divided out of either whenever they are even. Step +six and seven ensure that the $u$ and $v$ respectively have no more factors of two. At most only one of the while--loops will iterate since +they cannot both be even. + +By step eight both of $u$ and $v$ are odd which is required for the inner logic. First the pair are swapped such that $v$ is equal to +or greater than $u$. This ensures that the subtraction on step 8.2 will always produce a positive and even result. Step 8.3 removes any +factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd. + +After $v = 0$ occurs the variable $u$ has the greatest common divisor of the pair $\left < u, v \right >$ just after step six. The result +must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_gcd.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +This function makes use of the macros mp\_iszero and mp\_iseven. The former evaluates to $1$ if the input mp\_int is equivalent to the +integer zero otherwise it evaluates to $0$. The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise +it evaluates to $0$. Note that just because mp\_iseven may evaluate to $0$ does not mean the input is odd, it could also be zero. The three +trivial cases of inputs are handled on lines 24 through 30. After those lines the inputs are assumed to be non-zero. + +Lines 32 and 37 make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively. At this point the common factors of two +must be divided out of the two inputs. The block starting at line 44 removes common factors of two by first counting the number of trailing +zero bits in both. The local integer $k$ is used to keep track of how many factors of $2$ are pulled out of both values. It is assumed that +the number of factors will not exceed the maximum value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than +entries than are accessible by an ``int'' so this is not a limitation.}. + +At this point there are no more common factors of two in the two values. The divisions by a power of two on lines 62 and 68 remove +any independent factors of two such that both $u$ and $v$ are guaranteed to be an odd integer before hitting the main body of the algorithm. The while loop +on line 73 performs the reduction of the pair until $v$ is equal to zero. The unsigned comparison and subtraction algorithms are used in +place of the full signed routines since both values are guaranteed to be positive and the result of the subtraction is guaranteed to be non-negative. + +\section{Least Common Multiple} +The least common multiple of a pair of integers is their product divided by their greatest common divisor. For two integers $a$ and $b$ the +least common multiple is normally denoted as $[ a, b ]$ and numerically equivalent to ${ab} \over {(a, b)}$. For example, if $a = 2 \cdot 2 \cdot 3 = 12$ +and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$. + +The least common multiple arises often in coding theory as well as number theory. If two functions have periods of $a$ and $b$ respectively they will +collide, that is be in synchronous states, after only $[ a, b ]$ iterations. This is why, for example, random number generators based on +Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}). +Similarly in number theory if a composite $n$ has two prime factors $p$ and $q$ then maximal order of any unit of $\Z/n\Z$ will be $[ p - 1, q - 1] $. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_lcm}. \\ +\textbf{Input}. mp\_int $a$ and $b$ \\ +\textbf{Output}. The least common multiple $c = [a, b]$. \\ +\hline \\ +1. $c \leftarrow (a, b)$ \\ +2. $t \leftarrow a \cdot b$ \\ +3. $c \leftarrow \lfloor t / c \rfloor$ \\ +4. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_lcm} +\end{figure} +\textbf{Algorithm mp\_lcm.} +This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$. It computes the least common multiple directly by +dividing the product of the two inputs by their greatest common divisor. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_lcm.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\section{Jacobi Symbol Computation} +To explain the Jacobi Symbol we shall first discuss the Legendre function\footnote{Arrg. What is the name of this?} off which the Jacobi symbol is +defined. The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$. Numerically it is +equivalent to equation \ref{eqn:legendre}. + +\textit{-- Tom, don't be an ass, cite your source here...!} + +\begin{equation} +a^{(p-1)/2} \equiv \begin{array}{rl} + -1 & \mbox{if }a\mbox{ is a quadratic non-residue.} \\ + 0 & \mbox{if }a\mbox{ divides }p\mbox{.} \\ + 1 & \mbox{if }a\mbox{ is a quadratic residue}. + \end{array} \mbox{ (mod }p\mbox{)} +\label{eqn:legendre} +\end{equation} + +\textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.} +An integer $a$ is a quadratic residue if the following equation has a solution. + +\begin{equation} +x^2 \equiv a \mbox{ (mod }p\mbox{)} +\label{eqn:root} +\end{equation} + +Consider the following equation. + +\begin{equation} +0 \equiv x^{p-1} - 1 \equiv \left \lbrace \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \right \rbrace + \left ( a^{(p-1)/2} - 1 \right ) \mbox{ (mod }p\mbox{)} +\label{eqn:rooti} +\end{equation} + +Whether equation \ref{eqn:root} has a solution or not equation \ref{eqn:rooti} is always true. If $a^{(p-1)/2} - 1 \equiv 0 \mbox{ (mod }p\mbox{)}$ +then the quantity in the braces must be zero. By reduction, + +\begin{eqnarray} +\left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0 \nonumber \\ +\left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\ +x^2 \equiv a \mbox{ (mod }p\mbox{)} +\end{eqnarray} + +As a result there must be a solution to the quadratic equation and in turn $a$ must be a quadratic residue. If $a$ does not divide $p$ and $a$ +is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since +\begin{equation} +0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)} +\end{equation} +One of the terms on the right hand side must be zero. \textbf{QED} + +\subsection{Jacobi Symbol} +The Jacobi symbol is a generalization of the Legendre function for any odd non prime moduli $p$ greater than 2. If $p = \prod_{i=0}^n p_i$ then +the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation. + +\begin{equation} +\left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right ) +\end{equation} + +By inspection if $p$ is prime the Jacobi symbol is equivalent to the Legendre function. The following facts\footnote{See HAC \cite[pp. 72-74]{HAC} for +further details.} will be used to derive an efficient Jacobi symbol algorithm. Where $p$ is an odd integer greater than two and $a, b \in \Z$ the +following are true. + +\begin{enumerate} +\item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$. +\item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$. +\item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$. +\item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$. Otherwise, it equals $-1$. +\item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$. More specifically +$\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$. +\end{enumerate} + +Using these facts if $a = 2^k \cdot a'$ then + +\begin{eqnarray} +\left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\ + = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right ) +\label{eqn:jacobi} +\end{eqnarray} + +By fact five, + +\begin{equation} +\left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} +\end{equation} + +Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then + +\begin{equation} +\left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} +\end{equation} + +By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed. + +\begin{equation} +\left ( { a \over p } \right ) = \left ( {2 \over p } \right )^k \left ( {{p\mbox{ mod }a'} \over a'} \right ) \cdot (-1)^{(p-1)(a'-1)/4} +\end{equation} + +The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively. The value of +$\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$. Using this approach the +factors of $p$ do not have to be known. Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the +Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$. + +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_jacobi}. \\ +\textbf{Input}. mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\ +\textbf{Output}. The Jacobi symbol $c = \left ( {a \over p } \right )$. \\ +\hline \\ +1. If $a = 0$ then \\ +\hspace{3mm}1.1 $c \leftarrow 0$ \\ +\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ +2. If $a = 1$ then \\ +\hspace{3mm}2.1 $c \leftarrow 1$ \\ +\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\ +3. $a' \leftarrow a$ \\ +4. $k \leftarrow 0$ \\ +5. While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}5.1 $k \leftarrow k + 1$ \\ +\hspace{3mm}5.2 $a' \leftarrow \lfloor a' / 2 \rfloor$ \\ +6. If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\ +\hspace{3mm}6.1 $s \leftarrow 1$ \\ +7. else \\ +\hspace{3mm}7.1 $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\ +\hspace{3mm}7.2 If $r = 1$ or $r = 7$ then \\ +\hspace{6mm}7.2.1 $s \leftarrow 1$ \\ +\hspace{3mm}7.3 else \\ +\hspace{6mm}7.3.1 $s \leftarrow -1$ \\ +8. If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\ +\hspace{3mm}8.1 $s \leftarrow -s$ \\ +9. If $a' \ne 1$ then \\ +\hspace{3mm}9.1 $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\ +\hspace{3mm}9.2 $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\ +10. $c \leftarrow s$ \\ +11. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_jacobi} +\end{figure} +\textbf{Algorithm mp\_jacobi.} +This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three. The algorithm +is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}. + +Step numbers one and two handle the trivial cases of $a = 0$ and $a = 1$ respectively. Step five determines the number of two factors in the +input $a$. If $k$ is even than the term $\left ( { 2 \over p } \right )^k$ must always evaluate to one. If $k$ is odd than the term evaluates to one +if $p_0$ is congruent to one or seven modulo eight, otherwise it evaluates to $-1$. After the the $\left ( { 2 \over p } \right )^k$ term is handled +the $(-1)^{(p-1)(a'-1)/4}$ is computed and multiplied against the current product $s$. The latter term evaluates to one if both $p$ and $a'$ +are congruent to one modulo four, otherwise it evaluates to negative one. + +By step nine if $a'$ does not equal one a recursion is required. Step 9.1 computes $p' \equiv p \mbox{ (mod }a'\mbox{)}$ and will recurse to compute +$\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_jacobi.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +As a matter of practicality the variable $a'$ as per the pseudo-code is reprensented by the variable $a1$ since the $'$ symbol is not valid for a C +variable name character. + +The two simple cases of $a = 0$ and $a = 1$ are handled at the very beginning to simplify the algorithm. If the input is non-trivial the algorithm +has to proceed compute the Jacobi. The variable $s$ is used to hold the current Jacobi product. Note that $s$ is merely a C ``int'' data type since +the values it may obtain are merely $-1$, $0$ and $1$. + +After a local copy of $a$ is made all of the factors of two are divided out and the total stored in $k$. Technically only the least significant +bit of $k$ is required, however, it makes the algorithm simpler to follow to perform an addition. In practice an exclusive-or and addition have the same +processor requirements and neither is faster than the other. + +Line 58 through 71 determines the value of $\left ( { 2 \over p } \right )^k$. If the least significant bit of $k$ is zero than +$k$ is even and the value is one. Otherwise, the value of $s$ depends on which residue class $p$ belongs to modulo eight. The value of +$(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines 71 through 74. + +Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$. + +\textit{-- Comment about default $s$ and such...} + +\section{Modular Inverse} +\label{sec:modinv} +The modular inverse of a number actually refers to the modular multiplicative inverse. Essentially for any integer $a$ such that $(a, p) = 1$ there +exist another integer $b$ such that $ab \equiv 1 \mbox{ (mod }p\mbox{)}$. The integer $b$ is called the multiplicative inverse of $a$ which is +denoted as $b = a^{-1}$. Technically speaking modular inversion is a well defined operation for any finite ring or field not just for rings and +fields of integers. However, the former will be the matter of discussion. + +The simplest approach is to compute the algebraic inverse of the input. That is to compute $b \equiv a^{\Phi(p) - 1}$. If $\Phi(p)$ is the +order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$. The proof of which is trivial. + +\begin{equation} +ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)} +\end{equation} + +However, as simple as this approach may be it has two serious flaws. It requires that the value of $\Phi(p)$ be known which if $p$ is composite +requires all of the prime factors. This approach also is very slow as the size of $p$ grows. + +A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear +Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation. + +\begin{equation} +ab + pq = 1 +\end{equation} + +Where $a$, $b$, $p$ and $q$ are all integers. If such a pair of integers $ \left < b, q \right >$ exist than $b$ is the multiplicative inverse of +$a$ modulo $p$. The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$. +However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place. The +binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine +equation. + +\subsection{General Case} +\newpage\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_invmod}. \\ +\textbf{Input}. mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$. \\ +\textbf{Output}. The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\ +\hline \\ +1. If $b \le 0$ then return(\textit{MP\_VAL}). \\ +2. If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\ +3. $x \leftarrow \vert a \vert, y \leftarrow b$ \\ +4. If $x_0 \equiv y_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\ +5. $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\ +6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\ +\hspace{3mm}6.2 If ($A.used > 0$ and $A_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($B.used > 0$ and $B_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\ +\hspace{6mm}6.2.1 $A \leftarrow A + y$ \\ +\hspace{6mm}6.2.2 $B \leftarrow B - x$ \\ +\hspace{3mm}6.3 $A \leftarrow \lfloor A / 2 \rfloor$ \\ +\hspace{3mm}6.4 $B \leftarrow \lfloor B / 2 \rfloor$ \\ +7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ +\hspace{3mm}7.2 If ($C.used > 0$ and $C_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($D.used > 0$ and $D_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\ +\hspace{6mm}7.2.1 $C \leftarrow C + y$ \\ +\hspace{6mm}7.2.2 $D \leftarrow D - x$ \\ +\hspace{3mm}7.3 $C \leftarrow \lfloor C / 2 \rfloor$ \\ +\hspace{3mm}7.4 $D \leftarrow \lfloor D / 2 \rfloor$ \\ +8. If $u \ge v$ then \\ +\hspace{3mm}8.1 $u \leftarrow u - v$ \\ +\hspace{3mm}8.2 $A \leftarrow A - C$ \\ +\hspace{3mm}8.3 $B \leftarrow B - D$ \\ +9. else \\ +\hspace{3mm}9.1 $v \leftarrow v - u$ \\ +\hspace{3mm}9.2 $C \leftarrow C - A$ \\ +\hspace{3mm}9.3 $D \leftarrow D - B$ \\ +10. If $u \ne 0$ goto step 6. \\ +11. If $v \ne 1$ return(\textit{MP\_VAL}). \\ +12. While $C \le 0$ do \\ +\hspace{3mm}12.1 $C \leftarrow C + b$ \\ +13. While $C \ge b$ do \\ +\hspace{3mm}13.1 $C \leftarrow C - b$ \\ +14. $c \leftarrow C$ \\ +15. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\end{figure} +\textbf{Algorithm mp\_invmod.} +This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$. This algorithm is a variation of the +extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}. It has been modified to only compute the modular inverse and not a complete +Diophantine solution. + +If $b \le 0$ than the modulus is invalid and MP\_VAL is returned. Similarly if both $a$ and $b$ are even then there cannot be a multiplicative +inverse for $a$ and the error is reported. + +The astute reader will observe that steps seven through nine are very similar to the binary greatest common divisor algorithm mp\_gcd. In this case +the other variables to the Diophantine equation are solved. The algorithm terminates when $u = 0$ in which case the solution is + +\begin{equation} +Ca + Db = v +\end{equation} + +If $v$, the greatest common divisor of $a$ and $b$ is not equal to one then the algorithm will report an error as no inverse exists. Otherwise, $C$ +is the modular inverse of $a$. The actual value of $C$ is congruent to, but not necessarily equal to, the ideal modular inverse which should lie +within $1 \le a^{-1} < b$. Step numbers twelve and thirteen adjust the inverse until it is in range. If the original input $a$ is within $0 < a < p$ +then only a couple of additions or subtractions will be required to adjust the inverse. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_invmod.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\subsubsection{Odd Moduli} + +When the modulus $b$ is odd the variables $A$ and $C$ are fixed and are not required to compute the inverse. In particular by attempting to solve +the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$. + +The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed. This +optimization will halve the time required to compute the modular inverse. + +\section{Primality Tests} + +A non-zero integer $a$ is said to be prime if it is not divisible by any other integer excluding one and itself. For example, $a = 7$ is prime +since the integers $2 \ldots 6$ do not evenly divide $a$. By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$. + +Prime numbers arise in cryptography considerably as they allow finite fields to be formed. The ability to determine whether an integer is prime or +not quickly has been a viable subject in cryptography and number theory for considerable time. The algorithms that will be presented are all +probablistic algorithms in that when they report an integer is composite it must be composite. However, when the algorithms report an integer is +prime the algorithm may be incorrect. + +As will be discussed it is possible to limit the probability of error so well that for practical purposes the probablity of error might as +well be zero. For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question. + +\subsection{Trial Division} + +Trial division means to attempt to evenly divide a candidate integer by small prime integers. If the candidate can be evenly divided it obviously +cannot be prime. By dividing by all primes $1 < p \le \sqrt{n}$ this test can actually prove whether an integer is prime. However, such a test +would require a prohibitive amount of time as $n$ grows. + +Instead of dividing by every prime, a smaller, more mangeable set of primes may be used instead. By performing trial division with only a subset +of the primes less than $\sqrt{n} + 1$ the algorithm cannot prove if a candidate is prime. However, often it can prove a candidate is not prime. + +The benefit of this test is that trial division by small values is fairly efficient. Specially compared to the other algorithms that will be +discussed shortly. The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by +$1 - {1.12 \over ln(q)}$. The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range +$3 \le q \le 100$. + +At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly. At $q = 90$ further testing is generally not going to +be of any practical use. In the case of LibTomMath the default limit $q = 256$ was chosen since it is not too high and will eliminate +approximately $80\%$ of all candidate integers. The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base. The +array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\ +\textbf{Input}. mp\_int $a$ \\ +\textbf{Output}. $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$. \\ +\hline \\ +1. for $ix$ from $0$ to $PRIME\_SIZE$ do \\ +\hspace{3mm}1.1 $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\ +\hspace{3mm}1.2 If $d = 0$ then \\ +\hspace{6mm}1.2.1 $c \leftarrow 1$ \\ +\hspace{6mm}1.2.2 Return(\textit{MP\_OKAY}). \\ +2. $c \leftarrow 0$ \\ +3. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_prime\_is\_divisible} +\end{figure} +\textbf{Algorithm mp\_prime\_is\_divisible.} +This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_is\_divisible.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +The algorithm defaults to a return of $0$ in case an error occurs. The values in the prime table are all specified to be in the range of a +mp\_digit. The table \_\_prime\_tab is defined in the following file. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_prime\_tab.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +Note that there are two possible tables. When an mp\_digit is 7-bits long only the primes upto $127$ may be included, otherwise the primes +upto $1619$ are used. Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit. + +\subsection{The Fermat Test} +The Fermat test is probably one the oldest tests to have a non-trivial probability of success. It is based on the fact that if $n$ is in +fact prime then $a^{n} \equiv a \mbox{ (mod }n\mbox{)}$ for all $0 < a < n$. The reason being that if $n$ is prime than the order of +the multiplicative sub group is $n - 1$. Any base $a$ must have an order which divides $n - 1$ and as such $a^n$ is equivalent to +$a^1 = a$. + +If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$. In which case +it is possible that $a^n \nequiv a \mbox{ (mod }n\mbox{)}$. However, this test is not absolute as it is possible that the order +of a base will divide $n - 1$ which would then be reported as prime. Such a base yields what is known as a Fermat pseudo-prime. Several +integers known as Carmichael numbers will be a pseudo-prime to all valid bases. Fortunately such numbers are extremely rare as $n$ grows +in size. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_prime\_fermat}. \\ +\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\ +\textbf{Output}. $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$. \\ +\hline \\ +1. $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\ +2. If $t = b$ then \\ +\hspace{3mm}2.1 $c = 1$ \\ +3. else \\ +\hspace{3mm}3.1 $c = 0$ \\ +4. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_prime\_fermat} +\end{figure} +\textbf{Algorithm mp\_prime\_fermat.} +This algorithm determines whether an mp\_int $a$ is a Fermat prime to the base $b$ or not. It uses a single modular exponentiation to +determine the result. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_fermat.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + +\subsection{The Miller-Rabin Test} +The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen +candidate integers. The algorithm is based on the observation that if $n - 1 = 2^kr$ and if $b^r \nequiv \pm 1$ then after upto $k - 1$ squarings the +value must be equal to $-1$. The squarings are stopped as soon as $-1$ is observed. If the value of $1$ is observed first it means that +some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime. + +\begin{figure}[!here] +\begin{small} +\begin{center} +\begin{tabular}{l} +\hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\ +\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\ +\textbf{Output}. $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$. \\ +\hline +1. $a' \leftarrow a - 1$ \\ +2. $r \leftarrow n1$ \\ +3. $c \leftarrow 0, s \leftarrow 0$ \\ +4. While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ +\hspace{3mm}4.1 $s \leftarrow s + 1$ \\ +\hspace{3mm}4.2 $r \leftarrow \lfloor r / 2 \rfloor$ \\ +5. $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\ +6. If $y \nequiv \pm 1$ then \\ +\hspace{3mm}6.1 $j \leftarrow 1$ \\ +\hspace{3mm}6.2 While $j \le (s - 1)$ and $y \nequiv a'$ \\ +\hspace{6mm}6.2.1 $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\ +\hspace{6mm}6.2.2 If $y = 1$ then goto step 8. \\ +\hspace{6mm}6.2.3 $j \leftarrow j + 1$ \\ +\hspace{3mm}6.3 If $y \nequiv a'$ goto step 8. \\ +7. $c \leftarrow 1$\\ +8. Return(\textit{MP\_OKAY}). \\ +\hline +\end{tabular} +\end{center} +\end{small} +\caption{Algorithm mp\_prime\_miller\_rabin} +\end{figure} +\textbf{Algorithm mp\_prime\_miller\_rabin.} +This algorithm performs one trial round of the Miller-Rabin algorithm to the base $b$. It will set $c = 1$ if the algorithm cannot determine +if $b$ is composite or $c = 0$ if $b$ is provably composite. The values of $s$ and $r$ are computed such that $a' = a - 1 = 2^sr$. + +If the value $y \equiv b^r$ is congruent to $\pm 1$ then the algorithm cannot prove if $a$ is composite or not. Otherwise, the algorithm will +square $y$ upto $s - 1$ times stopping only when $y \equiv -1$. If $y^2 \equiv 1$ and $y \nequiv \pm 1$ then the algorithm can report that $a$ +is provably composite. If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite. If $a$ is not provably +composite then it is \textit{probably} prime. + +\vspace{+3mm}\begin{small} +\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_miller\_rabin.c +\vspace{-3mm} +\begin{alltt} +\end{alltt} +\end{small} + + + + +\backmatter +\appendix +\begin{thebibliography}{ABCDEF} +\bibitem[1]{TAOCPV2} +Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998 + +\bibitem[2]{HAC} +A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996 + +\bibitem[3]{ROSE} +Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999 + +\bibitem[4]{COMBA} +Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990) + +\bibitem[5]{KARA} +A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294 + +\bibitem[6]{KARAP} +Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002 + +\bibitem[7]{BARRETT} +Paul Barrett, \textit{Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor}, Advances in Cryptology, Crypto '86, Springer-Verlag. + +\bibitem[8]{MONT} +P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985. + +\bibitem[9]{DRMET} +Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories + +\bibitem[10]{MMB} +J. Daemen and R. Govaerts and J. Vandewalle, \textit{Block ciphers based on Modular Arithmetic}, State and {P}rogress in the {R}esearch of {C}ryptography, 1993, pp. 80-89 + +\bibitem[11]{RSAREF} +R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems} + +\bibitem[12]{DHREF} +Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976 + +\bibitem[13]{IEEE} +IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985) + +\bibitem[14]{GMP} +GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/} + +\bibitem[15]{MPI} +Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/} + +\bibitem[16]{OPENSSL} +OpenSSL Cryptographic Toolkit, \url{http://openssl.org} + +\bibitem[17]{LIP} +Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip} + +\bibitem[18]{ISOC} +JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.'' + +\bibitem[19]{JAVA} +The Sun Java Website, \url{http://java.sun.com/} + +\end{thebibliography} + +\input{tommath.ind} + +\end{document} diff --git a/lib/hcrypto/libtommath/tommath_class.h b/lib/hcrypto/libtommath/tommath_class.h new file mode 100644 index 000000000..166dd80e5 --- /dev/null +++ b/lib/hcrypto/libtommath/tommath_class.h @@ -0,0 +1,999 @@ +#if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) +#if defined(LTM2) +#define LTM3 +#endif +#if defined(LTM1) +#define LTM2 +#endif +#define LTM1 + +#if defined(LTM_ALL) +#define BN_ERROR_C +#define BN_FAST_MP_INVMOD_C +#define BN_FAST_MP_MONTGOMERY_REDUCE_C +#define BN_FAST_S_MP_MUL_DIGS_C +#define BN_FAST_S_MP_MUL_HIGH_DIGS_C +#define BN_FAST_S_MP_SQR_C +#define BN_MP_2EXPT_C +#define BN_MP_ABS_C +#define BN_MP_ADD_C +#define BN_MP_ADD_D_C +#define BN_MP_ADDMOD_C +#define BN_MP_AND_C +#define BN_MP_CLAMP_C +#define BN_MP_CLEAR_C +#define BN_MP_CLEAR_MULTI_C +#define BN_MP_CMP_C +#define BN_MP_CMP_D_C +#define BN_MP_CMP_MAG_C +#define BN_MP_CNT_LSB_C +#define BN_MP_COPY_C +#define BN_MP_COUNT_BITS_C +#define BN_MP_DIV_C +#define BN_MP_DIV_2_C +#define BN_MP_DIV_2D_C +#define BN_MP_DIV_3_C +#define BN_MP_DIV_D_C +#define BN_MP_DR_IS_MODULUS_C +#define BN_MP_DR_REDUCE_C +#define BN_MP_DR_SETUP_C +#define BN_MP_EXCH_C +#define BN_MP_EXPT_D_C +#define BN_MP_EXPTMOD_C +#define BN_MP_EXPTMOD_FAST_C +#define BN_MP_EXTEUCLID_C +#define BN_MP_FREAD_C +#define BN_MP_FWRITE_C +#define BN_MP_GCD_C +#define BN_MP_GET_INT_C +#define BN_MP_GROW_C +#define BN_MP_INIT_C +#define BN_MP_INIT_COPY_C +#define BN_MP_INIT_MULTI_C +#define BN_MP_INIT_SET_C +#define BN_MP_INIT_SET_INT_C +#define BN_MP_INIT_SIZE_C +#define BN_MP_INVMOD_C +#define BN_MP_INVMOD_SLOW_C +#define BN_MP_IS_SQUARE_C +#define BN_MP_JACOBI_C +#define BN_MP_KARATSUBA_MUL_C +#define BN_MP_KARATSUBA_SQR_C +#define BN_MP_LCM_C +#define BN_MP_LSHD_C +#define BN_MP_MOD_C +#define BN_MP_MOD_2D_C +#define BN_MP_MOD_D_C +#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +#define BN_MP_MONTGOMERY_REDUCE_C +#define BN_MP_MONTGOMERY_SETUP_C +#define BN_MP_MUL_C +#define BN_MP_MUL_2_C +#define BN_MP_MUL_2D_C +#define BN_MP_MUL_D_C +#define BN_MP_MULMOD_C +#define BN_MP_N_ROOT_C +#define BN_MP_NEG_C +#define BN_MP_OR_C +#define BN_MP_PRIME_FERMAT_C +#define BN_MP_PRIME_IS_DIVISIBLE_C +#define BN_MP_PRIME_IS_PRIME_C +#define BN_MP_PRIME_MILLER_RABIN_C +#define BN_MP_PRIME_NEXT_PRIME_C +#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C +#define BN_MP_PRIME_RANDOM_EX_C +#define BN_MP_RADIX_SIZE_C +#define BN_MP_RADIX_SMAP_C +#define BN_MP_RAND_C +#define BN_MP_READ_RADIX_C +#define BN_MP_READ_SIGNED_BIN_C +#define BN_MP_READ_UNSIGNED_BIN_C +#define BN_MP_REDUCE_C +#define BN_MP_REDUCE_2K_C +#define BN_MP_REDUCE_2K_L_C +#define BN_MP_REDUCE_2K_SETUP_C +#define BN_MP_REDUCE_2K_SETUP_L_C +#define BN_MP_REDUCE_IS_2K_C +#define BN_MP_REDUCE_IS_2K_L_C +#define BN_MP_REDUCE_SETUP_C +#define BN_MP_RSHD_C +#define BN_MP_SET_C +#define BN_MP_SET_INT_C +#define BN_MP_SHRINK_C +#define BN_MP_SIGNED_BIN_SIZE_C +#define BN_MP_SQR_C +#define BN_MP_SQRMOD_C +#define BN_MP_SQRT_C +#define BN_MP_SUB_C +#define BN_MP_SUB_D_C +#define BN_MP_SUBMOD_C +#define BN_MP_TO_SIGNED_BIN_C +#define BN_MP_TO_SIGNED_BIN_N_C +#define BN_MP_TO_UNSIGNED_BIN_C +#define BN_MP_TO_UNSIGNED_BIN_N_C +#define BN_MP_TOOM_MUL_C +#define BN_MP_TOOM_SQR_C +#define BN_MP_TORADIX_C +#define BN_MP_TORADIX_N_C +#define BN_MP_UNSIGNED_BIN_SIZE_C +#define BN_MP_XOR_C +#define BN_MP_ZERO_C +#define BN_PRIME_TAB_C +#define BN_REVERSE_C +#define BN_S_MP_ADD_C +#define BN_S_MP_EXPTMOD_C +#define BN_S_MP_MUL_DIGS_C +#define BN_S_MP_MUL_HIGH_DIGS_C +#define BN_S_MP_SQR_C +#define BN_S_MP_SUB_C +#define BNCORE_C +#endif + +#if defined(BN_ERROR_C) + #define BN_MP_ERROR_TO_STRING_C +#endif + +#if defined(BN_FAST_MP_INVMOD_C) + #define BN_MP_ISEVEN_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_COPY_C + #define BN_MP_MOD_C + #define BN_MP_SET_C + #define BN_MP_DIV_2_C + #define BN_MP_ISODD_C + #define BN_MP_SUB_C + #define BN_MP_CMP_C + #define BN_MP_ISZERO_C + #define BN_MP_CMP_D_C + #define BN_MP_ADD_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C) + #define BN_MP_GROW_C + #define BN_MP_RSHD_C + #define BN_MP_CLAMP_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_FAST_S_MP_MUL_DIGS_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_FAST_S_MP_SQR_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_2EXPT_C) + #define BN_MP_ZERO_C + #define BN_MP_GROW_C +#endif + +#if defined(BN_MP_ABS_C) + #define BN_MP_COPY_C +#endif + +#if defined(BN_MP_ADD_C) + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_ADD_D_C) + #define BN_MP_GROW_C + #define BN_MP_SUB_D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_ADDMOD_C) + #define BN_MP_INIT_C + #define BN_MP_ADD_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_AND_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_CLAMP_C) +#endif + +#if defined(BN_MP_CLEAR_C) +#endif + +#if defined(BN_MP_CLEAR_MULTI_C) + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_CMP_C) + #define BN_MP_CMP_MAG_C +#endif + +#if defined(BN_MP_CMP_D_C) +#endif + +#if defined(BN_MP_CMP_MAG_C) +#endif + +#if defined(BN_MP_CNT_LSB_C) + #define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_COPY_C) + #define BN_MP_GROW_C +#endif + +#if defined(BN_MP_COUNT_BITS_C) +#endif + +#if defined(BN_MP_DIV_C) + #define BN_MP_ISZERO_C + #define BN_MP_CMP_MAG_C + #define BN_MP_COPY_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_SET_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_ABS_C + #define BN_MP_MUL_2D_C + #define BN_MP_CMP_C + #define BN_MP_SUB_C + #define BN_MP_ADD_C + #define BN_MP_DIV_2D_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_INIT_C + #define BN_MP_INIT_COPY_C + #define BN_MP_LSHD_C + #define BN_MP_RSHD_C + #define BN_MP_MUL_D_C + #define BN_MP_CLAMP_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DIV_2_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_DIV_2D_C) + #define BN_MP_COPY_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_C + #define BN_MP_MOD_2D_C + #define BN_MP_CLEAR_C + #define BN_MP_RSHD_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_MP_DIV_3_C) + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DIV_D_C) + #define BN_MP_ISZERO_C + #define BN_MP_COPY_C + #define BN_MP_DIV_2D_C + #define BN_MP_DIV_3_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DR_IS_MODULUS_C) +#endif + +#if defined(BN_MP_DR_REDUCE_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_DR_SETUP_C) +#endif + +#if defined(BN_MP_EXCH_C) +#endif + +#if defined(BN_MP_EXPT_D_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_SET_C + #define BN_MP_SQR_C + #define BN_MP_CLEAR_C + #define BN_MP_MUL_C +#endif + +#if defined(BN_MP_EXPTMOD_C) + #define BN_MP_INIT_C + #define BN_MP_INVMOD_C + #define BN_MP_CLEAR_C + #define BN_MP_ABS_C + #define BN_MP_CLEAR_MULTI_C + #define BN_MP_REDUCE_IS_2K_L_C + #define BN_S_MP_EXPTMOD_C + #define BN_MP_DR_IS_MODULUS_C + #define BN_MP_REDUCE_IS_2K_C + #define BN_MP_ISODD_C + #define BN_MP_EXPTMOD_FAST_C +#endif + +#if defined(BN_MP_EXPTMOD_FAST_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_INIT_C + #define BN_MP_CLEAR_C + #define BN_MP_MONTGOMERY_SETUP_C + #define BN_FAST_MP_MONTGOMERY_REDUCE_C + #define BN_MP_MONTGOMERY_REDUCE_C + #define BN_MP_DR_SETUP_C + #define BN_MP_DR_REDUCE_C + #define BN_MP_REDUCE_2K_SETUP_C + #define BN_MP_REDUCE_2K_C + #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C + #define BN_MP_MULMOD_C + #define BN_MP_SET_C + #define BN_MP_MOD_C + #define BN_MP_COPY_C + #define BN_MP_SQR_C + #define BN_MP_MUL_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_MP_EXTEUCLID_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_SET_C + #define BN_MP_COPY_C + #define BN_MP_ISZERO_C + #define BN_MP_DIV_C + #define BN_MP_MUL_C + #define BN_MP_SUB_C + #define BN_MP_NEG_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_FREAD_C) + #define BN_MP_ZERO_C + #define BN_MP_S_RMAP_C + #define BN_MP_MUL_D_C + #define BN_MP_ADD_D_C + #define BN_MP_CMP_D_C +#endif + +#if defined(BN_MP_FWRITE_C) + #define BN_MP_RADIX_SIZE_C + #define BN_MP_TORADIX_C +#endif + +#if defined(BN_MP_GCD_C) + #define BN_MP_ISZERO_C + #define BN_MP_ABS_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_CNT_LSB_C + #define BN_MP_DIV_2D_C + #define BN_MP_CMP_MAG_C + #define BN_MP_EXCH_C + #define BN_S_MP_SUB_C + #define BN_MP_MUL_2D_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_GET_INT_C) +#endif + +#if defined(BN_MP_GROW_C) +#endif + +#if defined(BN_MP_INIT_C) +#endif + +#if defined(BN_MP_INIT_COPY_C) + #define BN_MP_COPY_C +#endif + +#if defined(BN_MP_INIT_MULTI_C) + #define BN_MP_ERR_C + #define BN_MP_INIT_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_INIT_SET_C) + #define BN_MP_INIT_C + #define BN_MP_SET_C +#endif + +#if defined(BN_MP_INIT_SET_INT_C) + #define BN_MP_INIT_C + #define BN_MP_SET_INT_C +#endif + +#if defined(BN_MP_INIT_SIZE_C) + #define BN_MP_INIT_C +#endif + +#if defined(BN_MP_INVMOD_C) + #define BN_MP_ISZERO_C + #define BN_MP_ISODD_C + #define BN_FAST_MP_INVMOD_C + #define BN_MP_INVMOD_SLOW_C +#endif + +#if defined(BN_MP_INVMOD_SLOW_C) + #define BN_MP_ISZERO_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_MOD_C + #define BN_MP_COPY_C + #define BN_MP_ISEVEN_C + #define BN_MP_SET_C + #define BN_MP_DIV_2_C + #define BN_MP_ISODD_C + #define BN_MP_ADD_C + #define BN_MP_SUB_C + #define BN_MP_CMP_C + #define BN_MP_CMP_D_C + #define BN_MP_CMP_MAG_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_IS_SQUARE_C) + #define BN_MP_MOD_D_C + #define BN_MP_INIT_SET_INT_C + #define BN_MP_MOD_C + #define BN_MP_GET_INT_C + #define BN_MP_SQRT_C + #define BN_MP_SQR_C + #define BN_MP_CMP_MAG_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_JACOBI_C) + #define BN_MP_CMP_D_C + #define BN_MP_ISZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_CNT_LSB_C + #define BN_MP_DIV_2D_C + #define BN_MP_MOD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_KARATSUBA_MUL_C) + #define BN_MP_MUL_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_SUB_C + #define BN_MP_ADD_C + #define BN_MP_LSHD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_KARATSUBA_SQR_C) + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_SQR_C + #define BN_MP_SUB_C + #define BN_S_MP_ADD_C + #define BN_MP_LSHD_C + #define BN_MP_ADD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_LCM_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_GCD_C + #define BN_MP_CMP_MAG_C + #define BN_MP_DIV_C + #define BN_MP_MUL_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_LSHD_C) + #define BN_MP_GROW_C + #define BN_MP_RSHD_C +#endif + +#if defined(BN_MP_MOD_C) + #define BN_MP_INIT_C + #define BN_MP_DIV_C + #define BN_MP_CLEAR_C + #define BN_MP_ADD_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_MP_MOD_2D_C) + #define BN_MP_ZERO_C + #define BN_MP_COPY_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MOD_D_C) + #define BN_MP_DIV_D_C +#endif + +#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_2EXPT_C + #define BN_MP_SET_C + #define BN_MP_MUL_2_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_MONTGOMERY_REDUCE_C) + #define BN_FAST_MP_MONTGOMERY_REDUCE_C + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C + #define BN_MP_RSHD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_MONTGOMERY_SETUP_C) +#endif + +#if defined(BN_MP_MUL_C) + #define BN_MP_TOOM_MUL_C + #define BN_MP_KARATSUBA_MUL_C + #define BN_FAST_S_MP_MUL_DIGS_C + #define BN_S_MP_MUL_C + #define BN_S_MP_MUL_DIGS_C +#endif + +#if defined(BN_MP_MUL_2_C) + #define BN_MP_GROW_C +#endif + +#if defined(BN_MP_MUL_2D_C) + #define BN_MP_COPY_C + #define BN_MP_GROW_C + #define BN_MP_LSHD_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MUL_D_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MULMOD_C) + #define BN_MP_INIT_C + #define BN_MP_MUL_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_N_ROOT_C) + #define BN_MP_INIT_C + #define BN_MP_SET_C + #define BN_MP_COPY_C + #define BN_MP_EXPT_D_C + #define BN_MP_MUL_C + #define BN_MP_SUB_C + #define BN_MP_MUL_D_C + #define BN_MP_DIV_C + #define BN_MP_CMP_C + #define BN_MP_SUB_D_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_NEG_C) + #define BN_MP_COPY_C + #define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_OR_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_FERMAT_C) + #define BN_MP_CMP_D_C + #define BN_MP_INIT_C + #define BN_MP_EXPTMOD_C + #define BN_MP_CMP_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_IS_DIVISIBLE_C) + #define BN_MP_MOD_D_C +#endif + +#if defined(BN_MP_PRIME_IS_PRIME_C) + #define BN_MP_CMP_D_C + #define BN_MP_PRIME_IS_DIVISIBLE_C + #define BN_MP_INIT_C + #define BN_MP_SET_C + #define BN_MP_PRIME_MILLER_RABIN_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_MILLER_RABIN_C) + #define BN_MP_CMP_D_C + #define BN_MP_INIT_COPY_C + #define BN_MP_SUB_D_C + #define BN_MP_CNT_LSB_C + #define BN_MP_DIV_2D_C + #define BN_MP_EXPTMOD_C + #define BN_MP_CMP_C + #define BN_MP_SQRMOD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_NEXT_PRIME_C) + #define BN_MP_CMP_D_C + #define BN_MP_SET_C + #define BN_MP_SUB_D_C + #define BN_MP_ISEVEN_C + #define BN_MP_MOD_D_C + #define BN_MP_INIT_C + #define BN_MP_ADD_D_C + #define BN_MP_PRIME_MILLER_RABIN_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C) +#endif + +#if defined(BN_MP_PRIME_RANDOM_EX_C) + #define BN_MP_READ_UNSIGNED_BIN_C + #define BN_MP_PRIME_IS_PRIME_C + #define BN_MP_SUB_D_C + #define BN_MP_DIV_2_C + #define BN_MP_MUL_2_C + #define BN_MP_ADD_D_C +#endif + +#if defined(BN_MP_RADIX_SIZE_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_INIT_COPY_C + #define BN_MP_ISZERO_C + #define BN_MP_DIV_D_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_RADIX_SMAP_C) + #define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_RAND_C) + #define BN_MP_ZERO_C + #define BN_MP_ADD_D_C + #define BN_MP_LSHD_C +#endif + +#if defined(BN_MP_READ_RADIX_C) + #define BN_MP_ZERO_C + #define BN_MP_S_RMAP_C + #define BN_MP_RADIX_SMAP_C + #define BN_MP_MUL_D_C + #define BN_MP_ADD_D_C + #define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_READ_SIGNED_BIN_C) + #define BN_MP_READ_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_READ_UNSIGNED_BIN_C) + #define BN_MP_GROW_C + #define BN_MP_ZERO_C + #define BN_MP_MUL_2D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_REDUCE_C) + #define BN_MP_REDUCE_SETUP_C + #define BN_MP_INIT_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_MUL_C + #define BN_S_MP_MUL_HIGH_DIGS_C + #define BN_FAST_S_MP_MUL_HIGH_DIGS_C + #define BN_MP_MOD_2D_C + #define BN_S_MP_MUL_DIGS_C + #define BN_MP_SUB_C + #define BN_MP_CMP_D_C + #define BN_MP_SET_C + #define BN_MP_LSHD_C + #define BN_MP_ADD_C + #define BN_MP_CMP_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_C) + #define BN_MP_INIT_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_DIV_2D_C + #define BN_MP_MUL_D_C + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_L_C) + #define BN_MP_INIT_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_DIV_2D_C + #define BN_MP_MUL_C + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_SETUP_C) + #define BN_MP_INIT_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_2EXPT_C + #define BN_MP_CLEAR_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_REDUCE_2K_SETUP_L_C) + #define BN_MP_INIT_C + #define BN_MP_2EXPT_C + #define BN_MP_COUNT_BITS_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_IS_2K_C) + #define BN_MP_REDUCE_2K_C + #define BN_MP_COUNT_BITS_C +#endif + +#if defined(BN_MP_REDUCE_IS_2K_L_C) +#endif + +#if defined(BN_MP_REDUCE_SETUP_C) + #define BN_MP_2EXPT_C + #define BN_MP_DIV_C +#endif + +#if defined(BN_MP_RSHD_C) + #define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_SET_C) + #define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_SET_INT_C) + #define BN_MP_ZERO_C + #define BN_MP_MUL_2D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_SHRINK_C) +#endif + +#if defined(BN_MP_SIGNED_BIN_SIZE_C) + #define BN_MP_UNSIGNED_BIN_SIZE_C +#endif + +#if defined(BN_MP_SQR_C) + #define BN_MP_TOOM_SQR_C + #define BN_MP_KARATSUBA_SQR_C + #define BN_FAST_S_MP_SQR_C + #define BN_S_MP_SQR_C +#endif + +#if defined(BN_MP_SQRMOD_C) + #define BN_MP_INIT_C + #define BN_MP_SQR_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_SQRT_C) + #define BN_MP_N_ROOT_C + #define BN_MP_ISZERO_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_DIV_C + #define BN_MP_ADD_C + #define BN_MP_DIV_2_C + #define BN_MP_CMP_MAG_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_SUB_C) + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_SUB_D_C) + #define BN_MP_GROW_C + #define BN_MP_ADD_D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_SUBMOD_C) + #define BN_MP_INIT_C + #define BN_MP_SUB_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_TO_SIGNED_BIN_C) + #define BN_MP_TO_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_TO_SIGNED_BIN_N_C) + #define BN_MP_SIGNED_BIN_SIZE_C + #define BN_MP_TO_SIGNED_BIN_C +#endif + +#if defined(BN_MP_TO_UNSIGNED_BIN_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_ISZERO_C + #define BN_MP_DIV_2D_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_TO_UNSIGNED_BIN_N_C) + #define BN_MP_UNSIGNED_BIN_SIZE_C + #define BN_MP_TO_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_TOOM_MUL_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_MOD_2D_C + #define BN_MP_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_MUL_C + #define BN_MP_MUL_2_C + #define BN_MP_ADD_C + #define BN_MP_SUB_C + #define BN_MP_DIV_2_C + #define BN_MP_MUL_2D_C + #define BN_MP_MUL_D_C + #define BN_MP_DIV_3_C + #define BN_MP_LSHD_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_TOOM_SQR_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_MOD_2D_C + #define BN_MP_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_SQR_C + #define BN_MP_MUL_2_C + #define BN_MP_ADD_C + #define BN_MP_SUB_C + #define BN_MP_DIV_2_C + #define BN_MP_MUL_2D_C + #define BN_MP_MUL_D_C + #define BN_MP_DIV_3_C + #define BN_MP_LSHD_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_TORADIX_C) + #define BN_MP_ISZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_DIV_D_C + #define BN_MP_CLEAR_C + #define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_TORADIX_N_C) + #define BN_MP_ISZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_DIV_D_C + #define BN_MP_CLEAR_C + #define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_UNSIGNED_BIN_SIZE_C) + #define BN_MP_COUNT_BITS_C +#endif + +#if defined(BN_MP_XOR_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_ZERO_C) +#endif + +#if defined(BN_PRIME_TAB_C) +#endif + +#if defined(BN_REVERSE_C) +#endif + +#if defined(BN_S_MP_ADD_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_S_MP_EXPTMOD_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_INIT_C + #define BN_MP_CLEAR_C + #define BN_MP_REDUCE_SETUP_C + #define BN_MP_REDUCE_C + #define BN_MP_REDUCE_2K_SETUP_L_C + #define BN_MP_REDUCE_2K_L_C + #define BN_MP_MOD_C + #define BN_MP_COPY_C + #define BN_MP_SQR_C + #define BN_MP_MUL_C + #define BN_MP_SET_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_S_MP_MUL_DIGS_C) + #define BN_FAST_S_MP_MUL_DIGS_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_MUL_HIGH_DIGS_C) + #define BN_FAST_S_MP_MUL_HIGH_DIGS_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_SQR_C) + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_SUB_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BNCORE_C) +#endif + +#ifdef LTM3 +#define LTM_LAST +#endif +#include +#include +#else +#define LTM_LAST +#endif + +/* $Source: /cvs/libtom/libtommath/tommath_class.h,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2005/07/28 11:59:32 $ */ diff --git a/lib/hcrypto/libtommath/tommath_superclass.h b/lib/hcrypto/libtommath/tommath_superclass.h new file mode 100644 index 000000000..2fdebe683 --- /dev/null +++ b/lib/hcrypto/libtommath/tommath_superclass.h @@ -0,0 +1,76 @@ +/* super class file for PK algos */ + +/* default ... include all MPI */ +#define LTM_ALL + +/* RSA only (does not support DH/DSA/ECC) */ +/* #define SC_RSA_1 */ + +/* For reference.... On an Athlon64 optimizing for speed... + + LTM's mpi.o with all functions [striped] is 142KiB in size. + +*/ + +/* Works for RSA only, mpi.o is 68KiB */ +#ifdef SC_RSA_1 + #define BN_MP_SHRINK_C + #define BN_MP_LCM_C + #define BN_MP_PRIME_RANDOM_EX_C + #define BN_MP_INVMOD_C + #define BN_MP_GCD_C + #define BN_MP_MOD_C + #define BN_MP_MULMOD_C + #define BN_MP_ADDMOD_C + #define BN_MP_EXPTMOD_C + #define BN_MP_SET_INT_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_CLEAR_MULTI_C + #define BN_MP_UNSIGNED_BIN_SIZE_C + #define BN_MP_TO_UNSIGNED_BIN_C + #define BN_MP_MOD_D_C + #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C + #define BN_REVERSE_C + #define BN_PRIME_TAB_C + + /* other modifiers */ + #define BN_MP_DIV_SMALL /* Slower division, not critical */ + + /* here we are on the last pass so we turn things off. The functions classes are still there + * but we remove them specifically from the build. This also invokes tweaks in functions + * like removing support for even moduli, etc... + */ +#ifdef LTM_LAST + #undef BN_MP_TOOM_MUL_C + #undef BN_MP_TOOM_SQR_C + #undef BN_MP_KARATSUBA_MUL_C + #undef BN_MP_KARATSUBA_SQR_C + #undef BN_MP_REDUCE_C + #undef BN_MP_REDUCE_SETUP_C + #undef BN_MP_DR_IS_MODULUS_C + #undef BN_MP_DR_SETUP_C + #undef BN_MP_DR_REDUCE_C + #undef BN_MP_REDUCE_IS_2K_C + #undef BN_MP_REDUCE_2K_SETUP_C + #undef BN_MP_REDUCE_2K_C + #undef BN_S_MP_EXPTMOD_C + #undef BN_MP_DIV_3_C + #undef BN_S_MP_MUL_HIGH_DIGS_C + #undef BN_FAST_S_MP_MUL_HIGH_DIGS_C + #undef BN_FAST_MP_INVMOD_C + + /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold + * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] + * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without + * trouble. + */ + #undef BN_S_MP_MUL_DIGS_C + #undef BN_S_MP_SQR_C + #undef BN_MP_MONTGOMERY_REDUCE_C +#endif + +#endif + +/* $Source: /cvs/libtom/libtommath/tommath_superclass.h,v $ */ +/* $Revision: 1.3 $ */ +/* $Date: 2005/05/14 13:29:17 $ */