From d20a448b3bb3b49e246347d2e5b71685b8c484f2 Mon Sep 17 00:00:00 2001 From: hasufell Date: Sat, 24 May 2014 23:11:41 +0200 Subject: [PATCH] ALL: rm libtompoly/libtommath --- external/libtommath-0.42.0/LICENSE | 4 - external/libtommath-0.42.0/bn.tex | 1835 --- external/libtommath-0.42.0/bn_error.c | 47 - .../libtommath-0.42.0/bn_fast_mp_invmod.c | 148 - .../bn_fast_mp_montgomery_reduce.c | 172 - .../libtommath-0.42.0/bn_fast_s_mp_mul_digs.c | 107 - .../bn_fast_s_mp_mul_high_digs.c | 98 - external/libtommath-0.42.0/bn_fast_s_mp_sqr.c | 114 - external/libtommath-0.42.0/bn_mp_2expt.c | 48 - external/libtommath-0.42.0/bn_mp_abs.c | 43 - external/libtommath-0.42.0/bn_mp_add.c | 53 - external/libtommath-0.42.0/bn_mp_add_d.c | 112 - external/libtommath-0.42.0/bn_mp_addmod.c | 41 - external/libtommath-0.42.0/bn_mp_and.c | 57 - external/libtommath-0.42.0/bn_mp_clamp.c | 44 - external/libtommath-0.42.0/bn_mp_clear.c | 44 - .../libtommath-0.42.0/bn_mp_clear_multi.c | 34 - external/libtommath-0.42.0/bn_mp_cmp.c | 43 - external/libtommath-0.42.0/bn_mp_cmp_d.c | 44 - external/libtommath-0.42.0/bn_mp_cmp_mag.c | 55 - external/libtommath-0.42.0/bn_mp_cnt_lsb.c | 53 - external/libtommath-0.42.0/bn_mp_copy.c | 68 - external/libtommath-0.42.0/bn_mp_count_bits.c | 45 - external/libtommath-0.42.0/bn_mp_div.c | 292 - external/libtommath-0.42.0/bn_mp_div_2.c | 68 - external/libtommath-0.42.0/bn_mp_div_2d.c | 97 - external/libtommath-0.42.0/bn_mp_div_3.c | 79 - external/libtommath-0.42.0/bn_mp_div_d.c | 115 - .../libtommath-0.42.0/bn_mp_dr_is_modulus.c | 43 - external/libtommath-0.42.0/bn_mp_dr_reduce.c | 94 - external/libtommath-0.42.0/bn_mp_dr_setup.c | 32 - external/libtommath-0.42.0/bn_mp_exch.c | 34 - external/libtommath-0.42.0/bn_mp_expt_d.c | 57 - external/libtommath-0.42.0/bn_mp_exptmod.c | 112 - .../libtommath-0.42.0/bn_mp_exptmod_fast.c | 321 - external/libtommath-0.42.0/bn_mp_exteuclid.c | 82 - external/libtommath-0.42.0/bn_mp_fread.c | 67 - external/libtommath-0.42.0/bn_mp_fwrite.c | 52 - external/libtommath-0.42.0/bn_mp_gcd.c | 105 - external/libtommath-0.42.0/bn_mp_get_int.c | 45 - external/libtommath-0.42.0/bn_mp_grow.c | 57 - external/libtommath-0.42.0/bn_mp_init.c | 46 - external/libtommath-0.42.0/bn_mp_init_copy.c | 32 - external/libtommath-0.42.0/bn_mp_init_multi.c | 59 - external/libtommath-0.42.0/bn_mp_init_set.c | 32 - .../libtommath-0.42.0/bn_mp_init_set_int.c | 31 - external/libtommath-0.42.0/bn_mp_init_size.c | 48 - external/libtommath-0.42.0/bn_mp_invmod.c | 43 - .../libtommath-0.42.0/bn_mp_invmod_slow.c | 175 - external/libtommath-0.42.0/bn_mp_is_square.c | 109 - external/libtommath-0.42.0/bn_mp_jacobi.c | 105 - .../libtommath-0.42.0/bn_mp_karatsuba_mul.c | 167 - .../libtommath-0.42.0/bn_mp_karatsuba_sqr.c | 121 - external/libtommath-0.42.0/bn_mp_lcm.c | 60 - external/libtommath-0.42.0/bn_mp_lshd.c | 67 - external/libtommath-0.42.0/bn_mp_mod.c | 48 - external/libtommath-0.42.0/bn_mp_mod_2d.c | 55 - external/libtommath-0.42.0/bn_mp_mod_d.c | 27 - .../bn_mp_montgomery_calc_normalization.c | 59 - .../bn_mp_montgomery_reduce.c | 118 - .../bn_mp_montgomery_setup.c | 59 - external/libtommath-0.42.0/bn_mp_mul.c | 66 - external/libtommath-0.42.0/bn_mp_mul_2.c | 82 - external/libtommath-0.42.0/bn_mp_mul_2d.c | 85 - external/libtommath-0.42.0/bn_mp_mul_d.c | 79 - external/libtommath-0.42.0/bn_mp_mulmod.c | 40 - external/libtommath-0.42.0/bn_mp_n_root.c | 132 - external/libtommath-0.42.0/bn_mp_neg.c | 40 - external/libtommath-0.42.0/bn_mp_or.c | 50 - .../libtommath-0.42.0/bn_mp_prime_fermat.c | 62 - .../bn_mp_prime_is_divisible.c | 50 - .../libtommath-0.42.0/bn_mp_prime_is_prime.c | 83 - .../bn_mp_prime_miller_rabin.c | 103 - .../bn_mp_prime_next_prime.c | 170 - .../bn_mp_prime_rabin_miller_trials.c | 52 - .../libtommath-0.42.0/bn_mp_prime_random_ex.c | 125 - external/libtommath-0.42.0/bn_mp_radix_size.c | 78 - external/libtommath-0.42.0/bn_mp_radix_smap.c | 24 - external/libtommath-0.42.0/bn_mp_rand.c | 55 - external/libtommath-0.42.0/bn_mp_read_radix.c | 85 - .../libtommath-0.42.0/bn_mp_read_signed_bin.c | 41 - .../bn_mp_read_unsigned_bin.c | 55 - external/libtommath-0.42.0/bn_mp_reduce.c | 100 - external/libtommath-0.42.0/bn_mp_reduce_2k.c | 61 - .../libtommath-0.42.0/bn_mp_reduce_2k_l.c | 62 - .../libtommath-0.42.0/bn_mp_reduce_2k_setup.c | 47 - .../bn_mp_reduce_2k_setup_l.c | 44 - .../libtommath-0.42.0/bn_mp_reduce_is_2k.c | 52 - .../libtommath-0.42.0/bn_mp_reduce_is_2k_l.c | 44 - .../libtommath-0.42.0/bn_mp_reduce_setup.c | 34 - external/libtommath-0.42.0/bn_mp_rshd.c | 72 - external/libtommath-0.42.0/bn_mp_set.c | 29 - external/libtommath-0.42.0/bn_mp_set_int.c | 48 - external/libtommath-0.42.0/bn_mp_shrink.c | 40 - .../libtommath-0.42.0/bn_mp_signed_bin_size.c | 27 - external/libtommath-0.42.0/bn_mp_sqr.c | 58 - external/libtommath-0.42.0/bn_mp_sqrmod.c | 41 - external/libtommath-0.42.0/bn_mp_sqrt.c | 81 - external/libtommath-0.42.0/bn_mp_sub.c | 59 - external/libtommath-0.42.0/bn_mp_sub_d.c | 93 - external/libtommath-0.42.0/bn_mp_submod.c | 42 - .../libtommath-0.42.0/bn_mp_to_signed_bin.c | 33 - .../libtommath-0.42.0/bn_mp_to_signed_bin_n.c | 31 - .../libtommath-0.42.0/bn_mp_to_unsigned_bin.c | 48 - .../bn_mp_to_unsigned_bin_n.c | 31 - external/libtommath-0.42.0/bn_mp_toom_mul.c | 284 - external/libtommath-0.42.0/bn_mp_toom_sqr.c | 226 - external/libtommath-0.42.0/bn_mp_toradix.c | 75 - external/libtommath-0.42.0/bn_mp_toradix_n.c | 88 - .../bn_mp_unsigned_bin_size.c | 28 - external/libtommath-0.42.0/bn_mp_xor.c | 51 - external/libtommath-0.42.0/bn_mp_zero.c | 36 - external/libtommath-0.42.0/bn_prime_tab.c | 61 - external/libtommath-0.42.0/bn_reverse.c | 39 - external/libtommath-0.42.0/bn_s_mp_add.c | 109 - external/libtommath-0.42.0/bn_s_mp_exptmod.c | 252 - external/libtommath-0.42.0/bn_s_mp_mul_digs.c | 90 - .../libtommath-0.42.0/bn_s_mp_mul_high_digs.c | 81 - external/libtommath-0.42.0/bn_s_mp_sqr.c | 84 - external/libtommath-0.42.0/bn_s_mp_sub.c | 89 - external/libtommath-0.42.0/bncore.c | 36 - external/libtommath-0.42.0/booker.pl | 265 - external/libtommath-0.42.0/callgraph.txt | 11913 ---------------- external/libtommath-0.42.0/changes.txt | 403 - external/libtommath-0.42.0/demo/demo.c | 740 - external/libtommath-0.42.0/demo/timing.c | 319 - external/libtommath-0.42.0/dep.pl | 123 - external/libtommath-0.42.0/etc/2kprime.1 | 2 - external/libtommath-0.42.0/etc/2kprime.c | 84 - external/libtommath-0.42.0/etc/drprime.c | 64 - external/libtommath-0.42.0/etc/drprimes.28 | 25 - external/libtommath-0.42.0/etc/drprimes.txt | 9 - external/libtommath-0.42.0/etc/makefile | 50 - external/libtommath-0.42.0/etc/makefile.icc | 67 - external/libtommath-0.42.0/etc/makefile.msvc | 23 - external/libtommath-0.42.0/etc/mersenne.c | 144 - external/libtommath-0.42.0/etc/mont.c | 50 - external/libtommath-0.42.0/etc/pprime.c | 400 - external/libtommath-0.42.0/etc/prime.1024 | 414 - external/libtommath-0.42.0/etc/prime.512 | 205 - external/libtommath-0.42.0/etc/timer.asm | 37 - external/libtommath-0.42.0/etc/tune.c | 142 - external/libtommath-0.42.0/gen.pl | 17 - external/libtommath-0.42.0/libtommath.dsp | 572 - .../libtommath-0.42.0/libtommath_VS2005.sln | 20 - .../libtommath_VS2005.vcproj | 2803 ---- .../libtommath-0.42.0/libtommath_VS2008.sln | 20 - .../libtommath_VS2008.vcproj | 2805 ---- external/libtommath-0.42.0/logs/README | 13 - external/libtommath-0.42.0/logs/add.log | 16 - external/libtommath-0.42.0/logs/addsub.png | Bin 6254 -> 0 bytes external/libtommath-0.42.0/logs/expt.log | 7 - external/libtommath-0.42.0/logs/expt.png | Bin 6605 -> 0 bytes external/libtommath-0.42.0/logs/expt_2k.log | 5 - external/libtommath-0.42.0/logs/expt_2kl.log | 4 - external/libtommath-0.42.0/logs/expt_dr.log | 7 - external/libtommath-0.42.0/logs/graphs.dem | 17 - external/libtommath-0.42.0/logs/index.html | 27 - external/libtommath-0.42.0/logs/invmod.log | 0 external/libtommath-0.42.0/logs/invmod.png | Bin 4918 -> 0 bytes external/libtommath-0.42.0/logs/mult.log | 84 - external/libtommath-0.42.0/logs/mult.png | Bin 6770 -> 0 bytes external/libtommath-0.42.0/logs/mult_kara.log | 84 - external/libtommath-0.42.0/logs/sqr.log | 84 - external/libtommath-0.42.0/logs/sqr_kara.log | 84 - external/libtommath-0.42.0/logs/sub.log | 16 - external/libtommath-0.42.0/makefile | 186 - external/libtommath-0.42.0/makefile.bcc | 44 - .../libtommath-0.42.0/makefile.cygwin_dll | 55 - external/libtommath-0.42.0/makefile.icc | 116 - external/libtommath-0.42.0/makefile.msvc | 40 - external/libtommath-0.42.0/makefile.shared | 102 - external/libtommath-0.42.0/mess.sh | 4 - external/libtommath-0.42.0/mtest/logtab.h | 24 - external/libtommath-0.42.0/mtest/mpi-config.h | 90 - external/libtommath-0.42.0/mtest/mpi-types.h | 20 - external/libtommath-0.42.0/mtest/mpi.c | 3985 ------ external/libtommath-0.42.0/mtest/mpi.h | 231 - external/libtommath-0.42.0/mtest/mtest.c | 308 - .../libtommath-0.42.0/pics/design_process.sxd | Bin 6950 -> 0 bytes .../libtommath-0.42.0/pics/design_process.tif | Bin 79042 -> 0 bytes .../libtommath-0.42.0/pics/expt_state.sxd | Bin 6869 -> 0 bytes .../libtommath-0.42.0/pics/expt_state.tif | Bin 87542 -> 0 bytes external/libtommath-0.42.0/pics/makefile | 35 - external/libtommath-0.42.0/pics/primality.tif | Bin 85514 -> 0 bytes external/libtommath-0.42.0/pics/radix.sxd | Bin 6181 -> 0 bytes .../libtommath-0.42.0/pics/sliding_window.sxd | Bin 6787 -> 0 bytes .../libtommath-0.42.0/pics/sliding_window.tif | Bin 53880 -> 0 bytes external/libtommath-0.42.0/poster.out | 0 external/libtommath-0.42.0/poster.tex | 35 - external/libtommath-0.42.0/pre_gen/mpi.c | 9524 ------------ external/libtommath-0.42.0/pretty.build | 66 - external/libtommath-0.42.0/tombc/grammar.txt | 35 - external/libtommath-0.42.0/tommath.h | 584 - external/libtommath-0.42.0/tommath.out | 139 - external/libtommath-0.42.0/tommath.src | 6350 -------- external/libtommath-0.42.0/tommath_class.h | 999 -- .../libtommath-0.42.0/tommath_superclass.h | 76 - external/libtompoly-0.04/LICENSE | 4 - external/libtompoly-0.04/changes.txt | 24 - external/libtompoly-0.04/demo/demo.c | 216 - external/libtompoly-0.04/makefile | 56 - external/libtompoly-0.04/makefile.msvc | 17 - external/libtompoly-0.04/pb.pdf | Bin 193637 -> 0 bytes external/libtompoly-0.04/pb.tex | 433 - external/libtompoly-0.04/pb_add.c | 73 - external/libtompoly-0.04/pb_addmod.c | 35 - external/libtompoly-0.04/pb_clamp.c | 21 - external/libtompoly-0.04/pb_clear.c | 32 - external/libtompoly-0.04/pb_clear_multi.c | 25 - external/libtompoly-0.04/pb_cmp.c | 32 - external/libtompoly-0.04/pb_copy.c | 51 - external/libtompoly-0.04/pb_div.c | 135 - external/libtompoly-0.04/pb_exch.c | 20 - external/libtompoly-0.04/pb_exptmod.c | 186 - external/libtompoly-0.04/pb_exteuclid.c | 74 - external/libtompoly-0.04/pb_gcd.c | 69 - external/libtompoly-0.04/pb_grow.c | 46 - external/libtompoly-0.04/pb_init.c | 49 - external/libtompoly-0.04/pb_init_copy.c | 21 - external/libtompoly-0.04/pb_init_multi.c | 50 - external/libtompoly-0.04/pb_init_size.c | 58 - external/libtompoly-0.04/pb_invmod.c | 33 - external/libtompoly-0.04/pb_isirreduc.c | 59 - external/libtompoly-0.04/pb_lshd.c | 42 - external/libtompoly-0.04/pb_mod.c | 19 - external/libtompoly-0.04/pb_monic.c | 60 - external/libtompoly-0.04/pb_mul.c | 62 - external/libtompoly-0.04/pb_mulmod.c | 35 - external/libtompoly-0.04/pb_rawsize.c | 32 - external/libtompoly-0.04/pb_readraw.c | 55 - external/libtompoly-0.04/pb_rshd.c | 38 - external/libtompoly-0.04/pb_shrink.c | 44 - external/libtompoly-0.04/pb_sub.c | 86 - external/libtompoly-0.04/pb_submod.c | 35 - external/libtompoly-0.04/pb_toraw.c | 42 - external/libtompoly-0.04/pb_zero.c | 23 - external/libtompoly-0.04/tompoly.h | 115 - 238 files changed, 58604 deletions(-) delete mode 100755 external/libtommath-0.42.0/LICENSE delete mode 100755 external/libtommath-0.42.0/bn.tex delete mode 100755 external/libtommath-0.42.0/bn_error.c delete mode 100755 external/libtommath-0.42.0/bn_fast_mp_invmod.c delete mode 100755 external/libtommath-0.42.0/bn_fast_mp_montgomery_reduce.c delete mode 100755 external/libtommath-0.42.0/bn_fast_s_mp_mul_digs.c delete mode 100755 external/libtommath-0.42.0/bn_fast_s_mp_mul_high_digs.c delete mode 100755 external/libtommath-0.42.0/bn_fast_s_mp_sqr.c delete mode 100755 external/libtommath-0.42.0/bn_mp_2expt.c delete mode 100755 external/libtommath-0.42.0/bn_mp_abs.c delete mode 100755 external/libtommath-0.42.0/bn_mp_add.c delete mode 100755 external/libtommath-0.42.0/bn_mp_add_d.c delete mode 100755 external/libtommath-0.42.0/bn_mp_addmod.c delete mode 100755 external/libtommath-0.42.0/bn_mp_and.c delete mode 100755 external/libtommath-0.42.0/bn_mp_clamp.c delete mode 100755 external/libtommath-0.42.0/bn_mp_clear.c delete mode 100755 external/libtommath-0.42.0/bn_mp_clear_multi.c delete mode 100755 external/libtommath-0.42.0/bn_mp_cmp.c delete mode 100755 external/libtommath-0.42.0/bn_mp_cmp_d.c delete mode 100755 external/libtommath-0.42.0/bn_mp_cmp_mag.c delete mode 100755 external/libtommath-0.42.0/bn_mp_cnt_lsb.c delete mode 100755 external/libtommath-0.42.0/bn_mp_copy.c delete mode 100755 external/libtommath-0.42.0/bn_mp_count_bits.c delete mode 100755 external/libtommath-0.42.0/bn_mp_div.c delete mode 100755 external/libtommath-0.42.0/bn_mp_div_2.c delete mode 100755 external/libtommath-0.42.0/bn_mp_div_2d.c delete mode 100755 external/libtommath-0.42.0/bn_mp_div_3.c delete mode 100755 external/libtommath-0.42.0/bn_mp_div_d.c delete mode 100755 external/libtommath-0.42.0/bn_mp_dr_is_modulus.c delete mode 100755 external/libtommath-0.42.0/bn_mp_dr_reduce.c delete mode 100755 external/libtommath-0.42.0/bn_mp_dr_setup.c delete mode 100755 external/libtommath-0.42.0/bn_mp_exch.c delete mode 100755 external/libtommath-0.42.0/bn_mp_expt_d.c delete mode 100755 external/libtommath-0.42.0/bn_mp_exptmod.c delete mode 100755 external/libtommath-0.42.0/bn_mp_exptmod_fast.c delete mode 100755 external/libtommath-0.42.0/bn_mp_exteuclid.c delete mode 100755 external/libtommath-0.42.0/bn_mp_fread.c delete mode 100755 external/libtommath-0.42.0/bn_mp_fwrite.c delete mode 100755 external/libtommath-0.42.0/bn_mp_gcd.c delete mode 100755 external/libtommath-0.42.0/bn_mp_get_int.c delete mode 100755 external/libtommath-0.42.0/bn_mp_grow.c delete mode 100755 external/libtommath-0.42.0/bn_mp_init.c delete mode 100755 external/libtommath-0.42.0/bn_mp_init_copy.c delete mode 100755 external/libtommath-0.42.0/bn_mp_init_multi.c delete mode 100755 external/libtommath-0.42.0/bn_mp_init_set.c delete mode 100755 external/libtommath-0.42.0/bn_mp_init_set_int.c delete mode 100755 external/libtommath-0.42.0/bn_mp_init_size.c delete mode 100755 external/libtommath-0.42.0/bn_mp_invmod.c delete mode 100755 external/libtommath-0.42.0/bn_mp_invmod_slow.c delete mode 100755 external/libtommath-0.42.0/bn_mp_is_square.c delete mode 100755 external/libtommath-0.42.0/bn_mp_jacobi.c delete mode 100755 external/libtommath-0.42.0/bn_mp_karatsuba_mul.c delete mode 100755 external/libtommath-0.42.0/bn_mp_karatsuba_sqr.c delete mode 100755 external/libtommath-0.42.0/bn_mp_lcm.c delete mode 100755 external/libtommath-0.42.0/bn_mp_lshd.c delete mode 100755 external/libtommath-0.42.0/bn_mp_mod.c delete mode 100755 external/libtommath-0.42.0/bn_mp_mod_2d.c delete mode 100755 external/libtommath-0.42.0/bn_mp_mod_d.c delete mode 100755 external/libtommath-0.42.0/bn_mp_montgomery_calc_normalization.c delete mode 100755 external/libtommath-0.42.0/bn_mp_montgomery_reduce.c delete mode 100755 external/libtommath-0.42.0/bn_mp_montgomery_setup.c delete mode 100755 external/libtommath-0.42.0/bn_mp_mul.c delete mode 100755 external/libtommath-0.42.0/bn_mp_mul_2.c delete mode 100755 external/libtommath-0.42.0/bn_mp_mul_2d.c delete mode 100755 external/libtommath-0.42.0/bn_mp_mul_d.c delete mode 100755 external/libtommath-0.42.0/bn_mp_mulmod.c delete mode 100755 external/libtommath-0.42.0/bn_mp_n_root.c delete mode 100755 external/libtommath-0.42.0/bn_mp_neg.c delete mode 100755 external/libtommath-0.42.0/bn_mp_or.c delete mode 100755 external/libtommath-0.42.0/bn_mp_prime_fermat.c delete mode 100755 external/libtommath-0.42.0/bn_mp_prime_is_divisible.c delete mode 100755 external/libtommath-0.42.0/bn_mp_prime_is_prime.c delete mode 100755 external/libtommath-0.42.0/bn_mp_prime_miller_rabin.c delete mode 100755 external/libtommath-0.42.0/bn_mp_prime_next_prime.c delete mode 100755 external/libtommath-0.42.0/bn_mp_prime_rabin_miller_trials.c delete mode 100755 external/libtommath-0.42.0/bn_mp_prime_random_ex.c delete mode 100755 external/libtommath-0.42.0/bn_mp_radix_size.c delete mode 100755 external/libtommath-0.42.0/bn_mp_radix_smap.c delete mode 100755 external/libtommath-0.42.0/bn_mp_rand.c delete mode 100755 external/libtommath-0.42.0/bn_mp_read_radix.c delete mode 100755 external/libtommath-0.42.0/bn_mp_read_signed_bin.c delete mode 100755 external/libtommath-0.42.0/bn_mp_read_unsigned_bin.c delete mode 100755 external/libtommath-0.42.0/bn_mp_reduce.c delete mode 100755 external/libtommath-0.42.0/bn_mp_reduce_2k.c delete mode 100755 external/libtommath-0.42.0/bn_mp_reduce_2k_l.c delete mode 100755 external/libtommath-0.42.0/bn_mp_reduce_2k_setup.c delete mode 100755 external/libtommath-0.42.0/bn_mp_reduce_2k_setup_l.c delete mode 100755 external/libtommath-0.42.0/bn_mp_reduce_is_2k.c delete mode 100755 external/libtommath-0.42.0/bn_mp_reduce_is_2k_l.c delete mode 100755 external/libtommath-0.42.0/bn_mp_reduce_setup.c delete mode 100755 external/libtommath-0.42.0/bn_mp_rshd.c delete mode 100755 external/libtommath-0.42.0/bn_mp_set.c delete mode 100755 external/libtommath-0.42.0/bn_mp_set_int.c delete mode 100755 external/libtommath-0.42.0/bn_mp_shrink.c delete mode 100755 external/libtommath-0.42.0/bn_mp_signed_bin_size.c delete mode 100755 external/libtommath-0.42.0/bn_mp_sqr.c delete mode 100755 external/libtommath-0.42.0/bn_mp_sqrmod.c delete mode 100755 external/libtommath-0.42.0/bn_mp_sqrt.c delete mode 100755 external/libtommath-0.42.0/bn_mp_sub.c delete mode 100755 external/libtommath-0.42.0/bn_mp_sub_d.c delete mode 100755 external/libtommath-0.42.0/bn_mp_submod.c delete mode 100755 external/libtommath-0.42.0/bn_mp_to_signed_bin.c delete mode 100755 external/libtommath-0.42.0/bn_mp_to_signed_bin_n.c delete mode 100755 external/libtommath-0.42.0/bn_mp_to_unsigned_bin.c delete mode 100755 external/libtommath-0.42.0/bn_mp_to_unsigned_bin_n.c delete mode 100755 external/libtommath-0.42.0/bn_mp_toom_mul.c delete mode 100755 external/libtommath-0.42.0/bn_mp_toom_sqr.c delete mode 100755 external/libtommath-0.42.0/bn_mp_toradix.c delete mode 100755 external/libtommath-0.42.0/bn_mp_toradix_n.c delete mode 100755 external/libtommath-0.42.0/bn_mp_unsigned_bin_size.c delete mode 100755 external/libtommath-0.42.0/bn_mp_xor.c delete mode 100755 external/libtommath-0.42.0/bn_mp_zero.c delete mode 100755 external/libtommath-0.42.0/bn_prime_tab.c delete mode 100755 external/libtommath-0.42.0/bn_reverse.c delete mode 100755 external/libtommath-0.42.0/bn_s_mp_add.c delete mode 100755 external/libtommath-0.42.0/bn_s_mp_exptmod.c delete mode 100755 external/libtommath-0.42.0/bn_s_mp_mul_digs.c delete mode 100755 external/libtommath-0.42.0/bn_s_mp_mul_high_digs.c delete mode 100755 external/libtommath-0.42.0/bn_s_mp_sqr.c delete mode 100755 external/libtommath-0.42.0/bn_s_mp_sub.c delete mode 100755 external/libtommath-0.42.0/bncore.c delete mode 100755 external/libtommath-0.42.0/booker.pl delete mode 100755 external/libtommath-0.42.0/callgraph.txt delete mode 100755 external/libtommath-0.42.0/changes.txt delete mode 100755 external/libtommath-0.42.0/demo/demo.c delete mode 100755 external/libtommath-0.42.0/demo/timing.c delete mode 100755 external/libtommath-0.42.0/dep.pl delete mode 100755 external/libtommath-0.42.0/etc/2kprime.1 delete mode 100755 external/libtommath-0.42.0/etc/2kprime.c delete mode 100755 external/libtommath-0.42.0/etc/drprime.c delete mode 100755 external/libtommath-0.42.0/etc/drprimes.28 delete mode 100755 external/libtommath-0.42.0/etc/drprimes.txt delete mode 100755 external/libtommath-0.42.0/etc/makefile delete mode 100755 external/libtommath-0.42.0/etc/makefile.icc delete mode 100755 external/libtommath-0.42.0/etc/makefile.msvc delete mode 100755 external/libtommath-0.42.0/etc/mersenne.c delete mode 100755 external/libtommath-0.42.0/etc/mont.c delete mode 100755 external/libtommath-0.42.0/etc/pprime.c delete mode 100755 external/libtommath-0.42.0/etc/prime.1024 delete mode 100755 external/libtommath-0.42.0/etc/prime.512 delete mode 100755 external/libtommath-0.42.0/etc/timer.asm delete mode 100755 external/libtommath-0.42.0/etc/tune.c delete mode 100755 external/libtommath-0.42.0/gen.pl delete mode 100755 external/libtommath-0.42.0/libtommath.dsp delete mode 100755 external/libtommath-0.42.0/libtommath_VS2005.sln delete mode 100755 external/libtommath-0.42.0/libtommath_VS2005.vcproj delete mode 100755 external/libtommath-0.42.0/libtommath_VS2008.sln delete mode 100755 external/libtommath-0.42.0/libtommath_VS2008.vcproj delete mode 100755 external/libtommath-0.42.0/logs/README delete mode 100755 external/libtommath-0.42.0/logs/add.log delete mode 100755 external/libtommath-0.42.0/logs/addsub.png delete mode 100755 external/libtommath-0.42.0/logs/expt.log delete mode 100755 external/libtommath-0.42.0/logs/expt.png delete mode 100755 external/libtommath-0.42.0/logs/expt_2k.log delete mode 100755 external/libtommath-0.42.0/logs/expt_2kl.log delete mode 100755 external/libtommath-0.42.0/logs/expt_dr.log delete mode 100755 external/libtommath-0.42.0/logs/graphs.dem delete mode 100755 external/libtommath-0.42.0/logs/index.html delete mode 100755 external/libtommath-0.42.0/logs/invmod.log delete mode 100755 external/libtommath-0.42.0/logs/invmod.png delete mode 100755 external/libtommath-0.42.0/logs/mult.log delete mode 100755 external/libtommath-0.42.0/logs/mult.png delete mode 100755 external/libtommath-0.42.0/logs/mult_kara.log delete mode 100755 external/libtommath-0.42.0/logs/sqr.log delete mode 100755 external/libtommath-0.42.0/logs/sqr_kara.log delete mode 100755 external/libtommath-0.42.0/logs/sub.log delete mode 100755 external/libtommath-0.42.0/makefile delete mode 100755 external/libtommath-0.42.0/makefile.bcc delete mode 100755 external/libtommath-0.42.0/makefile.cygwin_dll delete mode 100755 external/libtommath-0.42.0/makefile.icc delete mode 100755 external/libtommath-0.42.0/makefile.msvc delete mode 100755 external/libtommath-0.42.0/makefile.shared delete mode 100755 external/libtommath-0.42.0/mess.sh delete mode 100755 external/libtommath-0.42.0/mtest/logtab.h delete mode 100755 external/libtommath-0.42.0/mtest/mpi-config.h delete mode 100755 external/libtommath-0.42.0/mtest/mpi-types.h delete mode 100755 external/libtommath-0.42.0/mtest/mpi.c delete mode 100755 external/libtommath-0.42.0/mtest/mpi.h delete mode 100755 external/libtommath-0.42.0/mtest/mtest.c delete mode 100755 external/libtommath-0.42.0/pics/design_process.sxd delete mode 100755 external/libtommath-0.42.0/pics/design_process.tif delete mode 100755 external/libtommath-0.42.0/pics/expt_state.sxd delete mode 100755 external/libtommath-0.42.0/pics/expt_state.tif delete mode 100755 external/libtommath-0.42.0/pics/makefile delete mode 100755 external/libtommath-0.42.0/pics/primality.tif delete mode 100755 external/libtommath-0.42.0/pics/radix.sxd delete mode 100755 external/libtommath-0.42.0/pics/sliding_window.sxd delete mode 100755 external/libtommath-0.42.0/pics/sliding_window.tif delete mode 100644 external/libtommath-0.42.0/poster.out delete mode 100755 external/libtommath-0.42.0/poster.tex delete mode 100644 external/libtommath-0.42.0/pre_gen/mpi.c delete mode 100755 external/libtommath-0.42.0/pretty.build delete mode 100755 external/libtommath-0.42.0/tombc/grammar.txt delete mode 100755 external/libtommath-0.42.0/tommath.h delete mode 100755 external/libtommath-0.42.0/tommath.out delete mode 100755 external/libtommath-0.42.0/tommath.src delete mode 100755 external/libtommath-0.42.0/tommath_class.h delete mode 100755 external/libtommath-0.42.0/tommath_superclass.h delete mode 100644 external/libtompoly-0.04/LICENSE delete mode 100644 external/libtompoly-0.04/changes.txt delete mode 100644 external/libtompoly-0.04/demo/demo.c delete mode 100644 external/libtompoly-0.04/makefile delete mode 100644 external/libtompoly-0.04/makefile.msvc delete mode 100644 external/libtompoly-0.04/pb.pdf delete mode 100644 external/libtompoly-0.04/pb.tex delete mode 100644 external/libtompoly-0.04/pb_add.c delete mode 100644 external/libtompoly-0.04/pb_addmod.c delete mode 100644 external/libtompoly-0.04/pb_clamp.c delete mode 100644 external/libtompoly-0.04/pb_clear.c delete mode 100644 external/libtompoly-0.04/pb_clear_multi.c delete mode 100644 external/libtompoly-0.04/pb_cmp.c delete mode 100644 external/libtompoly-0.04/pb_copy.c delete mode 100644 external/libtompoly-0.04/pb_div.c delete mode 100644 external/libtompoly-0.04/pb_exch.c delete mode 100644 external/libtompoly-0.04/pb_exptmod.c delete mode 100644 external/libtompoly-0.04/pb_exteuclid.c delete mode 100644 external/libtompoly-0.04/pb_gcd.c delete mode 100644 external/libtompoly-0.04/pb_grow.c delete mode 100644 external/libtompoly-0.04/pb_init.c delete mode 100644 external/libtompoly-0.04/pb_init_copy.c delete mode 100644 external/libtompoly-0.04/pb_init_multi.c delete mode 100644 external/libtompoly-0.04/pb_init_size.c delete mode 100644 external/libtompoly-0.04/pb_invmod.c delete mode 100644 external/libtompoly-0.04/pb_isirreduc.c delete mode 100644 external/libtompoly-0.04/pb_lshd.c delete mode 100644 external/libtompoly-0.04/pb_mod.c delete mode 100644 external/libtompoly-0.04/pb_monic.c delete mode 100644 external/libtompoly-0.04/pb_mul.c delete mode 100644 external/libtompoly-0.04/pb_mulmod.c delete mode 100644 external/libtompoly-0.04/pb_rawsize.c delete mode 100644 external/libtompoly-0.04/pb_readraw.c delete mode 100644 external/libtompoly-0.04/pb_rshd.c delete mode 100644 external/libtompoly-0.04/pb_shrink.c delete mode 100644 external/libtompoly-0.04/pb_sub.c delete mode 100644 external/libtompoly-0.04/pb_submod.c delete mode 100644 external/libtompoly-0.04/pb_toraw.c delete mode 100644 external/libtompoly-0.04/pb_zero.c delete mode 100644 external/libtompoly-0.04/tompoly.h diff --git a/external/libtommath-0.42.0/LICENSE b/external/libtommath-0.42.0/LICENSE deleted file mode 100755 index 5baa792..0000000 --- a/external/libtommath-0.42.0/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -LibTomMath is hereby released into the Public Domain. - --- Tom St Denis - diff --git a/external/libtommath-0.42.0/bn.tex b/external/libtommath-0.42.0/bn.tex deleted file mode 100755 index 71b6840..0000000 --- a/external/libtommath-0.42.0/bn.tex +++ /dev/null @@ -1,1835 +0,0 @@ -\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.42.0} -\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/external/libtommath-0.42.0/bn_error.c b/external/libtommath-0.42.0/bn_error.c deleted file mode 100755 index 250057b..0000000 --- a/external/libtommath-0.42.0/bn_error.c +++ /dev/null @@ -1,47 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_fast_mp_invmod.c b/external/libtommath-0.42.0/bn_fast_mp_invmod.c deleted file mode 100755 index 948a134..0000000 --- a/external/libtommath-0.42.0/bn_fast_mp_invmod.c +++ /dev/null @@ -1,148 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_fast_mp_montgomery_reduce.c b/external/libtommath-0.42.0/bn_fast_mp_montgomery_reduce.c deleted file mode 100755 index 1a81689..0000000 --- a/external/libtommath-0.42.0/bn_fast_mp_montgomery_reduce.c +++ /dev/null @@ -1,172 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_fast_s_mp_mul_digs.c b/external/libtommath-0.42.0/bn_fast_s_mp_mul_digs.c deleted file mode 100755 index 04becfd..0000000 --- a/external/libtommath-0.42.0/bn_fast_s_mp_mul_digs.c +++ /dev/null @@ -1,107 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_fast_s_mp_mul_high_digs.c b/external/libtommath-0.42.0/bn_fast_s_mp_mul_high_digs.c deleted file mode 100755 index 98bee37..0000000 --- a/external/libtommath-0.42.0/bn_fast_s_mp_mul_high_digs.c +++ /dev/null @@ -1,98 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_fast_s_mp_sqr.c b/external/libtommath-0.42.0/bn_fast_s_mp_sqr.c deleted file mode 100755 index 086b52c..0000000 --- a/external/libtommath-0.42.0/bn_fast_s_mp_sqr.c +++ /dev/null @@ -1,114 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_2expt.c b/external/libtommath-0.42.0/bn_mp_2expt.c deleted file mode 100755 index 4774aab..0000000 --- a/external/libtommath-0.42.0/bn_mp_2expt.c +++ /dev/null @@ -1,48 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_abs.c b/external/libtommath-0.42.0/bn_mp_abs.c deleted file mode 100755 index 4d1fa44..0000000 --- a/external/libtommath-0.42.0/bn_mp_abs.c +++ /dev/null @@ -1,43 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_add.c b/external/libtommath-0.42.0/bn_mp_add.c deleted file mode 100755 index 122c850..0000000 --- a/external/libtommath-0.42.0/bn_mp_add.c +++ /dev/null @@ -1,53 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_add_d.c b/external/libtommath-0.42.0/bn_mp_add_d.c deleted file mode 100755 index aec8fc8..0000000 --- a/external/libtommath-0.42.0/bn_mp_add_d.c +++ /dev/null @@ -1,112 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_addmod.c b/external/libtommath-0.42.0/bn_mp_addmod.c deleted file mode 100755 index 0376659..0000000 --- a/external/libtommath-0.42.0/bn_mp_addmod.c +++ /dev/null @@ -1,41 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_and.c b/external/libtommath-0.42.0/bn_mp_and.c deleted file mode 100755 index 22dfbff..0000000 --- a/external/libtommath-0.42.0/bn_mp_and.c +++ /dev/null @@ -1,57 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_clamp.c b/external/libtommath-0.42.0/bn_mp_clamp.c deleted file mode 100755 index 1e0c817..0000000 --- a/external/libtommath-0.42.0/bn_mp_clamp.c +++ /dev/null @@ -1,44 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_clear.c b/external/libtommath-0.42.0/bn_mp_clear.c deleted file mode 100755 index 72301df..0000000 --- a/external/libtommath-0.42.0/bn_mp_clear.c +++ /dev/null @@ -1,44 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_clear_multi.c b/external/libtommath-0.42.0/bn_mp_clear_multi.c deleted file mode 100755 index 6bbc10c..0000000 --- a/external/libtommath-0.42.0/bn_mp_clear_multi.c +++ /dev/null @@ -1,34 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_cmp.c b/external/libtommath-0.42.0/bn_mp_cmp.c deleted file mode 100755 index 77d00cd..0000000 --- a/external/libtommath-0.42.0/bn_mp_cmp.c +++ /dev/null @@ -1,43 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_cmp_d.c b/external/libtommath-0.42.0/bn_mp_cmp_d.c deleted file mode 100755 index 0d5bcb4..0000000 --- a/external/libtommath-0.42.0/bn_mp_cmp_d.c +++ /dev/null @@ -1,44 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_cmp_mag.c b/external/libtommath-0.42.0/bn_mp_cmp_mag.c deleted file mode 100755 index 063fd18..0000000 --- a/external/libtommath-0.42.0/bn_mp_cmp_mag.c +++ /dev/null @@ -1,55 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_cnt_lsb.c b/external/libtommath-0.42.0/bn_mp_cnt_lsb.c deleted file mode 100755 index efebd2a..0000000 --- a/external/libtommath-0.42.0/bn_mp_cnt_lsb.c +++ /dev/null @@ -1,53 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_copy.c b/external/libtommath-0.42.0/bn_mp_copy.c deleted file mode 100755 index 45cac61..0000000 --- a/external/libtommath-0.42.0/bn_mp_copy.c +++ /dev/null @@ -1,68 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_count_bits.c b/external/libtommath-0.42.0/bn_mp_count_bits.c deleted file mode 100755 index 6c02ec6..0000000 --- a/external/libtommath-0.42.0/bn_mp_count_bits.c +++ /dev/null @@ -1,45 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_div.c b/external/libtommath-0.42.0/bn_mp_div.c deleted file mode 100755 index af5c55d..0000000 --- a/external/libtommath-0.42.0/bn_mp_div.c +++ /dev/null @@ -1,292 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_div_2.c b/external/libtommath-0.42.0/bn_mp_div_2.c deleted file mode 100755 index 64ef823..0000000 --- a/external/libtommath-0.42.0/bn_mp_div_2.c +++ /dev/null @@ -1,68 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_div_2d.c b/external/libtommath-0.42.0/bn_mp_div_2d.c deleted file mode 100755 index 72936a4..0000000 --- a/external/libtommath-0.42.0/bn_mp_div_2d.c +++ /dev/null @@ -1,97 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_div_3.c b/external/libtommath-0.42.0/bn_mp_div_3.c deleted file mode 100755 index 7f6869b..0000000 --- a/external/libtommath-0.42.0/bn_mp_div_3.c +++ /dev/null @@ -1,79 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_div_d.c b/external/libtommath-0.42.0/bn_mp_div_d.c deleted file mode 100755 index ca34e87..0000000 --- a/external/libtommath-0.42.0/bn_mp_div_d.c +++ /dev/null @@ -1,115 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_dr_is_modulus.c b/external/libtommath-0.42.0/bn_mp_dr_is_modulus.c deleted file mode 100755 index 52b4fdf..0000000 --- a/external/libtommath-0.42.0/bn_mp_dr_is_modulus.c +++ /dev/null @@ -1,43 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_dr_reduce.c b/external/libtommath-0.42.0/bn_mp_dr_reduce.c deleted file mode 100755 index 47f0c60..0000000 --- a/external/libtommath-0.42.0/bn_mp_dr_reduce.c +++ /dev/null @@ -1,94 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_dr_setup.c b/external/libtommath-0.42.0/bn_mp_dr_setup.c deleted file mode 100755 index 99ee67d..0000000 --- a/external/libtommath-0.42.0/bn_mp_dr_setup.c +++ /dev/null @@ -1,32 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_exch.c b/external/libtommath-0.42.0/bn_mp_exch.c deleted file mode 100755 index dd3098e..0000000 --- a/external/libtommath-0.42.0/bn_mp_exch.c +++ /dev/null @@ -1,34 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_expt_d.c b/external/libtommath-0.42.0/bn_mp_expt_d.c deleted file mode 100755 index f9357cc..0000000 --- a/external/libtommath-0.42.0/bn_mp_expt_d.c +++ /dev/null @@ -1,57 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_exptmod.c b/external/libtommath-0.42.0/bn_mp_exptmod.c deleted file mode 100755 index 8fbce19..0000000 --- a/external/libtommath-0.42.0/bn_mp_exptmod.c +++ /dev/null @@ -1,112 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_exptmod_fast.c b/external/libtommath-0.42.0/bn_mp_exptmod_fast.c deleted file mode 100755 index 60c7e2b..0000000 --- a/external/libtommath-0.42.0/bn_mp_exptmod_fast.c +++ /dev/null @@ -1,321 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_exteuclid.c b/external/libtommath-0.42.0/bn_mp_exteuclid.c deleted file mode 100755 index c65928d..0000000 --- a/external/libtommath-0.42.0/bn_mp_exteuclid.c +++ /dev/null @@ -1,82 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_fread.c b/external/libtommath-0.42.0/bn_mp_fread.c deleted file mode 100755 index a2e51a1..0000000 --- a/external/libtommath-0.42.0/bn_mp_fread.c +++ /dev/null @@ -1,67 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_fwrite.c b/external/libtommath-0.42.0/bn_mp_fwrite.c deleted file mode 100755 index b3fd834..0000000 --- a/external/libtommath-0.42.0/bn_mp_fwrite.c +++ /dev/null @@ -1,52 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_gcd.c b/external/libtommath-0.42.0/bn_mp_gcd.c deleted file mode 100755 index b45cfed..0000000 --- a/external/libtommath-0.42.0/bn_mp_gcd.c +++ /dev/null @@ -1,105 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_get_int.c b/external/libtommath-0.42.0/bn_mp_get_int.c deleted file mode 100755 index 11baa0e..0000000 --- a/external/libtommath-0.42.0/bn_mp_get_int.c +++ /dev/null @@ -1,45 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_grow.c b/external/libtommath-0.42.0/bn_mp_grow.c deleted file mode 100755 index f1c1cab..0000000 --- a/external/libtommath-0.42.0/bn_mp_grow.c +++ /dev/null @@ -1,57 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_init.c b/external/libtommath-0.42.0/bn_mp_init.c deleted file mode 100755 index 79cca3c..0000000 --- a/external/libtommath-0.42.0/bn_mp_init.c +++ /dev/null @@ -1,46 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_init_copy.c b/external/libtommath-0.42.0/bn_mp_init_copy.c deleted file mode 100755 index 8ce0ef9..0000000 --- a/external/libtommath-0.42.0/bn_mp_init_copy.c +++ /dev/null @@ -1,32 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_init_multi.c b/external/libtommath-0.42.0/bn_mp_init_multi.c deleted file mode 100755 index a40ea8e..0000000 --- a/external/libtommath-0.42.0/bn_mp_init_multi.c +++ /dev/null @@ -1,59 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_init_set.c b/external/libtommath-0.42.0/bn_mp_init_set.c deleted file mode 100755 index f9b08e9..0000000 --- a/external/libtommath-0.42.0/bn_mp_init_set.c +++ /dev/null @@ -1,32 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_init_set_int.c b/external/libtommath-0.42.0/bn_mp_init_set_int.c deleted file mode 100755 index 9473c3f..0000000 --- a/external/libtommath-0.42.0/bn_mp_init_set_int.c +++ /dev/null @@ -1,31 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_init_size.c b/external/libtommath-0.42.0/bn_mp_init_size.c deleted file mode 100755 index 69dd49c..0000000 --- a/external/libtommath-0.42.0/bn_mp_init_size.c +++ /dev/null @@ -1,48 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_invmod.c b/external/libtommath-0.42.0/bn_mp_invmod.c deleted file mode 100755 index f4bdc17..0000000 --- a/external/libtommath-0.42.0/bn_mp_invmod.c +++ /dev/null @@ -1,43 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_invmod_slow.c b/external/libtommath-0.42.0/bn_mp_invmod_slow.c deleted file mode 100755 index 2430f02..0000000 --- a/external/libtommath-0.42.0/bn_mp_invmod_slow.c +++ /dev/null @@ -1,175 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_is_square.c b/external/libtommath-0.42.0/bn_mp_is_square.c deleted file mode 100755 index 12b9ec7..0000000 --- a/external/libtommath-0.42.0/bn_mp_is_square.c +++ /dev/null @@ -1,109 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_jacobi.c b/external/libtommath-0.42.0/bn_mp_jacobi.c deleted file mode 100755 index 07a9d65..0000000 --- a/external/libtommath-0.42.0/bn_mp_jacobi.c +++ /dev/null @@ -1,105 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_karatsuba_mul.c b/external/libtommath-0.42.0/bn_mp_karatsuba_mul.c deleted file mode 100755 index 62e885c..0000000 --- a/external/libtommath-0.42.0/bn_mp_karatsuba_mul.c +++ /dev/null @@ -1,167 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_lshd.c b/external/libtommath-0.42.0/bn_mp_lshd.c deleted file mode 100755 index 87c216b..0000000 --- a/external/libtommath-0.42.0/bn_mp_lshd.c +++ /dev/null @@ -1,67 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_mod.c b/external/libtommath-0.42.0/bn_mp_mod.c deleted file mode 100755 index 6828328..0000000 --- a/external/libtommath-0.42.0/bn_mp_mod.c +++ /dev/null @@ -1,48 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_mod_2d.c b/external/libtommath-0.42.0/bn_mp_mod_2d.c deleted file mode 100755 index 77f13c3..0000000 --- a/external/libtommath-0.42.0/bn_mp_mod_2d.c +++ /dev/null @@ -1,55 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_mod_d.c b/external/libtommath-0.42.0/bn_mp_mod_d.c deleted file mode 100755 index 4ad3d90..0000000 --- a/external/libtommath-0.42.0/bn_mp_mod_d.c +++ /dev/null @@ -1,27 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_montgomery_calc_normalization.c b/external/libtommath-0.42.0/bn_mp_montgomery_calc_normalization.c deleted file mode 100755 index 4825ab5..0000000 --- a/external/libtommath-0.42.0/bn_mp_montgomery_calc_normalization.c +++ /dev/null @@ -1,59 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_montgomery_reduce.c b/external/libtommath-0.42.0/bn_mp_montgomery_reduce.c deleted file mode 100755 index 3c73268..0000000 --- a/external/libtommath-0.42.0/bn_mp_montgomery_reduce.c +++ /dev/null @@ -1,118 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_montgomery_setup.c b/external/libtommath-0.42.0/bn_mp_montgomery_setup.c deleted file mode 100755 index 0de27bb..0000000 --- a/external/libtommath-0.42.0/bn_mp_montgomery_setup.c +++ /dev/null @@ -1,59 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_mul.c b/external/libtommath-0.42.0/bn_mp_mul.c deleted file mode 100755 index bd75d04..0000000 --- a/external/libtommath-0.42.0/bn_mp_mul.c +++ /dev/null @@ -1,66 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_mul_2.c b/external/libtommath-0.42.0/bn_mp_mul_2.c deleted file mode 100755 index 6ba76be..0000000 --- a/external/libtommath-0.42.0/bn_mp_mul_2.c +++ /dev/null @@ -1,82 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_mul_2d.c b/external/libtommath-0.42.0/bn_mp_mul_2d.c deleted file mode 100755 index 385ac59..0000000 --- a/external/libtommath-0.42.0/bn_mp_mul_2d.c +++ /dev/null @@ -1,85 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_mul_d.c b/external/libtommath-0.42.0/bn_mp_mul_d.c deleted file mode 100755 index 13c6066..0000000 --- a/external/libtommath-0.42.0/bn_mp_mul_d.c +++ /dev/null @@ -1,79 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_mulmod.c b/external/libtommath-0.42.0/bn_mp_mulmod.c deleted file mode 100755 index eebca37..0000000 --- a/external/libtommath-0.42.0/bn_mp_mulmod.c +++ /dev/null @@ -1,40 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_n_root.c b/external/libtommath-0.42.0/bn_mp_n_root.c deleted file mode 100755 index e6bf725..0000000 --- a/external/libtommath-0.42.0/bn_mp_n_root.c +++ /dev/null @@ -1,132 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_neg.c b/external/libtommath-0.42.0/bn_mp_neg.c deleted file mode 100755 index 0e868ce..0000000 --- a/external/libtommath-0.42.0/bn_mp_neg.c +++ /dev/null @@ -1,40 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_or.c b/external/libtommath-0.42.0/bn_mp_or.c deleted file mode 100755 index 5c2761a..0000000 --- a/external/libtommath-0.42.0/bn_mp_or.c +++ /dev/null @@ -1,50 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_prime_fermat.c b/external/libtommath-0.42.0/bn_mp_prime_fermat.c deleted file mode 100755 index fe10ab2..0000000 --- a/external/libtommath-0.42.0/bn_mp_prime_fermat.c +++ /dev/null @@ -1,62 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_prime_is_divisible.c b/external/libtommath-0.42.0/bn_mp_prime_is_divisible.c deleted file mode 100755 index 2b217ae..0000000 --- a/external/libtommath-0.42.0/bn_mp_prime_is_divisible.c +++ /dev/null @@ -1,50 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_prime_is_prime.c b/external/libtommath-0.42.0/bn_mp_prime_is_prime.c deleted file mode 100755 index 09908df..0000000 --- a/external/libtommath-0.42.0/bn_mp_prime_is_prime.c +++ /dev/null @@ -1,83 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_prime_miller_rabin.c b/external/libtommath-0.42.0/bn_mp_prime_miller_rabin.c deleted file mode 100755 index fe88d94..0000000 --- a/external/libtommath-0.42.0/bn_mp_prime_miller_rabin.c +++ /dev/null @@ -1,103 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_prime_next_prime.c b/external/libtommath-0.42.0/bn_mp_prime_next_prime.c deleted file mode 100755 index 37a03c6..0000000 --- a/external/libtommath-0.42.0/bn_mp_prime_next_prime.c +++ /dev/null @@ -1,170 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_prime_random_ex.c b/external/libtommath-0.42.0/bn_mp_prime_random_ex.c deleted file mode 100755 index 16d2aae..0000000 --- a/external/libtommath-0.42.0/bn_mp_prime_random_ex.c +++ /dev/null @@ -1,125 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_radix_size.c b/external/libtommath-0.42.0/bn_mp_radix_size.c deleted file mode 100755 index 9d95c48..0000000 --- a/external/libtommath-0.42.0/bn_mp_radix_size.c +++ /dev/null @@ -1,78 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_radix_smap.c b/external/libtommath-0.42.0/bn_mp_radix_smap.c deleted file mode 100755 index b3abd3e..0000000 --- a/external/libtommath-0.42.0/bn_mp_radix_smap.c +++ /dev/null @@ -1,24 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_rand.c b/external/libtommath-0.42.0/bn_mp_rand.c deleted file mode 100755 index 96e4e46..0000000 --- a/external/libtommath-0.42.0/bn_mp_rand.c +++ /dev/null @@ -1,55 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_read_radix.c b/external/libtommath-0.42.0/bn_mp_read_radix.c deleted file mode 100755 index 8ce103f..0000000 --- a/external/libtommath-0.42.0/bn_mp_read_radix.c +++ /dev/null @@ -1,85 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_read_signed_bin.c b/external/libtommath-0.42.0/bn_mp_read_signed_bin.c deleted file mode 100755 index 92924e8..0000000 --- a/external/libtommath-0.42.0/bn_mp_read_signed_bin.c +++ /dev/null @@ -1,41 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_read_unsigned_bin.c b/external/libtommath-0.42.0/bn_mp_read_unsigned_bin.c deleted file mode 100755 index 5a7fa91..0000000 --- a/external/libtommath-0.42.0/bn_mp_read_unsigned_bin.c +++ /dev/null @@ -1,55 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_reduce.c b/external/libtommath-0.42.0/bn_mp_reduce.c deleted file mode 100755 index 50e1eaa..0000000 --- a/external/libtommath-0.42.0/bn_mp_reduce.c +++ /dev/null @@ -1,100 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_reduce_2k.c b/external/libtommath-0.42.0/bn_mp_reduce_2k.c deleted file mode 100755 index 6bbc5f1..0000000 --- a/external/libtommath-0.42.0/bn_mp_reduce_2k.c +++ /dev/null @@ -1,61 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_reduce_2k_l.c b/external/libtommath-0.42.0/bn_mp_reduce_2k_l.c deleted file mode 100755 index 067122a..0000000 --- a/external/libtommath-0.42.0/bn_mp_reduce_2k_l.c +++ /dev/null @@ -1,62 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_reduce_2k_setup.c b/external/libtommath-0.42.0/bn_mp_reduce_2k_setup.c deleted file mode 100755 index 3f9ffd9..0000000 --- a/external/libtommath-0.42.0/bn_mp_reduce_2k_setup.c +++ /dev/null @@ -1,47 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_reduce_2k_setup_l.c b/external/libtommath-0.42.0/bn_mp_reduce_2k_setup_l.c deleted file mode 100755 index 686368e..0000000 --- a/external/libtommath-0.42.0/bn_mp_reduce_2k_setup_l.c +++ /dev/null @@ -1,44 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_reduce_is_2k.c b/external/libtommath-0.42.0/bn_mp_reduce_is_2k.c deleted file mode 100755 index 08b62ff..0000000 --- a/external/libtommath-0.42.0/bn_mp_reduce_is_2k.c +++ /dev/null @@ -1,52 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_reduce_is_2k_l.c b/external/libtommath-0.42.0/bn_mp_reduce_is_2k_l.c deleted file mode 100755 index a72e39c..0000000 --- a/external/libtommath-0.42.0/bn_mp_reduce_is_2k_l.c +++ /dev/null @@ -1,44 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_reduce_setup.c b/external/libtommath-0.42.0/bn_mp_reduce_setup.c deleted file mode 100755 index f017386..0000000 --- a/external/libtommath-0.42.0/bn_mp_reduce_setup.c +++ /dev/null @@ -1,34 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_rshd.c b/external/libtommath-0.42.0/bn_mp_rshd.c deleted file mode 100755 index bb506e9..0000000 --- a/external/libtommath-0.42.0/bn_mp_rshd.c +++ /dev/null @@ -1,72 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_set.c b/external/libtommath-0.42.0/bn_mp_set.c deleted file mode 100755 index 412673a..0000000 --- a/external/libtommath-0.42.0/bn_mp_set.c +++ /dev/null @@ -1,29 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_set_int.c b/external/libtommath-0.42.0/bn_mp_set_int.c deleted file mode 100755 index 17cfe89..0000000 --- a/external/libtommath-0.42.0/bn_mp_set_int.c +++ /dev/null @@ -1,48 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_shrink.c b/external/libtommath-0.42.0/bn_mp_shrink.c deleted file mode 100755 index 2bee381..0000000 --- a/external/libtommath-0.42.0/bn_mp_shrink.c +++ /dev/null @@ -1,40 +0,0 @@ -#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; - int used = 1; - - if(a->used > 0) - used = a->used; - - if (a->alloc != used) { - if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * used)) == NULL) { - return MP_MEM; - } - a->dp = tmp; - a->alloc = used; - } - return MP_OKAY; -} -#endif - -/* $Source$ */ -/* $Revision: v0.42.0 $ */ -/* $Date: 2010-06-02 15:09:36 +0200 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_signed_bin_size.c b/external/libtommath-0.42.0/bn_mp_signed_bin_size.c deleted file mode 100755 index b28d402..0000000 --- a/external/libtommath-0.42.0/bn_mp_signed_bin_size.c +++ /dev/null @@ -1,27 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_sqr.c b/external/libtommath-0.42.0/bn_mp_sqr.c deleted file mode 100755 index b085668..0000000 --- a/external/libtommath-0.42.0/bn_mp_sqr.c +++ /dev/null @@ -1,58 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_sqrmod.c b/external/libtommath-0.42.0/bn_mp_sqrmod.c deleted file mode 100755 index 369028b..0000000 --- a/external/libtommath-0.42.0/bn_mp_sqrmod.c +++ /dev/null @@ -1,41 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_sqrt.c b/external/libtommath-0.42.0/bn_mp_sqrt.c deleted file mode 100755 index 983e41c..0000000 --- a/external/libtommath-0.42.0/bn_mp_sqrt.c +++ /dev/null @@ -1,81 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_sub.c b/external/libtommath-0.42.0/bn_mp_sub.c deleted file mode 100755 index 3c8e5d4..0000000 --- a/external/libtommath-0.42.0/bn_mp_sub.c +++ /dev/null @@ -1,59 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_sub_d.c b/external/libtommath-0.42.0/bn_mp_sub_d.c deleted file mode 100755 index 13b49bc..0000000 --- a/external/libtommath-0.42.0/bn_mp_sub_d.c +++ /dev/null @@ -1,93 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_submod.c b/external/libtommath-0.42.0/bn_mp_submod.c deleted file mode 100755 index d919c17..0000000 --- a/external/libtommath-0.42.0/bn_mp_submod.c +++ /dev/null @@ -1,42 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_to_signed_bin.c b/external/libtommath-0.42.0/bn_mp_to_signed_bin.c deleted file mode 100755 index dda9285..0000000 --- a/external/libtommath-0.42.0/bn_mp_to_signed_bin.c +++ /dev/null @@ -1,33 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_to_signed_bin_n.c b/external/libtommath-0.42.0/bn_mp_to_signed_bin_n.c deleted file mode 100755 index 9e3b011..0000000 --- a/external/libtommath-0.42.0/bn_mp_to_signed_bin_n.c +++ /dev/null @@ -1,31 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_to_unsigned_bin.c b/external/libtommath-0.42.0/bn_mp_to_unsigned_bin.c deleted file mode 100755 index 76072a9..0000000 --- a/external/libtommath-0.42.0/bn_mp_to_unsigned_bin.c +++ /dev/null @@ -1,48 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_to_unsigned_bin_n.c b/external/libtommath-0.42.0/bn_mp_to_unsigned_bin_n.c deleted file mode 100755 index 51028d8..0000000 --- a/external/libtommath-0.42.0/bn_mp_to_unsigned_bin_n.c +++ /dev/null @@ -1,31 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_toom_mul.c b/external/libtommath-0.42.0/bn_mp_toom_mul.c deleted file mode 100755 index e0fd772..0000000 --- a/external/libtommath-0.42.0/bn_mp_toom_mul.c +++ /dev/null @@ -1,284 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_toom_sqr.c b/external/libtommath-0.42.0/bn_mp_toom_sqr.c deleted file mode 100755 index 9076e6f..0000000 --- a/external/libtommath-0.42.0/bn_mp_toom_sqr.c +++ /dev/null @@ -1,226 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_toradix.c b/external/libtommath-0.42.0/bn_mp_toradix.c deleted file mode 100755 index bb95783..0000000 --- a/external/libtommath-0.42.0/bn_mp_toradix.c +++ /dev/null @@ -1,75 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_toradix_n.c b/external/libtommath-0.42.0/bn_mp_toradix_n.c deleted file mode 100755 index 7e425d6..0000000 --- a/external/libtommath-0.42.0/bn_mp_toradix_n.c +++ /dev/null @@ -1,88 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_unsigned_bin_size.c b/external/libtommath-0.42.0/bn_mp_unsigned_bin_size.c deleted file mode 100755 index b16fdcd..0000000 --- a/external/libtommath-0.42.0/bn_mp_unsigned_bin_size.c +++ /dev/null @@ -1,28 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_xor.c b/external/libtommath-0.42.0/bn_mp_xor.c deleted file mode 100755 index 5744556..0000000 --- a/external/libtommath-0.42.0/bn_mp_xor.c +++ /dev/null @@ -1,51 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_mp_zero.c b/external/libtommath-0.42.0/bn_mp_zero.c deleted file mode 100755 index 99e6df2..0000000 --- a/external/libtommath-0.42.0/bn_mp_zero.c +++ /dev/null @@ -1,36 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_prime_tab.c b/external/libtommath-0.42.0/bn_prime_tab.c deleted file mode 100755 index fb5ad08..0000000 --- a/external/libtommath-0.42.0/bn_prime_tab.c +++ /dev/null @@ -1,61 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_reverse.c b/external/libtommath-0.42.0/bn_reverse.c deleted file mode 100755 index 17cdcc1..0000000 --- a/external/libtommath-0.42.0/bn_reverse.c +++ /dev/null @@ -1,39 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_s_mp_add.c b/external/libtommath-0.42.0/bn_s_mp_add.c deleted file mode 100755 index 0ca20b8..0000000 --- a/external/libtommath-0.42.0/bn_s_mp_add.c +++ /dev/null @@ -1,109 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_s_mp_exptmod.c b/external/libtommath-0.42.0/bn_s_mp_exptmod.c deleted file mode 100755 index bc02a28..0000000 --- a/external/libtommath-0.42.0/bn_s_mp_exptmod.c +++ /dev/null @@ -1,252 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_s_mp_mul_digs.c b/external/libtommath-0.42.0/bn_s_mp_mul_digs.c deleted file mode 100755 index 86196bf..0000000 --- a/external/libtommath-0.42.0/bn_s_mp_mul_digs.c +++ /dev/null @@ -1,90 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_s_mp_mul_high_digs.c b/external/libtommath-0.42.0/bn_s_mp_mul_high_digs.c deleted file mode 100755 index 019014e..0000000 --- a/external/libtommath-0.42.0/bn_s_mp_mul_high_digs.c +++ /dev/null @@ -1,81 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_s_mp_sqr.c b/external/libtommath-0.42.0/bn_s_mp_sqr.c deleted file mode 100755 index 90c465d..0000000 --- a/external/libtommath-0.42.0/bn_s_mp_sqr.c +++ /dev/null @@ -1,84 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bn_s_mp_sub.c b/external/libtommath-0.42.0/bn_s_mp_sub.c deleted file mode 100755 index ccea6bd..0000000 --- a/external/libtommath-0.42.0/bn_s_mp_sub.c +++ /dev/null @@ -1,89 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/bncore.c b/external/libtommath-0.42.0/bncore.c deleted file mode 100755 index 1a0ac2c..0000000 --- a/external/libtommath-0.42.0/bncore.c +++ /dev/null @@ -1,36 +0,0 @@ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ diff --git a/external/libtommath-0.42.0/booker.pl b/external/libtommath-0.42.0/booker.pl deleted file mode 100755 index 49f1889..0000000 --- a/external/libtommath-0.42.0/booker.pl +++ /dev/null @@ -1,265 +0,0 @@ -#!/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/external/libtommath-0.42.0/callgraph.txt b/external/libtommath-0.42.0/callgraph.txt deleted file mode 100755 index 2efcf24..0000000 --- a/external/libtommath-0.42.0/callgraph.txt +++ /dev/null @@ -1,11913 +0,0 @@ -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/external/libtommath-0.42.0/changes.txt b/external/libtommath-0.42.0/changes.txt deleted file mode 100755 index 4fc0913..0000000 --- a/external/libtommath-0.42.0/changes.txt +++ /dev/null @@ -1,403 +0,0 @@ -July 23rd, 2010 -v0.42.0 - -- Fix for mp_prime_next_prime() bug when checking generated prime - -- allow mp_shrink to shrink initialized, but empty MPI's - -- Added project and solution files for Visual Studio 2005 and Visual Studio 2008. - -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/external/libtommath-0.42.0/demo/demo.c b/external/libtommath-0.42.0/demo/demo.c deleted file mode 100755 index 3e5663b..0000000 --- a/external/libtommath-0.42.0/demo/demo.c +++ /dev/null @@ -1,740 +0,0 @@ -#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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/demo/timing.c b/external/libtommath-0.42.0/demo/timing.c deleted file mode 100755 index 57bb6d4..0000000 --- a/external/libtommath-0.42.0/demo/timing.c +++ /dev/null @@ -1,319 +0,0 @@ -#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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/dep.pl b/external/libtommath-0.42.0/dep.pl deleted file mode 100755 index c39e27e..0000000 --- a/external/libtommath-0.42.0/dep.pl +++ /dev/null @@ -1,123 +0,0 @@ -#!/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/external/libtommath-0.42.0/etc/2kprime.1 b/external/libtommath-0.42.0/etc/2kprime.1 deleted file mode 100755 index c41ded1..0000000 --- a/external/libtommath-0.42.0/etc/2kprime.1 +++ /dev/null @@ -1,2 +0,0 @@ -256-bits (k = 36113) = 115792089237316195423570985008687907853269984665640564039457584007913129603823 -512-bits (k = 38117) = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006045979 diff --git a/external/libtommath-0.42.0/etc/2kprime.c b/external/libtommath-0.42.0/etc/2kprime.c deleted file mode 100755 index fff4825..0000000 --- a/external/libtommath-0.42.0/etc/2kprime.c +++ /dev/null @@ -1,84 +0,0 @@ -/* 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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/etc/drprime.c b/external/libtommath-0.42.0/etc/drprime.c deleted file mode 100755 index ea40bd3..0000000 --- a/external/libtommath-0.42.0/etc/drprime.c +++ /dev/null @@ -1,64 +0,0 @@ -/* 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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/etc/drprimes.28 b/external/libtommath-0.42.0/etc/drprimes.28 deleted file mode 100755 index 9d438ad..0000000 --- a/external/libtommath-0.42.0/etc/drprimes.28 +++ /dev/null @@ -1,25 +0,0 @@ -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/external/libtommath-0.42.0/etc/drprimes.txt b/external/libtommath-0.42.0/etc/drprimes.txt deleted file mode 100755 index 7c97f67..0000000 --- a/external/libtommath-0.42.0/etc/drprimes.txt +++ /dev/null @@ -1,9 +0,0 @@ -300-bit prime: -p == 2037035976334486086268445688409378161051468393665936250636140449354381298610415201576637819 - -540-bit prime: -p == 3599131035634557106248430806148785487095757694641533306480604458089470064537190296255232548883112685719936728506816716098566612844395439751206810991770626477344739 - -780-bit prime: -p == 6359114106063703798370219984742410466332205126109989319225557147754704702203399726411277962562135973685197744935448875852478791860694279747355800678568677946181447581781401213133886609947027230004277244697462656003655947791725966271167 - diff --git a/external/libtommath-0.42.0/etc/makefile b/external/libtommath-0.42.0/etc/makefile deleted file mode 100755 index 99154d8..0000000 --- a/external/libtommath-0.42.0/etc/makefile +++ /dev/null @@ -1,50 +0,0 @@ -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/external/libtommath-0.42.0/etc/makefile.icc b/external/libtommath-0.42.0/etc/makefile.icc deleted file mode 100755 index 8a1ffff..0000000 --- a/external/libtommath-0.42.0/etc/makefile.icc +++ /dev/null @@ -1,67 +0,0 @@ -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/external/libtommath-0.42.0/etc/makefile.msvc b/external/libtommath-0.42.0/etc/makefile.msvc deleted file mode 100755 index 2833372..0000000 --- a/external/libtommath-0.42.0/etc/makefile.msvc +++ /dev/null @@ -1,23 +0,0 @@ -#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/external/libtommath-0.42.0/etc/mersenne.c b/external/libtommath-0.42.0/etc/mersenne.c deleted file mode 100755 index 6f9eed2..0000000 --- a/external/libtommath-0.42.0/etc/mersenne.c +++ /dev/null @@ -1,144 +0,0 @@ -/* 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$ */ -/* $Revision: 0.39 $ */ -/* $Date: 2006-04-06 19:49:59 +0000 $ */ diff --git a/external/libtommath-0.42.0/etc/mont.c b/external/libtommath-0.42.0/etc/mont.c deleted file mode 100755 index 8356903..0000000 --- a/external/libtommath-0.42.0/etc/mont.c +++ /dev/null @@ -1,50 +0,0 @@ -/* 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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/etc/pprime.c b/external/libtommath-0.42.0/etc/pprime.c deleted file mode 100755 index d2d3a32..0000000 --- a/external/libtommath-0.42.0/etc/pprime.c +++ /dev/null @@ -1,400 +0,0 @@ -/* 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$ */ -/* $Revision: 0.39 $ */ -/* $Date: 2006-04-06 19:49:59 +0000 $ */ diff --git a/external/libtommath-0.42.0/etc/prime.1024 b/external/libtommath-0.42.0/etc/prime.1024 deleted file mode 100755 index 5636e2d..0000000 --- a/external/libtommath-0.42.0/etc/prime.1024 +++ /dev/null @@ -1,414 +0,0 @@ -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/external/libtommath-0.42.0/etc/prime.512 b/external/libtommath-0.42.0/etc/prime.512 deleted file mode 100755 index cb6ec30..0000000 --- a/external/libtommath-0.42.0/etc/prime.512 +++ /dev/null @@ -1,205 +0,0 @@ -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/external/libtommath-0.42.0/etc/timer.asm b/external/libtommath-0.42.0/etc/timer.asm deleted file mode 100755 index 35890d9..0000000 --- a/external/libtommath-0.42.0/etc/timer.asm +++ /dev/null @@ -1,37 +0,0 @@ -; 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/external/libtommath-0.42.0/etc/tune.c b/external/libtommath-0.42.0/etc/tune.c deleted file mode 100755 index 0094f19..0000000 --- a/external/libtommath-0.42.0/etc/tune.c +++ /dev/null @@ -1,142 +0,0 @@ -/* 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$ */ -/* $Revision: 0.39 $ */ -/* $Date: 2006-04-06 19:49:59 +0000 $ */ diff --git a/external/libtommath-0.42.0/gen.pl b/external/libtommath-0.42.0/gen.pl deleted file mode 100755 index 7236591..0000000 --- a/external/libtommath-0.42.0/gen.pl +++ /dev/null @@ -1,17 +0,0 @@ -#!/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/external/libtommath-0.42.0/libtommath.dsp b/external/libtommath-0.42.0/libtommath.dsp deleted file mode 100755 index 71ac243..0000000 --- a/external/libtommath-0.42.0/libtommath.dsp +++ /dev/null @@ -1,572 +0,0 @@ -# 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/external/libtommath-0.42.0/libtommath_VS2005.sln b/external/libtommath-0.42.0/libtommath_VS2005.sln deleted file mode 100755 index 21bc915..0000000 --- a/external/libtommath-0.42.0/libtommath_VS2005.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtommath", "libtommath_VS2005.vcproj", "{0272C9B2-D68B-4F24-B32D-C1FD552F7E51}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0272C9B2-D68B-4F24-B32D-C1FD552F7E51}.Debug|Win32.ActiveCfg = Debug|Win32 - {0272C9B2-D68B-4F24-B32D-C1FD552F7E51}.Debug|Win32.Build.0 = Debug|Win32 - {0272C9B2-D68B-4F24-B32D-C1FD552F7E51}.Release|Win32.ActiveCfg = Release|Win32 - {0272C9B2-D68B-4F24-B32D-C1FD552F7E51}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/external/libtommath-0.42.0/libtommath_VS2005.vcproj b/external/libtommath-0.42.0/libtommath_VS2005.vcproj deleted file mode 100755 index 7162185..0000000 --- a/external/libtommath-0.42.0/libtommath_VS2005.vcproj +++ /dev/null @@ -1,2803 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/external/libtommath-0.42.0/libtommath_VS2008.sln b/external/libtommath-0.42.0/libtommath_VS2008.sln deleted file mode 100755 index 1327ccf..0000000 --- a/external/libtommath-0.42.0/libtommath_VS2008.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtommath", "libtommath_VS2008.vcproj", "{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|Win32.ActiveCfg = Debug|Win32 - {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|Win32.Build.0 = Debug|Win32 - {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|Win32.ActiveCfg = Release|Win32 - {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/external/libtommath-0.42.0/libtommath_VS2008.vcproj b/external/libtommath-0.42.0/libtommath_VS2008.vcproj deleted file mode 100755 index 205aec1..0000000 --- a/external/libtommath-0.42.0/libtommath_VS2008.vcproj +++ /dev/null @@ -1,2805 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/external/libtommath-0.42.0/logs/README b/external/libtommath-0.42.0/logs/README deleted file mode 100755 index ea20c81..0000000 --- a/external/libtommath-0.42.0/logs/README +++ /dev/null @@ -1,13 +0,0 @@ -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/external/libtommath-0.42.0/logs/add.log b/external/libtommath-0.42.0/logs/add.log deleted file mode 100755 index 43503ac..0000000 --- a/external/libtommath-0.42.0/logs/add.log +++ /dev/null @@ -1,16 +0,0 @@ -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/external/libtommath-0.42.0/logs/addsub.png b/external/libtommath-0.42.0/logs/addsub.png deleted file mode 100755 index a5679ac563e6cf347bccc70fb4694ef684375ffc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6254 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 Ke`+qa^M3$0ORS*) diff --git a/external/libtommath-0.42.0/logs/expt.log b/external/libtommath-0.42.0/logs/expt.log deleted file mode 100755 index 70932ab..0000000 --- a/external/libtommath-0.42.0/logs/expt.log +++ /dev/null @@ -1,7 +0,0 @@ -513 1435869 -769 3544970 -1025 7791638 -2049 46902238 -2561 85334899 -3073 141451412 -4097 308770310 diff --git a/external/libtommath-0.42.0/logs/expt.png b/external/libtommath-0.42.0/logs/expt.png deleted file mode 100755 index 9ee8bb769feaa56ee7cffbbd5c7d39ebdb4799d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6605 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 diff --git a/external/libtommath-0.42.0/logs/expt_2k.log b/external/libtommath-0.42.0/logs/expt_2k.log deleted file mode 100755 index 97d325f..0000000 --- a/external/libtommath-0.42.0/logs/expt_2k.log +++ /dev/null @@ -1,5 +0,0 @@ -607 2109225 -1279 10148314 -2203 34126877 -3217 82716424 -4253 161569606 diff --git a/external/libtommath-0.42.0/logs/expt_2kl.log b/external/libtommath-0.42.0/logs/expt_2kl.log deleted file mode 100755 index d9ad4be..0000000 --- a/external/libtommath-0.42.0/logs/expt_2kl.log +++ /dev/null @@ -1,4 +0,0 @@ -1024 7705271 -2048 34286851 -4096 165207491 -521 1618631 diff --git a/external/libtommath-0.42.0/logs/expt_dr.log b/external/libtommath-0.42.0/logs/expt_dr.log deleted file mode 100755 index c6bbe07..0000000 --- a/external/libtommath-0.42.0/logs/expt_dr.log +++ /dev/null @@ -1,7 +0,0 @@ -532 1928550 -784 3763908 -1036 7564221 -1540 16566059 -2072 32283784 -3080 79851565 -4116 157843530 diff --git a/external/libtommath-0.42.0/logs/graphs.dem b/external/libtommath-0.42.0/logs/graphs.dem deleted file mode 100755 index dfaf613..0000000 --- a/external/libtommath-0.42.0/logs/graphs.dem +++ /dev/null @@ -1,17 +0,0 @@ -set terminal png -set size 1.75 -set ylabel "Cycles per Operation" -set xlabel "Operand size (bits)" - -set output "addsub.png" -plot 'add.log' smooth bezier title "Addition", 'sub.log' smooth bezier title "Subtraction" - -set output "mult.png" -plot 'sqr.log' smooth bezier title "Squaring (without Karatsuba)", 'sqr_kara.log' smooth bezier title "Squaring (Karatsuba)", 'mult.log' smooth bezier title "Multiplication (without Karatsuba)", 'mult_kara.log' smooth bezier title "Multiplication (Karatsuba)" - -set output "expt.png" -plot 'expt.log' smooth bezier title "Exptmod (Montgomery)", 'expt_dr.log' smooth bezier title "Exptmod (Dimminished Radix)", 'expt_2k.log' smooth bezier title "Exptmod (2k Reduction)" - -set output "invmod.png" -plot 'invmod.log' smooth bezier title "Modular Inverse" - diff --git a/external/libtommath-0.42.0/logs/index.html b/external/libtommath-0.42.0/logs/index.html deleted file mode 100755 index 4b68c25..0000000 --- a/external/libtommath-0.42.0/logs/index.html +++ /dev/null @@ -1,27 +0,0 @@ - - -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/external/libtommath-0.42.0/logs/invmod.log b/external/libtommath-0.42.0/logs/invmod.log deleted file mode 100755 index e69de29..0000000 diff --git a/external/libtommath-0.42.0/logs/invmod.png b/external/libtommath-0.42.0/logs/invmod.png deleted file mode 100755 index 0a8a4ad77170380b229a454283696e6cd4910fd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4918 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 diff --git a/external/libtommath-0.42.0/logs/mult_kara.log b/external/libtommath-0.42.0/logs/mult_kara.log deleted file mode 100755 index 7136c79..0000000 --- a/external/libtommath-0.42.0/logs/mult_kara.log +++ /dev/null @@ -1,84 +0,0 @@ -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/external/libtommath-0.42.0/logs/sqr.log b/external/libtommath-0.42.0/logs/sqr.log deleted file mode 100755 index cd29fc5..0000000 --- a/external/libtommath-0.42.0/logs/sqr.log +++ /dev/null @@ -1,84 +0,0 @@ -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/external/libtommath-0.42.0/logs/sqr_kara.log b/external/libtommath-0.42.0/logs/sqr_kara.log deleted file mode 100755 index 06355a7..0000000 --- a/external/libtommath-0.42.0/logs/sqr_kara.log +++ /dev/null @@ -1,84 +0,0 @@ -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/external/libtommath-0.42.0/logs/sub.log b/external/libtommath-0.42.0/logs/sub.log deleted file mode 100755 index 9f84fa2..0000000 --- a/external/libtommath-0.42.0/logs/sub.log +++ /dev/null @@ -1,16 +0,0 @@ -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/external/libtommath-0.42.0/makefile b/external/libtommath-0.42.0/makefile deleted file mode 100755 index 805c8fc..0000000 --- a/external/libtommath-0.42.0/makefile +++ /dev/null @@ -1,186 +0,0 @@ -#Makefile for GCC -# -#Tom St Denis - -#version of library -VERSION=0.42.0 - -CFLAGS += -fPIC -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/external/libtommath-0.42.0/makefile.bcc b/external/libtommath-0.42.0/makefile.bcc deleted file mode 100755 index 67743d9..0000000 --- a/external/libtommath-0.42.0/makefile.bcc +++ /dev/null @@ -1,44 +0,0 @@ -# -# 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/external/libtommath-0.42.0/makefile.cygwin_dll b/external/libtommath-0.42.0/makefile.cygwin_dll deleted file mode 100755 index 85a9b20..0000000 --- a/external/libtommath-0.42.0/makefile.cygwin_dll +++ /dev/null @@ -1,55 +0,0 @@ -#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/external/libtommath-0.42.0/makefile.icc b/external/libtommath-0.42.0/makefile.icc deleted file mode 100755 index cf70ab0..0000000 --- a/external/libtommath-0.42.0/makefile.icc +++ /dev/null @@ -1,116 +0,0 @@ -#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/external/libtommath-0.42.0/makefile.msvc b/external/libtommath-0.42.0/makefile.msvc deleted file mode 100755 index 5edebec..0000000 --- a/external/libtommath-0.42.0/makefile.msvc +++ /dev/null @@ -1,40 +0,0 @@ -#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/external/libtommath-0.42.0/makefile.shared b/external/libtommath-0.42.0/makefile.shared deleted file mode 100755 index f17bbbd..0000000 --- a/external/libtommath-0.42.0/makefile.shared +++ /dev/null @@ -1,102 +0,0 @@ -#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/external/libtommath-0.42.0/mess.sh b/external/libtommath-0.42.0/mess.sh deleted file mode 100755 index bf639ce..0000000 --- a/external/libtommath-0.42.0/mess.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/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/external/libtommath-0.42.0/mtest/logtab.h b/external/libtommath-0.42.0/mtest/logtab.h deleted file mode 100755 index 04c1ad3..0000000 --- a/external/libtommath-0.42.0/mtest/logtab.h +++ /dev/null @@ -1,24 +0,0 @@ -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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/mtest/mpi-config.h b/external/libtommath-0.42.0/mtest/mpi-config.h deleted file mode 100755 index 21e72b2..0000000 --- a/external/libtommath-0.42.0/mtest/mpi-config.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Default configuration for MPI library */ -/* $ID$ */ - -#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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/mtest/mpi-types.h b/external/libtommath-0.42.0/mtest/mpi-types.h deleted file mode 100755 index a90f11e..0000000 --- a/external/libtommath-0.42.0/mtest/mpi-types.h +++ /dev/null @@ -1,20 +0,0 @@ -/* 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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/mtest/mpi.c b/external/libtommath-0.42.0/mtest/mpi.c deleted file mode 100755 index f6ef8c7..0000000 --- a/external/libtommath-0.42.0/mtest/mpi.c +++ /dev/null @@ -1,3985 +0,0 @@ -/* - mpi.c - - by Michael J. Fromberger - Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved - - Arbitrary precision integer arithmetic library - - $ID$ - */ - -#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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/mtest/mpi.h b/external/libtommath-0.42.0/mtest/mpi.h deleted file mode 100755 index 526c3fd..0000000 --- a/external/libtommath-0.42.0/mtest/mpi.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - mpi.h - - by Michael J. Fromberger - Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved - - Arbitrary precision integer arithmetic library - - $ID$ - */ - -#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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/mtest/mtest.c b/external/libtommath-0.42.0/mtest/mtest.c deleted file mode 100755 index 92f03ad..0000000 --- a/external/libtommath-0.42.0/mtest/mtest.c +++ /dev/null @@ -1,308 +0,0 @@ -/* 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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/pics/design_process.sxd b/external/libtommath-0.42.0/pics/design_process.sxd deleted file mode 100755 index 7414dbb27696fe716fe8c73a5c2b21d8c3e0c23c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6950 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 diff --git a/external/libtommath-0.42.0/pics/design_process.tif b/external/libtommath-0.42.0/pics/design_process.tif deleted file mode 100755 index 4a0c012d565ecd12a43186f132b3bccdefb9a23e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79042 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 diff --git a/external/libtommath-0.42.0/pics/expt_state.sxd b/external/libtommath-0.42.0/pics/expt_state.sxd deleted file mode 100755 index 6518404d5fa6eca01b4457a813f85cda074c0915..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6869 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 YjJ7)dxd~WU_~#EhHWpUWwTse!03-Pj!~g&Q diff --git a/external/libtommath-0.42.0/pics/expt_state.tif b/external/libtommath-0.42.0/pics/expt_state.tif deleted file mode 100755 index cb06e8edf17017dec815be222c845f1b0a938e07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87542 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≦RYV{r={iMn(Ta_rSwB@dOoKkT7uoB zm>DX9w4o@~>(T4B6{=OK>K|NB_%L#N5_JJ$;s!Q}qJxUPIv=G3bmrL^6**GGA-Da^ zCB;W@?#|o}7gXp1E%T~qJTaVw0a<51tcNsB*noTLp+>XomZ1Ci_CA7uD{ibGLLbrc zT5N_{Zw1xom9I4Oe+VzQ2k5ll zA-%4~x&F@$@1$Lx7H*QE4ps;-706f=e)ER!+<0`&_7;vu*;d5e1Hdmg$Ck3Xz9$sC zT>ES{8$3`HsFZJ6Uks3y*oEzf$AQ*8vU5r+r>OaZO5$V<)eAq!DSxli{Vj1eh?-@R zM7k^F;Y|5aSD@rah|h1E#LmpZ{%oA72Ak^saDSUZe9flmts$QgjZS-A>rwtj1TI?h zJ^0)V-fJB_dBC+fRKDKg8^@9qC

Gz?-?J@iV6)5~XACr^a8KN7>Cj@YUK!?WXXd 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 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/external/libtommath-0.42.0/pics/primality.tif b/external/libtommath-0.42.0/pics/primality.tif deleted file mode 100755 index 76d6be3fac2cc8b07a401e008fbe45f02758cef7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85514 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 diff --git a/external/libtommath-0.42.0/pics/radix.sxd b/external/libtommath-0.42.0/pics/radix.sxd deleted file mode 100755 index b9eb9a032d0b5229d4828911466490a95c126a2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6181 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 D!-Jt8 diff --git a/external/libtommath-0.42.0/pics/sliding_window.sxd b/external/libtommath-0.42.0/pics/sliding_window.sxd deleted file mode 100755 index 91e7c0d9f43b612ff0a59d86a71c8928fbd695f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6787 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 diff --git a/external/libtommath-0.42.0/pics/sliding_window.tif b/external/libtommath-0.42.0/pics/sliding_window.tif deleted file mode 100755 index bb4cb96ebff4e06478672dd3583bd26a51d85b5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53880 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 DSo1$6 diff --git a/external/libtommath-0.42.0/poster.out b/external/libtommath-0.42.0/poster.out deleted file mode 100644 index e69de29..0000000 diff --git a/external/libtommath-0.42.0/poster.tex b/external/libtommath-0.42.0/poster.tex deleted file mode 100755 index e7388f4..0000000 --- a/external/libtommath-0.42.0/poster.tex +++ /dev/null @@ -1,35 +0,0 @@ -\documentclass[landscape,11pt]{article} -\usepackage{amsmath, amssymb} -\usepackage{hyperref} -\begin{document} -\hspace*{-3in} -\begin{tabular}{llllll} -$c = a + b$ & {\tt mp\_add(\&a, \&b, \&c)} & $b = 2a$ & {\tt mp\_mul\_2(\&a, \&b)} & \\ -$c = a - b$ & {\tt mp\_sub(\&a, \&b, \&c)} & $b = a/2$ & {\tt mp\_div\_2(\&a, \&b)} & \\ -$c = ab $ & {\tt mp\_mul(\&a, \&b, \&c)} & $c = 2^ba$ & {\tt mp\_mul\_2d(\&a, b, \&c)} \\ -$b = a^2 $ & {\tt mp\_sqr(\&a, \&b)} & $c = a/2^b, d = a \mod 2^b$ & {\tt mp\_div\_2d(\&a, b, \&c, \&d)} \\ -$c = \lfloor a/b \rfloor, d = a \mod b$ & {\tt mp\_div(\&a, \&b, \&c, \&d)} & $c = a \mod 2^b $ & {\tt mp\_mod\_2d(\&a, b, \&c)} \\ - && \\ -$a = b $ & {\tt mp\_set\_int(\&a, b)} & $c = a \vee b$ & {\tt mp\_or(\&a, \&b, \&c)} \\ -$b = a $ & {\tt mp\_copy(\&a, \&b)} & $c = a \wedge b$ & {\tt mp\_and(\&a, \&b, \&c)} \\ - && $c = a \oplus b$ & {\tt mp\_xor(\&a, \&b, \&c)} \\ - & \\ -$b = -a $ & {\tt mp\_neg(\&a, \&b)} & $d = a + b \mod c$ & {\tt mp\_addmod(\&a, \&b, \&c, \&d)} \\ -$b = |a| $ & {\tt mp\_abs(\&a, \&b)} & $d = a - b \mod c$ & {\tt mp\_submod(\&a, \&b, \&c, \&d)} \\ - && $d = ab \mod c$ & {\tt mp\_mulmod(\&a, \&b, \&c, \&d)} \\ -Compare $a$ and $b$ & {\tt mp\_cmp(\&a, \&b)} & $c = a^2 \mod b$ & {\tt mp\_sqrmod(\&a, \&b, \&c)} \\ -Is Zero? & {\tt mp\_iszero(\&a)} & $c = a^{-1} \mod b$ & {\tt mp\_invmod(\&a, \&b, \&c)} \\ -Is Even? & {\tt mp\_iseven(\&a)} & $d = a^b \mod c$ & {\tt mp\_exptmod(\&a, \&b, \&c, \&d)} \\ -Is Odd ? & {\tt mp\_isodd(\&a)} \\ -&\\ -$\vert \vert a \vert \vert$ & {\tt mp\_unsigned\_bin\_size(\&a)} & $res$ = 1 if $a$ prime to $t$ rounds? & {\tt mp\_prime\_is\_prime(\&a, t, \&res)} \\ -$buf \leftarrow a$ & {\tt mp\_to\_unsigned\_bin(\&a, buf)} & Next prime after $a$ to $t$ rounds. & {\tt mp\_prime\_next\_prime(\&a, t, bbs\_style)} \\ -$a \leftarrow buf[0..len-1]$ & {\tt mp\_read\_unsigned\_bin(\&a, buf, len)} \\ -&\\ -$b = \sqrt{a}$ & {\tt mp\_sqrt(\&a, \&b)} & $c = \mbox{gcd}(a, b)$ & {\tt mp\_gcd(\&a, \&b, \&c)} \\ -$c = a^{1/b}$ & {\tt mp\_n\_root(\&a, b, \&c)} & $c = \mbox{lcm}(a, b)$ & {\tt mp\_lcm(\&a, \&b, \&c)} \\ -&\\ -Greater Than & MP\_GT & Equal To & MP\_EQ \\ -Less Than & MP\_LT & Bits per digit & DIGIT\_BIT \\ -\end{tabular} -\end{document} diff --git a/external/libtommath-0.42.0/pre_gen/mpi.c b/external/libtommath-0.42.0/pre_gen/mpi.c deleted file mode 100644 index 7ba9d83..0000000 --- a/external/libtommath-0.42.0/pre_gen/mpi.c +++ /dev/null @@ -1,9524 +0,0 @@ -/* Start: bn_error.c */ -#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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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; - int used = 1; - - if(a->used > 0) - used = a->used; - - if (a->alloc != used) { - if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * used)) == NULL) { - return MP_MEM; - } - a->dp = tmp; - a->alloc = used; - } - return MP_OKAY; -} -#endif - -/* $Source$ */ -/* $Revision: v0.42.0 $ */ -/* $Date: 2010-06-02 15:09:36 +0200 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* 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$ */ -/* $Revision: 0.41 $ */ -/* $Date: 2007-04-18 09:58:18 +0000 $ */ - -/* End: bncore.c */ - - -/* EOF */ diff --git a/external/libtommath-0.42.0/pretty.build b/external/libtommath-0.42.0/pretty.build deleted file mode 100755 index a708b8a..0000000 --- a/external/libtommath-0.42.0/pretty.build +++ /dev/null @@ -1,66 +0,0 @@ -#!/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/external/libtommath-0.42.0/tombc/grammar.txt b/external/libtommath-0.42.0/tombc/grammar.txt deleted file mode 100755 index a780e75..0000000 --- a/external/libtommath-0.42.0/tombc/grammar.txt +++ /dev/null @@ -1,35 +0,0 @@ -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/external/libtommath-0.42.0/tommath.h b/external/libtommath-0.42.0/tommath.h deleted file mode 100755 index cf9c499..0000000 --- a/external/libtommath-0.42.0/tommath.h +++ /dev/null @@ -1,584 +0,0 @@ -/* 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$ */ -/* $Revision: 0.39 $ */ -/* $Date: 2006-04-06 19:49:59 +0000 $ */ diff --git a/external/libtommath-0.42.0/tommath.out b/external/libtommath-0.42.0/tommath.out deleted file mode 100755 index 9f62617..0000000 --- a/external/libtommath-0.42.0/tommath.out +++ /dev/null @@ -1,139 +0,0 @@ -\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/external/libtommath-0.42.0/tommath.src b/external/libtommath-0.42.0/tommath.src deleted file mode 100755 index 4065822..0000000 --- a/external/libtommath-0.42.0/tommath.src +++ /dev/null @@ -1,6350 +0,0 @@ -\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. - -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/external/libtommath-0.42.0/tommath_class.h b/external/libtommath-0.42.0/tommath_class.h deleted file mode 100755 index 1e29c8f..0000000 --- a/external/libtommath-0.42.0/tommath_class.h +++ /dev/null @@ -1,999 +0,0 @@ -#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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtommath-0.42.0/tommath_superclass.h b/external/libtommath-0.42.0/tommath_superclass.h deleted file mode 100755 index 89d5516..0000000 --- a/external/libtommath-0.42.0/tommath_superclass.h +++ /dev/null @@ -1,76 +0,0 @@ -/* 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$ */ -/* $Revision: 0.36 $ */ -/* $Date: 2005-08-01 16:37:28 +0000 $ */ diff --git a/external/libtompoly-0.04/LICENSE b/external/libtompoly-0.04/LICENSE deleted file mode 100644 index 87c21ca..0000000 --- a/external/libtompoly-0.04/LICENSE +++ /dev/null @@ -1,4 +0,0 @@ -LibTomPoly is hereby placed in the Public Domain. - --- Tom St Denis - diff --git a/external/libtompoly-0.04/changes.txt b/external/libtompoly-0.04/changes.txt deleted file mode 100644 index d7ed38a..0000000 --- a/external/libtompoly-0.04/changes.txt +++ /dev/null @@ -1,24 +0,0 @@ -May 5th, 2004 -v0.04 - Fixed a bug in pb_monic() which for zero valued inputs could cause a segfault - - Daniel Richards (kyhwana@kyhwana.org) found several typos in the manual. - - Fixed bug in pb_shrink() that would leak memory - -Jan 25th, 2004 -v0.03 - Added pb_rawsize(), pb_readraw(), pb_toraw() - - Fixed bug in pb_monic() where it would only check the first [not leading] coefficient for one - -Jan 3rd, 2004 -v0.02 - Update pb_div() to shift r(x) after multplying it wit b(x) to save a bit of time - - improved pb_gcd() to handle inputs which are zero - - Added pb_shrink() - - fixed pb_invmod() - - added pb_exteuclid() [back ported that code into LTM... hehehe] - - added pb_exptmod() [this led me to find a bug in LTM!!!] - - added pb_monic() - - added pb_isirreduc() - - Some minor additions to test/documentation - -Dec 31st, 2003 -v0.01 ++ thanks goes to Martin Marcel, Greg Rose and Colin Percival for providing some missing knowledge and - helping me get this release going - - Initial release. diff --git a/external/libtompoly-0.04/demo/demo.c b/external/libtompoly-0.04/demo/demo.c deleted file mode 100644 index a6fe41c..0000000 --- a/external/libtompoly-0.04/demo/demo.c +++ /dev/null @@ -1,216 +0,0 @@ -#include - -void draw_poly(pb_poly *a) -{ - int x; - char buf[8192]; - - if (a->used == 0) { - printf("0"); - } else { - for (x = a->used - 1; x >= 0; x--) { - if (mp_iszero(&(a->terms[x])) == MP_YES) continue; - mp_toradix(&(a->terms[x]), buf, 10); - if ((x != a->used - 1) && a->terms[x].sign == MP_ZPOS) { - printf("+"); - } - printf(" %sx^%d ", buf, x); - } - } - if (mp_iszero(&(a->characteristic)) == MP_NO) { - mp_toradix(&(a->characteristic), buf, 10); - printf(" (mod %s)", buf); - } - printf("\n"); -} - -int main(void) -{ - mp_int chara; - pb_poly a,b,c,d,e; - mp_int aa,bb,cc,dd,ee; - int res; - - mp_init(&chara); - mp_init_multi(&aa,&bb,&cc,&dd,&ee,NULL); - pb_init_size(&a, &chara, 32); - pb_init_size(&b, &chara, 32); - pb_init_size(&c, &chara, 32); - pb_init_size(&d, &chara, 32); - pb_init_size(&e, &chara, 32); - - /* a = 3x + 4 */ - mp_set(&(a.terms[1]), 3); - mp_set(&(a.terms[0]), 4); - a.used = 2; - pb_clamp(&a); - printf("a == \n"); - draw_poly(&a); - - /* b = 7x^2 + 5x + 7 */ - mp_set(&(b.terms[2]), 7); - mp_set(&(b.terms[1]), 5); - mp_set(&(b.terms[0]), 7); - b.used = 3; - pb_clamp(&b); - printf("b == \n"); - draw_poly(&b); - - /* c = a + b */ - printf("a + b\n"); - pb_add(&a, &b, &c); - draw_poly(&c); - - /* c = b + a */ - printf("b + a\n"); - pb_add(&b, &a, &c); - draw_poly(&c); - - /* now test clearing */ - printf("Shifting previous up one\n"); - pb_lshd(&c, 1); - draw_poly(&c); - pb_rshd(&c, 1); - draw_poly(&c); - pb_lshd(&c, 1); - pb_add(&a, &b, &c); - printf("previous add (test if excess cleared)\n"); - draw_poly(&c); - - /* multiply */ - printf("Multiply:\n"); - draw_poly(&a); - draw_poly(&b); - pb_mul(&a, &b, &c); - draw_poly(&c); - - /* subtract */ - printf("a - b\n"); - pb_sub(&a, &b, &c); - draw_poly(&c); - printf("b - a\n"); - pb_sub(&b, &a, &c); - draw_poly(&c); - - - /* now hijack the char */ - mp_set(&(a.characteristic), 17); - mp_set(&(b.characteristic), 17); - mp_set(&(c.characteristic), 17); - mp_set(&(d.characteristic), 17); - mp_set(&(e.characteristic), 17); - - /* perform modular addition */ - printf("a + b (in GF(17))\n"); - pb_add(&a, &b, &c); - draw_poly(&c); - pb_add(&b, &a, &c); - draw_poly(&c); - - /* perform modular subtaction */ - printf("a - b (in GF(17))\n"); - pb_sub(&a, &b, &c); - draw_poly(&c); - printf("b - a (in GF(17))\n"); - pb_sub(&b, &a, &c); - draw_poly(&c); - - /* perform division */ - printf("Division (b/a)\n"); - pb_div(&b, &a, &c, &d); - draw_poly(&a); - draw_poly(&b); - printf("Q == \n"); draw_poly(&c); - printf("R == \n"); draw_poly(&d); - - /* now test it */ - pb_mul(&a, &c, &c); - pb_add(&c, &d, &c); - printf("aQ + R =\n"); draw_poly(&c); - - /* test mod */ - pb_mod(&b, &a, &c); - printf("b mod a == "); draw_poly(&c); - - /* test GCD of (x^2 - 1) and 5*x^4+5*x^3+7*x^2+8*x+1 [should be x+1] */ - printf("GCD Test\n"); - pb_zero(&a); - mp_set(&(a.terms[2]), 1); - mp_set(&(a.terms[0]), 16); - a.used = 3; - pb_clamp(&a); - printf("a == \n"); - draw_poly(&a); - - pb_zero(&b); - mp_set(&(b.terms[4]), 5); - mp_set(&(b.terms[3]), 5); - mp_set(&(b.terms[2]), 7); - mp_set(&(b.terms[1]), 8); - mp_set(&(b.terms[0]), 1); - b.used = 6; - pb_clamp(&b); - printf("b == \n"); - draw_poly(&b); - - pb_gcd(&a, &b, &c); - printf("GCD: "); draw_poly(&c); - - /* test GCD */ - pb_div(&a, &c, &d, &e); - printf("a/c == "); draw_poly(&d); printf("a mod c == "); draw_poly(&e); pb_mul(&d, &c, &e); printf("should be a: "); draw_poly(&e); - pb_div(&b, &c, &d, &e); - printf("b/c == "); draw_poly(&d); printf("b mod c == "); draw_poly(&e); pb_mul(&d, &c, &e); printf("should be b: "); draw_poly(&e); - - /* test modular inverse... x^2 + 3 or so should work nice */ - printf("Modular Inverse\n"); - pb_zero(&a); - mp_set(&(a.terms[2]), 1); - mp_set(&(a.terms[1]), 0); - mp_set(&(a.terms[0]), 3); - a.used = 3; - pb_clamp(&a); - printf("a == \n"); - draw_poly(&a); - - /* take inverse of 2x + 9 */ - pb_zero(&b); - mp_set(&(b.terms[1]), 2); - mp_set(&(b.terms[0]), 9); - b.used = 2; - pb_clamp(&b); - printf("b == \n"); - draw_poly(&b); - - /* invert */ - pb_invmod(&b, &a, &c); - printf("Inverse\n"); - draw_poly(&c); - - /* test */ - pb_mulmod(&b, &c, &a, &d); - pb_mul(&b, &c, &e); - printf("This should be 1 : "); draw_poly(&d); - printf("This should be equal to k*a + 1: "); draw_poly(&e); - - /* now b has order [dividing] 17^2 - 1 == 288 so b^287 should equal c */ - printf("exptmod test\n"); - mp_set(&aa, 287); - pb_exptmod(&b, &aa, &a, &d); - printf("This should be invmod : "); draw_poly(&d); - - /* test irreduc */ - printf("Irreducibility testing\n"); - pb_isirreduc(&a, &res); - printf("This should be 1 : %d\n", res); - - pb_isirreduc(&b, &res); - printf("This should be 0 : %d\n", res); - - - - return EXIT_SUCCESS; -} - - - diff --git a/external/libtompoly-0.04/makefile b/external/libtompoly-0.04/makefile deleted file mode 100644 index c14f34d..0000000 --- a/external/libtompoly-0.04/makefile +++ /dev/null @@ -1,56 +0,0 @@ -#Makefile for GCC by Tom St Denis -CFLAGS += -fPIC -I. -Os -Wall -W -I../libtommath-0.42.0 - -VERSION=0.04 - -#default files to install -LIBNAME=libtompoly.a -HEADERS=tompoly.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/libtompoly/pdf - -default: libtompoly.a - -OBJECTS = pb_init.o pb_clear.o pb_init_size.o pb_grow.o pb_copy.o pb_clamp.o pb_init_copy.o \ -pb_add.o pb_sub.o pb_mul.o pb_div.o pb_zero.o pb_lshd.o pb_rshd.o pb_exch.o pb_mod.o \ -pb_addmod.o pb_submod.o pb_mulmod.o pb_gcd.o pb_init_multi.o pb_clear_multi.o pb_invmod.o \ -pb_cmp.o pb_shrink.o pb_exteuclid.o pb_monic.o pb_exptmod.o pb_isirreduc.o pb_rawsize.o \ -pb_toraw.o pb_readraw.o - -libtompoly.a: $(OBJECTS) - ar $(ARFLAGS) libtompoly.a $(OBJECTS) - -install: libtompoly.a - install -d -g root -o root $(DESTDIR)$(LIBPATH) - install -d -g root -o root $(DESTDIR)$(INCPATH) - install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH) - install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH) - -demo: demo/demo.o libtompoly.a - gcc demo/demo.o libtompoly.a -ltommath -o pbdemo - -mandvi: pb.tex - echo "hello" > pb.ind - latex pb > /dev/null - latex pb > /dev/null - makeindex pb - latex pb > /dev/null - -manual: mandvi - pdflatex pb >/dev/null - -clean: - rm -f *.o *.a *.obj *.lib *.exe pbdemo demo/*.o demo/*.obj demo/*.exe - rm -f *.idx *.ilg *.ind *.lof *.out *.toc *.dvi *.log *.aux - -zipup: manual clean - cd .. ; rm -rf ltp* libtompoly-$(VERSION) ; mkdir libtompoly-$(VERSION) ; \ - cp -R ./libtompoly/* ./libtompoly-$(VERSION)/ ; \ - tar -c libtompoly-$(VERSION)/* | bzip2 -9vvc > ltp-$(VERSION).tar.bz2 ; \ - zip -9 -r ltp-$(VERSION).zip libtompoly-$(VERSION)/* diff --git a/external/libtompoly-0.04/makefile.msvc b/external/libtompoly-0.04/makefile.msvc deleted file mode 100644 index 8fddcd4..0000000 --- a/external/libtompoly-0.04/makefile.msvc +++ /dev/null @@ -1,17 +0,0 @@ -#Makefile for MSVC by Tom St Denis -CFLAGS = /W3 /Ox /I. - -default: tompoly.lib - -OBJECTS = pb_init.obj pb_clear.obj pb_init_size.obj pb_grow.obj pb_copy.obj pb_clamp.obj pb_init_copy.obj \ -pb_add.obj pb_sub.obj pb_mul.obj pb_div.obj pb_zero.obj pb_lshd.obj pb_rshd.obj pb_exch.obj pb_mod.obj \ -pb_addmod.obj pb_submod.obj pb_mulmod.obj pb_gcd.obj pb_init_multi.obj pb_clear_multi.obj pb_invmod.obj \ -pb_cmp.obj pb_shrink.obj pb_exteuclid.obj pb_monic.obj pb_exptmod.obj pb_isirreduc.obj pb_rawsize.obj \ -pb_toraw.obj pb_readraw.obj - -tompoly.lib: $(OBJECTS) - lib /out:tompoly.lib $(OBJECTS) - -demo: demo/demo.obj tompoly.lib - cl demo.obj tompoly.lib tommath.lib - diff --git a/external/libtompoly-0.04/pb.pdf b/external/libtompoly-0.04/pb.pdf deleted file mode 100644 index c15f7dcb78aebe7bc82883648f6b17b25a3f0cb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 193637 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 -\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}} -\def\gap{\vspace{0.5ex}} -\makeindex -\begin{document} -\frontmatter -\pagestyle{empty} -\title{LibTomPoly User Manual \\ v0.04} -\author{Tom St Denis \\ tomstdenis@iahu.ca} -\maketitle -This text and library are 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 LibTomPoly?} -LibTomPoly is a public domain open source library to provide polynomial basis arithmetic. It uses the public domain -library LibTomMath (not included) for the integer arithmetic and extends the functonality to provide polynomial arithmetic. - -Technically speaking the library allows the user to perform arithmetic on elements from the group $GF(p)[x]$ and to -a lesser extent (this will change in the future) over $\Z[x]$. Essentially the math you can do with integers (including -forming rings and fields) you can do with with polynomials and now you can do with LibTomPoly. - -\section{License} -LibTomPoly is public domain. Enjoy. - -\section{Terminology} -Throughout this manual and within the library there will be some terminology that not everyone is familiar with. It is afterall -weird math. - -\begin{figure}[here] -\begin{center} -\begin{small} -\begin{tabular}{|l|l|} -\hline \textbf{Term} & \textbf{Definition} \\ -\hline monic polynomial & A polynomial where the leading coefficient is a one. \\ -\hline irreducible polynomial & A polynomial that has no factors in a given group. \\ - & For instance, $x^2 + 4$ is irreducible in $\Z[x]$ but not \\ - & in $GF(17)[x]$ since $x^2 + 4 = (x+8)(x+9) \mbox{ (mod }17\mbox{)}$. \\ -\hline primitive polynomial & An irreducible polynomial which generates all of \\ - & elements of a given field (e.g. $GF(p)[x]/v(x)$) \\ -\hline characteristic & An integer $k$ such that $k \cdot p(x) \equiv 0$ \\ -\hline deg() & Functon returns degree of polynomial, e.g. deg($x^6 + x^3 + 1$) = 6 \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Terminology} -\end{figure} - -\section{Building the Library} -The library is not ready for production yet but you can test out the library manually if you want. To build the library -simply type - -\begin{alltt} -make -\end{alltt} - -Which will build ``libtompoly.a''. To build a Win32 library with MSVC type - -\begin{alltt} -nmake -f makefile.msvc -\end{alltt} - -To build against this library include ``tompoly.h'' and link against ``libtompoly.a'' (or tommath.lib as appropriate). -To build the included demo type - -\begin{alltt} -make demo -\end{alltt} - -Which will build ``demo'' in the current directory. The demo is not interactive and produces results which must be manually -inspected. - -\chapter{Getting Started} - -\section{The LibTomMath Connection} -LibTomPoly is really just an extension of LibTomMath\footnote{\url{http://math.libtomcrypt.org}}. As such the library has -been designed in much the same way as far as argument passing and error handling events are concerned. The reader is -encouraged to become familiar with LibTomMath before diving into LibTomPoly. - -\section{The pb\_poly structure} -A polynomial can characterized by a few variables. Given the C structure as follows - -\begin{alltt} -typedef struct \{ - int used, /* number of terms */ - alloc; /* number of terms available (total) */ - mp_int characteristic, /* characteristic, zero if not finite */ - *terms; /* terms of polynomial */ -\} pb_poly; -\end{alltt} - -\begin{enumerate} - \item The \textbf{used} member indicates how many terms of the \textbf{terms} array are used to represent the polynomial. - \item The \textbf{alloc} member indicates the size of the \textbf{terms} array. Also note that even if \textbf{used} - is less than \textbf{alloc} the mp\_ints above \textbf{used} in the array must be set to a valid representation - of zero. - \item The \textbf{characteristic} member is an mp\_int representing the characteristic of the polynomial. If the desire is to - have a null characteristic (e.g. $\Z[x]$) this element must still be initialized to a valid representation - of zero. - \item The \textbf{terms} member is a dynamically sized array of mp\_int values which represent the coefficients for - the terms of the polynomial. They start from least to most significant degree. E.g. $p(x) = \sum_{i=0}^{used-1} terms_i \cdot x^i$. -\end{enumerate} - -\section{Return Codes} -The library uses the return codes from LibTomMath. They are - -\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} - -\section{Function Argument Passing} -Just like LibTomMath the arguments are meant to be read left to right where the destination is on the right. Consider -the following. - -\begin{alltt} -pb_add(a, b, c); /* c = a + b */ -pb_mul(a, b, c); /* c = a * b */ -\end{alltt} - -Also like LibTomMath input arguments can be specified as output arguments. Consider. - -\begin{alltt} -pb_mul(a, b, a); /* a = a * b */ -pb_gcd(a, b, b); /* b = (a, b) */ -\end{alltt} - -However, polynomial math raises another consideration. The characteristic of the result is taken from the right most -argument passed to the function. Not all functions will return an error code if the characteristics of the inputs -do not match so it's important to keep this in mind. In general the results are undefined if not all of the polynomials -have identical characteristics. - -\section{Initializing Polynomials} -In order to use a pb\_poly structure with one of the functions in this library the structure must be initialized. -There are three functions provided to initialize pb\_poly structures. - -\subsection{Default Initialization} -\index{pb\_init} -\begin{alltt} -int pb_init(pb_poly *a, mp_int *characteristic); -\end{alltt} -This will initialize ``a'' with the given ``characteristic'' such that the polynomial represented is a constant zero. -The mp\_int characteristic must be a valid initialized mp\_int even if a characteristic of zero is desired. By default, -the polynomial will be initialized so there are ``PB\_TERMS'' terms available. This will grow automatically as required -by the other functions. - -\subsection{Initilization of Given Size} -\index{pb\_init\_size} -\begin{alltt} -int pb_init_size(pb_poly *a, mp_int *characteristic, int size); -\end{alltt} -This behaves similar to pb\_init() except it will allocate ``size'' terms to initialize instead of ``PB\_TERMS''. This -is useful if you happen to know in advance how many terms you want. - -\subsection{Initilization of a Copy} -\index{pb\_init\_copy} -\begin{alltt} -int pb_init_copy(pb_poly *a, pb_poly *b); -\end{alltt} - -This will initialize ``a'' so it is a verbatim copy of ``b''. It will copy the characteristic and all of the terms -from ``b'' into ``a''. - -\subsection{Freeing a Polynomial} -\index{pb\_clear} -\begin{alltt} -int pb_clear(pb_poly *a); -\end{alltt} - -This will free all the memory required by ``a'' and mark it as been freed. You can repeatedly pb\_clear() the same -pb\_poly safely. - -\chapter{Basic Operations} -\section{Comparison} -Comparisions with polynomials is a bit less intuitive then with integers. Is $x^2 + 3$ greater than $x^2 + x + 4$? To -create a rational form of comparison the following comparison codes were designed. - -\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{|l|l|} -\hline \textbf{Code} & \textbf{Meaning} \\ -\hline PB\_EQ & The polynomials are exactly equal \\ -\hline PB\_DEG\_LT & The left polynomial has a lower degree than the right. \\ -\hline PB\_DEG\_EQ & Both have the same degree. \\ -\hline PB\_DEG\_GT & The left polynomial has a higher degree than the right. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Compare Codes} -\end{figure} - -\index{pb\_cmp} -\begin{alltt} -int pb_cmp(pb_poly *a, pb_poly *b); -\end{alltt} - -This will compare the polynomial ``a'' to the left of the polynomial ``b''. It will return one of the four -codes listed above. Note that the function does not compare the characteristics. So if $a \in GF(17)[x]$ and -$b \in GF(11)[x]$ were both equal to $x^2 + 3$ they would compare to PB\_EQ. Whereas $x^3 + 4$ -would compare to PB\_DEG\_LT, $x^1 + 7$ would compare to $PB\_DEG\_GT$ and $x^2 + 7$ would compare to $PB\_DEG\_EQ$\footnote{If the polynomial $a$ were on the left for all three cases.}. - -\section{Copying and Swapping} -\index{pb\_copy} -\begin{alltt} -int pb_copy(pb_poly *src, pb_poly *dest); -\end{alltt} -This will copy the polynomial from ``src'' to ``dest'' verbatim. - -\index{pb\_exch} -\begin{alltt} -int pb_exch(pb_poly *a, pb_poly *b); -\end{alltt} -This will exchange the contents of ``a'' with ``b''. - -\section{Multiplying and Dividing by $x$} -\index{pb\_lshd} \index{pb\_rshd} -\begin{alltt} -int pb_lshd(pb_poly *a, int i); -int pb_rshd(pb_poly *a, int i); -\end{alltt} -These will multiply (or divide, respectfully) the polynomial ``a'' by $x^i$. If $i \le 0$ the functions return without -performing any operation. For example, - -\begin{alltt} -pb_lshd(a, 2); /* a(x) = a(x) * x^2 */ -pb_rshd(a, 7); /* a(x) = a(x) / x^7 */ -\end{alltt} - -\chapter{Basic Arithmetic} -\section{Addition, Subtraction and Multiplication} -\index{pb\_add} \index{pb\_sub} -\begin{alltt} -int pb_add(pb_poly *a, pb_poly *b, pb_poly *c); -int pb_sub(pb_poly *a, pb_poly *b, pb_poly *c); -int pb_mul(pb_poly *a, pb_poly *b, pb_poly *c); -\end{alltt} - -These will add (subtract or multiply, respectfully) the polynomial ``a'' and polynomial ``b'' and store the result in -polynomial ``c''. The characteristic from ``c'' is used to calculate the result. Note that the coefficients of ``c'' -will always be positive provided the characteristic of ``c'' is greater than zero. - -Quick examples of usage. - -\begin{alltt} -pb_add(a, b, c); /* c = a + b */ -pb_sub(b, a, c); /* c = b - a */ -pb_mul(c, a, a); /* a = c * a */ -\end{alltt} - -\section{Division} -\index{pb\_div} -\begin{alltt} -int pb_div(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d); -\end{alltt} -This will divide the polynomial ``a'' by ``b'' and store the quotient in ``c'' and remainder in ``d''. That is - -\begin{equation} -b(x) \cdot c(x) + d(x) = a(x) -\end{equation} - -The value of $deg(d(x))$ is always less than $deg(b(x))$. Either of ``c'' and ``d'' can be set to \textbf{NULL} to -signify their value is not desired. This is useful if you only want the quotient or remainder but not both. - -Since one of the destinations can be \textbf{NULL} the characteristic of the result is taken from ``b''. The function -will return an error if the characteristic of ``a'' differs from that of ``b''. - -This function is defined for polynomials in $GF(p)[x]$ only. A routine pb\_zdiv()\footnote{To be written!} allows the -division of polynomials in $\Z[x]$. - -\section{Modular Functions} -\index{pb\_addmod} \index{pb\_submod} \index{pb\_mulmod} -\begin{alltt} -int pb_addmod(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d); -int pb_submod(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d); -int pb_mulmod(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d); -\end{alltt} - -These add (subtract or multiply respectfully) the polynomial ``a'' and the polynomial ``b'' modulo the polynomial ``c'' -and store the result in the polynomial ``d''. - -\chapter{Algebraic Functions} - -\section{Monic Reductions} -\index{pb\_monic} -\begin{alltt} -int pb_monic(pb_poly *a, pb_poly *b) -\end{alltt} -Makes ``b'' the monic representation of ``a'' by ensuring the most significant coefficient is one. Only defined -over $GF(p)[x]$. Note that this is not a straight copy to ``b'' so you must ensure the characteristic of the two -are equal before you call the function\footnote{Note that $a == b$ is acceptable as well.}. Monic polynomials -are related to their original polynomial through an integer $k$ as follows - -\begin{equation} -a(x) \cdot k^{-1} \equiv b(x) -\end{equation} - -\section{Extended Euclidean Algorithm} -\index{pb\_exteuclid} -\begin{alltt} -int pb_exteuclid(pb_poly *a, pb_poly *b, - pb_poly *U1, pb_poly *U2, pb_poly *U3); -\end{alltt} - -This will compute the Euclidean algorithm and find values ``U1'', ``U2'', ``U3'' such that - -\begin{equation} -a(x) \cdot U1(x) + b(x) \cdot U2(x) = U3(x) -\end{equation} - -The value of ``U3'' is reduced to a monic polynomial. The three destination variables are all optional and can -be specified as \textbf{NULL} if they are not desired. - -\section{Greatest Common Divisor} -\index{pb\_gcd} -\begin{alltt} -int pb_gcd(pb_poly *a, pb_poly *b, pb_poly *c); -\end{alltt} -This finds the monic greatest common divisor of the two polynomials ``a'' and ``b'' and store the result in ``c''. The -operation is only defined over $GF(p)[x]$. - -\section{Modular Inverse} -\index{pb\_invmod} -\begin{alltt} -int pb_invmod(pb_poly *a, pb_poly *b, pb_poly *c); -\end{alltt} -This finds the modular inverse of ``a'' modulo ``b'' and stores the result in ``c''. The operation is only defined over -$GF(p)[x]$. If the operation succeed then the following congruency should hold true. - -\begin{equation} -a(x)c(x) \equiv 1 \mbox{ (mod }b(x)\mbox{)} -\end{equation} - -\section{Modular Exponentiation} -\index{pb\_exptmod} -\begin{alltt} -int pb_exptmod (pb_poly * G, mp_int * X, pb_poly * P, pb_poly * Y); -\end{alltt} - -This raise ``G'' to the power of ``X'' modulo ``P'' and stores the result in ``Y''. Or as a congruence - -\begin{equation} -Y(x) \equiv G(x)^X \mbox{ (mod }P(x)\mbox{)} -\end{equation} - -Where ``X'' can be negative\footnote{But in that case $G^{-1}(x)$ must exist modulo $P(x)$.} or positive. This function -is only defined over $GF(p)[x]$. - -\section{Irreducibility Testing} -\index{pb\_isirreduc} -\begin{alltt} -int pb_isirreduc(pb_poly *a, int *res); -\end{alltt} -Sets ``res'' to MP\_YES if ``a'' is irreducible (only for $GF(p)[x]$) otherwise sets ``res'' to MP\_NO. - -\input{pb.ind} - -\end{document} diff --git a/external/libtompoly-0.04/pb_add.c b/external/libtompoly-0.04/pb_add.c deleted file mode 100644 index eb3c8f7..0000000 --- a/external/libtompoly-0.04/pb_add.c +++ /dev/null @@ -1,73 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_add(pb_poly *a, pb_poly *b, pb_poly *c) -{ - int err, x, y, z, characteristic; - pb_poly *tmp; - - /* grow c to be the max size */ - y = MAX(a->used, b->used); - if (c->alloc < y) { - if ((err = pb_grow(c, y)) != MP_OKAY) { - return err; - } - } - - /* do we need to concern char */ - characteristic = mp_iszero(&(c->characteristic)); - - /* add the terms */ - z = MIN(a->used, b->used); - for (x = 0; x < z; x++) { - if ((err = mp_add(&(a->terms[x]), &(b->terms[x]), &(c->terms[x]))) != MP_OKAY) { - return err; - } - if (characteristic == MP_NO) { - if ((err = mp_mod(&(c->terms[x]), &(c->characteristic), &(c->terms[x]))) != MP_OKAY) { - return err; - } - } - } - - /* excess digits? */ - if (y != z) { - if (a->used == y) { - tmp = a; - } else { - tmp = b; - } - for (x = z; x < y; x++) { - if (characteristic == MP_NO) { - if ((err = mp_mod(&(tmp->terms[x]), &(c->characteristic), &(c->terms[x]))) != MP_OKAY) { - return err; - } - } else { - if ((err = mp_copy(&(tmp->terms[x]), &(c->terms[x]))) != MP_OKAY) { - return err; - } - } - } - } - - /* zero excess */ - for (x = y; x < c->used; x++) { - mp_zero(&(c->terms[x])); - } - c->used = y; - pb_clamp(c); - - return MP_OKAY; -} - - diff --git a/external/libtompoly-0.04/pb_addmod.c b/external/libtompoly-0.04/pb_addmod.c deleted file mode 100644 index 7587e1e..0000000 --- a/external/libtompoly-0.04/pb_addmod.c +++ /dev/null @@ -1,35 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_addmod(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d) -{ - int err; - pb_poly tmp; - - if ((err = pb_init(&tmp, &(d->characteristic))) != MP_OKAY) { - return err; - } - if ((err = pb_add(a, b, &tmp)) != MP_OKAY) { - goto __TMP; - } - if ((err = pb_mod(&tmp, c, d)) != MP_OKAY) { - goto __TMP; - } - - err = MP_OKAY; -__TMP: pb_clear(&tmp); - return err; -} - - - diff --git a/external/libtompoly-0.04/pb_clamp.c b/external/libtompoly-0.04/pb_clamp.c deleted file mode 100644 index c99e7b4..0000000 --- a/external/libtompoly-0.04/pb_clamp.c +++ /dev/null @@ -1,21 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -void pb_clamp(pb_poly *a) -{ - while (a->used > 0 && (mp_iszero(&(a->terms[a->used-1])) == MP_YES)) { - --(a->used); - } -} - - diff --git a/external/libtompoly-0.04/pb_clear.c b/external/libtompoly-0.04/pb_clear.c deleted file mode 100644 index ecfb5c0..0000000 --- a/external/libtompoly-0.04/pb_clear.c +++ /dev/null @@ -1,32 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -void pb_clear(pb_poly *a) -{ - int x; - - if (a->terms != NULL) { - /* free stuff */ - for (x = 0; x < a->alloc; x++) { - mp_clear(&(a->terms[x])); - } - free(a->terms); - mp_clear(&(a->characteristic)); - - /* prevent double frees */ - a->terms = NULL; - a->alloc = a->used = 0; - } -} - - diff --git a/external/libtompoly-0.04/pb_clear_multi.c b/external/libtompoly-0.04/pb_clear_multi.c deleted file mode 100644 index a1dff4a..0000000 --- a/external/libtompoly-0.04/pb_clear_multi.c +++ /dev/null @@ -1,25 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include -#include - -void pb_clear_multi(pb_poly *mp, ...) -{ - pb_poly* next_mp = mp; - va_list args; - va_start(args, mp); - while (next_mp != NULL) { - pb_clear(next_mp); - next_mp = va_arg(args, pb_poly*); - } - va_end(args); -} diff --git a/external/libtompoly-0.04/pb_cmp.c b/external/libtompoly-0.04/pb_cmp.c deleted file mode 100644 index 0812d61..0000000 --- a/external/libtompoly-0.04/pb_cmp.c +++ /dev/null @@ -1,32 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_cmp(pb_poly *a, pb_poly *b) -{ - int x; - - if (a->used > b->used) { - return PB_DEG_GT; - } else if (a->used < b->used) { - return PB_DEG_LT; - } - - for (x = 0; x < a->used; x++) { - if (mp_cmp(&(a->terms[x]), &(b->terms[x])) != MP_EQ) { - return PB_DEG_EQ; - } - } - return PB_EQ; -} - - diff --git a/external/libtompoly-0.04/pb_copy.c b/external/libtompoly-0.04/pb_copy.c deleted file mode 100644 index d9ae366..0000000 --- a/external/libtompoly-0.04/pb_copy.c +++ /dev/null @@ -1,51 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -/* dest = src */ -int pb_copy(pb_poly *src, pb_poly *dest) -{ - int err, x; - - /* avoid trivial copies */ - if (src == dest) { - return MP_OKAY; - } - - /* grow dest as required */ - if (dest->alloc < src->used) { - if ((err = pb_grow(dest, src->used)) != MP_OKAY) { - return err; - } - } - - /* set the characteristic */ - if ((err = mp_copy(&(src->characteristic), &(dest->characteristic))) != MP_OKAY) { - return err; - } - - /* copy digits */ - for (x = 0; x < src->used; x++) { - if ((err = mp_copy(&(src->terms[x]), &(dest->terms[x]))) != MP_OKAY) { - return err; - } - } - - /* zero excess digits */ - for (x = src->used; x < dest->used; x++) { - mp_zero(&(dest->terms[x])); - } - dest->used = src->used; - return MP_OKAY; -} - - diff --git a/external/libtompoly-0.04/pb_div.c b/external/libtompoly-0.04/pb_div.c deleted file mode 100644 index 84d5665..0000000 --- a/external/libtompoly-0.04/pb_div.c +++ /dev/null @@ -1,135 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - - -/* Divides a by b (uses the char of b as the char of the result) only for - * polynomials over GF(p^k)[x] - */ -int pb_div(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d) -{ - int err, x; - pb_poly p, q, r; - mp_int tmp, tmp2; - - /* if ||b|| > ||a|| it's a simple copy over */ - if (b->used > a->used) { - if (d != NULL) { - pb_copy(a, d); - } - if (c != NULL) { - pb_zero(c); - } - } - - /* zero divisor */ - if (b->used == 0) { - return MP_VAL; - } - - /* compare chars */ - if (mp_cmp(&(a->characteristic), &(b->characteristic)) != MP_EQ) { - return MP_VAL; - } - - /* we don't support char zero! */ - if (mp_iszero(&(b->characteristic)) == MP_YES) { - return MP_VAL; - } - - /* get a copy of "a" to work with */ - if ((err = pb_init_copy(&p, a)) != MP_OKAY) { - return err; - } - - /* init a temp quotient */ - if ((err = pb_init_size(&q, &(b->characteristic), a->used - b->used + 1)) != MP_OKAY) { - goto __P; - } - - /* init a temp polynomial we can work with */ - if ((err = pb_init_size(&r, &(b->characteristic), a->used)) != MP_OKAY) { - goto __Q; - } - - /* now init an mp_int we can work with */ - if ((err = mp_init(&tmp)) != MP_OKAY) { - goto __R; - } - - /* and the inverse of the leading digit of b(x) */ - if ((err = mp_init(&tmp2)) != MP_OKAY) { - goto __TMP; - } - if ((err = mp_invmod(&(b->terms[b->used - 1]), &(b->characteristic), &tmp2)) != MP_OKAY) { - goto __TMP2; - } - - /* now let's reduce us some digits */ - for (x = a->used - 1; x >= b->used-1; x--) { - /* skip zero digits */ - if (mp_iszero(&(p.terms[x])) == MP_YES) { - continue; - } - - /* now we have a leading digit of p(x), call it A - and a leading digit of b(x), call it B - - Now we want to reduce it so we need A + CB = 0 which turns into - A + CB = 0 - CB = -A - C = -A/B - - So we multiply b(x) by C * x^k [where k = ||p(x)|| - ||b(x)||], add that to p(x) and - we must reduced one digit - */ - - /* multiply 1/B [tmp2] by A */ - if ((err = mp_mulmod(&tmp2, &(p.terms[x]), &(b->characteristic), &tmp)) != MP_OKAY) { goto __TMP2; } - - /* tmp is now a term of the quotient */ - if ((err = mp_copy(&tmp, &(q.terms[x - b->used + 1]))) != MP_OKAY) { goto __TMP2; } - - /* create r(x) = C */ - pb_zero(&r); - if ((err = mp_copy(&tmp, &(r.terms[0]))) != MP_OKAY) { goto __TMP2; } - r.used = 1; - - /* now multiply r(x) by b(x)*x^k and subtract from p(x) */ - if ((err = pb_mul(b, &r, &r)) != MP_OKAY) { goto __TMP2; } - if ((err = pb_lshd(&r, x - b->used + 1)) != MP_OKAY) { goto __TMP2; } - if ((err = pb_sub(&p, &r, &p)) != MP_OKAY) { goto __TMP2; } - } - - /* setup q properly (so q.used is valid) */ - q.used = a->used; - pb_clamp(&q); - - /* ok so now p(x) is the remainder and q(x) is the quotient */ - if (c != NULL) { - pb_exch(&q, c); - } - if (d != NULL) { - pb_exch(&p, d); - } - - err = MP_OKAY; - -__TMP2: mp_clear(&tmp2); -__TMP : mp_clear(&tmp); -__R : pb_clear(&r); -__Q : pb_clear(&q); -__P : pb_clear(&p); - return err; -} - - diff --git a/external/libtompoly-0.04/pb_exch.c b/external/libtompoly-0.04/pb_exch.c deleted file mode 100644 index b2925b9..0000000 --- a/external/libtompoly-0.04/pb_exch.c +++ /dev/null @@ -1,20 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -void pb_exch(pb_poly *a, pb_poly *b) -{ - pb_poly tmp; - tmp = *a; *a = *b; *b = tmp; -} - - diff --git a/external/libtompoly-0.04/pb_exptmod.c b/external/libtompoly-0.04/pb_exptmod.c deleted file mode 100644 index e203b72..0000000 --- a/external/libtompoly-0.04/pb_exptmod.c +++ /dev/null @@ -1,186 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -#ifdef MP_LOW_MEM - #define TAB_SIZE 32 -#else - #define TAB_SIZE 256 -#endif - -int pb_exptmod (pb_poly * G, mp_int * X, pb_poly * P, pb_poly * Y) -{ - pb_poly M[TAB_SIZE], res; - mp_digit buf; - int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; - - /* 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 = pb_init(&M[1], &(Y->characteristic))) != MP_OKAY) { - return err; - } - - /* now init the second half of the array */ - for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - if ((err = pb_init(&M[x], &(Y->characteristic))) != MP_OKAY) { - for (y = 1<<(winsize-1); y < x; y++) { - pb_clear (&M[y]); - } - pb_clear(&M[1]); - return err; - } - } - - /* 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 (X->sign == MP_ZPOS) { - if ((err = pb_mod (G, P, &M[1])) != MP_OKAY) { goto __M; } - } else { - if ((err = pb_invmod(G, P, &M[1])) != MP_OKAY) { goto __M; } - } - - /* compute the value at M[1<<(winsize-1)] by squaring - * M[1] (winsize-1) times - */ - if ((err = pb_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { goto __M; } - - for (x = 0; x < (winsize - 1); x++) { - if ((err = pb_mulmod (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)], - P, &M[1 << (winsize - 1)])) != MP_OKAY) { goto __M; } - } - - /* 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 = pb_mulmod (&M[x - 1], &M[1], P, &M[x])) != MP_OKAY) { goto __M; } - } - - /* setup result */ - if ((err = pb_init (&res, &(Y->characteristic))) != MP_OKAY) { goto __M; } - mp_set (&(res.terms[0]), 1); res.used = 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 = pb_mulmod (&res, &res, P, &res)) != MP_OKAY) { goto __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 = pb_mulmod (&res, &res, P, &res)) != MP_OKAY) { goto __RES; } - } - - /* then multiply */ - if ((err = pb_mulmod (&res, &M[bitbuf], P, &res)) != MP_OKAY) { goto __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 = pb_mulmod (&res, &res, P, &res)) != MP_OKAY) { goto __RES; } - - bitbuf <<= 1; - if ((bitbuf & (1 << winsize)) != 0) { - /* then multiply */ - if ((err = pb_mulmod (&res, &M[1], P, &res)) != MP_OKAY) { goto __RES; } - } - } - } - - pb_exch (&res, Y); - err = MP_OKAY; -__RES:pb_clear (&res); -__M: - pb_clear(&M[1]); - for (x = 1<<(winsize-1); x < (1 << winsize); x++) { - pb_clear (&M[x]); - } - return err; -} diff --git a/external/libtompoly-0.04/pb_exteuclid.c b/external/libtompoly-0.04/pb_exteuclid.c deleted file mode 100644 index 2fb6911..0000000 --- a/external/libtompoly-0.04/pb_exteuclid.c +++ /dev/null @@ -1,74 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -/* Extended euclidean algorithm of (a, b) produces - a*u1 + b*u2 = u3 - */ -int pb_exteuclid(pb_poly *a, pb_poly *b, pb_poly *U1, pb_poly *U2, pb_poly *U3) -{ - pb_poly u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp; - int err; - - if ((err = pb_init_multi(&(b->characteristic), - &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.terms[0]), 1); u1.used = 1; - if ((err = pb_copy(a, &u3)) != MP_OKAY) { goto _ERR; } - - /* initialize, (v1,v2,v3) = (0,1,b) */ - mp_set(&(v2.terms[0]), 1); v2.used = 1; - if ((err = pb_copy(b, &v3)) != MP_OKAY) { goto _ERR; } - - /* loop while v3 != 0 */ - while (v3.used > 0) { - /* q = u3/v3 */ - if ((err = pb_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; } - - /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ - if ((err = pb_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; } - if ((err = pb_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; } - if ((err = pb_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; } - if ((err = pb_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; } - if ((err = pb_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; } - if ((err = pb_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; } - - /* (u1,u2,u3) = (v1,v2,v3) */ - if ((err = pb_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; } - if ((err = pb_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; } - if ((err = pb_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; } - - /* (v1,v2,v3) = (t1,t2,t3) */ - if ((err = pb_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; } - if ((err = pb_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; } - if ((err = pb_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; } - } - - /* reduce U3 to monic but we have to mangle all three to remain consistent */ - pb_zero(&v1); - if ((err = mp_copy(&(u3.terms[u3.used-1]), &(v1.terms[0]))) != MP_OKAY) { goto _ERR; } - v1.used = 1; - - /* copy result out */ - if (U1 != NULL) { if ((err = pb_div(&u1, &v1, U1, NULL)) != MP_OKAY) { goto _ERR; }} - if (U2 != NULL) { if ((err = pb_div(&u2, &v1, U2, NULL)) != MP_OKAY) { goto _ERR; }} - if (U3 != NULL) { if ((err = pb_div(&u3, &v1, U3, NULL)) != MP_OKAY) { goto _ERR; }} - - err = MP_OKAY; -_ERR: pb_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); - return err; -} - - diff --git a/external/libtompoly-0.04/pb_gcd.c b/external/libtompoly-0.04/pb_gcd.c deleted file mode 100644 index 12749b6..0000000 --- a/external/libtompoly-0.04/pb_gcd.c +++ /dev/null @@ -1,69 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -/* returns the monic GCD only for GF(p^k)[x] */ -int pb_gcd(pb_poly *a, pb_poly *b, pb_poly *c) -{ - pb_poly A, B, tmp; - int err; - - if (mp_iszero(&(c->characteristic)) == MP_YES) { - return MP_VAL; - } - - /* special cases (one or both are zero) */ - if (a->used == 0 && b->used == 0) { - /* both zero, set to 1 */ - pb_zero(c); - c->used = 1; - mp_set(&(c->terms[0]), 1); - return MP_OKAY; - } else if (a->used == 0) { - return pb_copy(b, c); - } else if (b->used == 0) { - return pb_copy(a, c); - } - - if ((err = pb_init(&tmp, &(c->characteristic))) != MP_OKAY) { - return err; - } - if ((err = pb_init_copy(&A, a)) != MP_OKAY) { - goto __TMP; - } - if ((err = pb_init_copy(&B, b)) != MP_OKAY) { - goto __A; - } - - while (B.used > 0) { - if ((err = pb_mod(&A, &B, &tmp)) != MP_OKAY) { - goto __B; - } - /* A = B, B = tmp */ - if ((err = pb_copy(&B, &A)) != MP_OKAY) { - goto __B; - } - if ((err = pb_copy(&tmp, &B)) != MP_OKAY) { - goto __B; - } - } - - /* ensure it's monic */ - err = pb_monic(&A, c); - -__B : pb_clear(&B); -__A : pb_clear(&A); -__TMP: pb_clear(&tmp); - return err; -} - - diff --git a/external/libtompoly-0.04/pb_grow.c b/external/libtompoly-0.04/pb_grow.c deleted file mode 100644 index b9e34e5..0000000 --- a/external/libtompoly-0.04/pb_grow.c +++ /dev/null @@ -1,46 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_grow(pb_poly *a, int size) -{ - mp_int *tmp; - int x, err; - - if (a->alloc < size) { - /* pad size upwards */ - size += (PB_TERMS - (size % PB_TERMS)); - - /* regrow terms */ - tmp = realloc(a->terms, sizeof(mp_int) * size); - if (tmp == NULL) { - return MP_MEM; - } - a->terms = tmp; - - /* zero the new stuff (prevents mp_clear from double freeing) */ - memset(a->terms + a->alloc, 0, (size - a->alloc) * sizeof(mp_int)); - - /* now init the terms */ - for (x = a->alloc; x < size; x++) { - if ((err = mp_init(&(a->terms[x]))) != MP_OKAY) { - return err; - } - } - - /* update info */ - a->alloc = size; - } - return MP_OKAY; -} - - diff --git a/external/libtompoly-0.04/pb_init.c b/external/libtompoly-0.04/pb_init.c deleted file mode 100644 index c312534..0000000 --- a/external/libtompoly-0.04/pb_init.c +++ /dev/null @@ -1,49 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -/* initialize a */ -int pb_init(pb_poly *a, mp_int *characteristic) -{ - int x, y, err; - - /* init characteristic */ - if ((err = mp_init_copy(&(a->characteristic), characteristic)) != MP_OKAY) { - return err; - } - - /* now allocate an array of mp_ints */ - if ((a->terms = calloc(PB_TERMS, sizeof(mp_int))) == NULL) { - mp_clear(&(a->characteristic)); - return MP_MEM; - } - - /* now initialize them all */ - for (x = 0; x < PB_TERMS; x++) { - if ((err = mp_init(&(a->terms[x]))) != MP_OKAY) { - /* free stuff */ - for (y = 0; y < x; y++) { - mp_clear(&(a->terms[y])); - } - free(a->terms); - mp_clear(&(a->characteristic)); - return err; - } - } - - /* set our parameters */ - a->used = 0; - a->alloc = PB_TERMS; - return MP_OKAY; -} - - diff --git a/external/libtompoly-0.04/pb_init_copy.c b/external/libtompoly-0.04/pb_init_copy.c deleted file mode 100644 index dc93f2f..0000000 --- a/external/libtompoly-0.04/pb_init_copy.c +++ /dev/null @@ -1,21 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_init_copy(pb_poly *a, pb_poly *b) -{ - int err; - if ((err = pb_init(a, &(b->characteristic))) != MP_OKAY) { - return err; - } - return pb_copy(b, a); -} diff --git a/external/libtompoly-0.04/pb_init_multi.c b/external/libtompoly-0.04/pb_init_multi.c deleted file mode 100644 index f704b86..0000000 --- a/external/libtompoly-0.04/pb_init_multi.c +++ /dev/null @@ -1,50 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include -#include - -int pb_init_multi(mp_int *characteristic, pb_poly *pb, ...) -{ - mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ - int n = 0; /* Number of ok inits */ - pb_poly* cur_arg = pb; - va_list args; - - va_start(args, pb); /* init args to next argument from caller */ - while (cur_arg != NULL) { - if (pb_init(cur_arg, characteristic) != 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 = pb; - va_start(clean_args, pb); - while (n--) { - pb_clear(cur_arg); - cur_arg = va_arg(clean_args, pb_poly*); - } - va_end(clean_args); - res = MP_MEM; - break; - } - n++; - cur_arg = va_arg(args, pb_poly*); - } - va_end(args); - return res; /* Assumed ok, if error flagged above. */ -} - diff --git a/external/libtompoly-0.04/pb_init_size.c b/external/libtompoly-0.04/pb_init_size.c deleted file mode 100644 index bf44027..0000000 --- a/external/libtompoly-0.04/pb_init_size.c +++ /dev/null @@ -1,58 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -/* initialize a */ -int pb_init_size(pb_poly *a, mp_int *characteristic, int size) -{ - int x, y, err; - - /* enforce a minimum size */ - if (size < 1) { - size = 1; - } - - /* pad size upwards */ - size += (PB_TERMS - (size % PB_TERMS)); - - - /* init characteristic */ - if ((err = mp_init_copy(&(a->characteristic), characteristic)) != MP_OKAY) { - return err; - } - - /* now allocate an array of mp_ints */ - if ((a->terms = calloc(size, sizeof(mp_int))) == NULL) { - mp_clear(&(a->characteristic)); - return MP_MEM; - } - - /* now initialize them all */ - for (x = 0; x < size; x++) { - if ((err = mp_init(&(a->terms[x]))) != MP_OKAY) { - /* free stuff */ - for (y = 0; y < x; y++) { - mp_clear(&(a->terms[y])); - } - free(a->terms); - mp_clear(&(a->characteristic)); - return err; - } - } - - /* set our parameters */ - a->used = 0; - a->alloc = size; - return MP_OKAY; -} - - diff --git a/external/libtompoly-0.04/pb_invmod.c b/external/libtompoly-0.04/pb_invmod.c deleted file mode 100644 index 5607dec..0000000 --- a/external/libtompoly-0.04/pb_invmod.c +++ /dev/null @@ -1,33 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_invmod(pb_poly *a, pb_poly *b, pb_poly *c) -{ - int err; - pb_poly tmp; - - if ((err = pb_init(&tmp, &(c->characteristic))) != MP_OKAY) { - return err; - } - - if ((err = pb_exteuclid(a, b, c, NULL, &tmp)) != MP_OKAY) { goto _ERR; } - - /* if deg(tmp(x)) > 0 then there is no invmod */ - if (tmp.used > 1) { err = MP_VAL; goto _ERR; } - - err = MP_OKAY; -_ERR: pb_clear(&tmp); - return err; -} - - diff --git a/external/libtompoly-0.04/pb_isirreduc.c b/external/libtompoly-0.04/pb_isirreduc.c deleted file mode 100644 index 7600386..0000000 --- a/external/libtompoly-0.04/pb_isirreduc.c +++ /dev/null @@ -1,59 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -/* is a(x) irreducible? */ -int pb_isirreduc(pb_poly *a, int *res) -{ - pb_poly u, tmp, fm, d; - int err, i; - - /* default to no */ - *res = MP_NO; - - /* init temps */ - if ((err = pb_init_multi(&(a->characteristic), - &u, &tmp, &fm, &d, NULL)) != MP_OKAY) { - return err; - } - - /* fm = monic(a(x)) */ - if ((err = pb_monic(a, &fm)) != MP_OKAY) { goto _ERR; } - - /* u = x */ - mp_set(&(u.terms[1]), 1); u.used = 2; - - /* loop */ - for (i = 1; i <= (a->used / 2); i++) { - /* u = u^p mod fm */ - if ((err = pb_exptmod(&u, &(a->characteristic), &fm, &u)) != MP_OKAY) { goto _ERR; } - - /* tmp = u - x */ - pb_zero(&tmp); - mp_set(&(tmp.terms[1]), 1); tmp.used = 2; - if ((err = pb_sub(&u, &tmp, &tmp)) != MP_OKAY) { goto _ERR; } - - /* d = gcd(fm, tmp) */ - if ((err = pb_gcd(&fm, &tmp, &d)) != MP_OKAY) { goto _ERR; } - - /* if d != 1 then reducible */ - if (d.used > 1) { err = MP_OKAY; goto _ERR; } - } - - /* irreducible */ - *res = MP_YES; - err = MP_OKAY; -_ERR: pb_clear_multi(&u, &tmp, &fm, &d, NULL); - return err; -} - - diff --git a/external/libtompoly-0.04/pb_lshd.c b/external/libtompoly-0.04/pb_lshd.c deleted file mode 100644 index 155b391..0000000 --- a/external/libtompoly-0.04/pb_lshd.c +++ /dev/null @@ -1,42 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_lshd(pb_poly *a, int x) -{ - int err, y; - - if (x <= 0) { - return MP_OKAY; - } - - /* grow as required */ - if (a->alloc < (a->used + x)) { - if ((err = pb_grow(a, a->used + x)) != MP_OKAY) { - return err; - } - } - - /* shift */ - for (y = a->used + x; y >= x; y--) { - mp_exch(&(a->terms[y-x]), &(a->terms[y])); - } - - /* zero lower digits */ - for (y = 0; y < x; y++) { - mp_zero(&(a->terms[y])); - } - a->used += x; - - return MP_OKAY; -} - diff --git a/external/libtompoly-0.04/pb_mod.c b/external/libtompoly-0.04/pb_mod.c deleted file mode 100644 index 4be21e9..0000000 --- a/external/libtompoly-0.04/pb_mod.c +++ /dev/null @@ -1,19 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_mod(pb_poly *a, pb_poly *b, pb_poly *c) -{ - return pb_div(a, b, NULL, c); -} - - diff --git a/external/libtompoly-0.04/pb_monic.c b/external/libtompoly-0.04/pb_monic.c deleted file mode 100644 index 19107bb..0000000 --- a/external/libtompoly-0.04/pb_monic.c +++ /dev/null @@ -1,60 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -/* makes b equal to the monic polynomial form of a */ -int pb_monic(pb_poly *a, pb_poly *b) -{ - mp_int tmp; - int err, x; - - /* must be in GF(p)[x] */ - if (mp_iszero(&(b->characteristic)) == MP_YES) { - return MP_VAL; - } - - /* if it's already monic just copy */ - if (a->used == 0 || mp_cmp_d(&(a->terms[a->used - 1]), 1) == MP_EQ) { - return pb_copy(a, b); - } - - /* grow b to hold result */ - if (b->alloc < a->used) { - if ((err = pb_grow(b, a->used)) != MP_OKAY) { - return err; - } - } - - /* now init tmp and find the inverse of the leading digit */ - if ((err = mp_init(&tmp)) != MP_OKAY) { - return err; - } - - if ((err = mp_invmod(&(a->terms[a->used-1]), &(b->characteristic), &tmp)) != MP_OKAY) { goto _ERR; } - - /* now reduce each coefficient */ - for (x = 0; x < a->used; x++) { - if ((err = mp_mulmod(&(a->terms[x]), &tmp, &(b->characteristic), &(b->terms[x]))) != MP_OKAY) { goto _ERR; } - } - - /* zero excess digits */ - for (x = a->used; x < b->used; x++) { - mp_zero(&(b->terms[x])); - } - b->used = a->used; - - err = MP_OKAY; -_ERR: mp_clear(&tmp); - return err; -} - - diff --git a/external/libtompoly-0.04/pb_mul.c b/external/libtompoly-0.04/pb_mul.c deleted file mode 100644 index b215f54..0000000 --- a/external/libtompoly-0.04/pb_mul.c +++ /dev/null @@ -1,62 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_mul(pb_poly *a, pb_poly *b, pb_poly *c) -{ - int err, x, y; - pb_poly tmp; - mp_int tmp2; - - /* make temp */ - if ((err = pb_init_size(&tmp, &(c->characteristic), a->used + b->used)) != MP_OKAY) { - return err; - } - - if ((err = mp_init(&tmp2)) != MP_OKAY) { - goto __TMP; - } - - /* multiply the terms */ - for (x = 0; x < a->used; x++) { - for (y = 0; y < b->used; y++) { - if ((err = mp_mul(&(a->terms[x]), &(b->terms[y]), &tmp2)) != MP_OKAY) { - goto __TMP2; - } - if ((err = mp_add(&tmp2, &(tmp.terms[x+y]), &(tmp.terms[x+y]))) != MP_OKAY) { - goto __TMP2; - } - } - } - - /* now reduce the terms as required */ - if (mp_iszero(&(c->characteristic)) == MP_NO) { - for (x = 0; x < (a->used + b->used); x++) { - if ((err = mp_mod(&(tmp.terms[x]), &(c->characteristic), &(tmp.terms[x]))) != MP_OKAY) { - goto __TMP2; - } - } - } - - /* set digit count */ - tmp.used = a->used + b->used; - pb_clamp(&tmp); - - /* exchange tmp and c */ - pb_exch(&tmp, c); - - err = MP_OKAY; - -__TMP2: mp_clear(&tmp2); -__TMP : pb_clear(&tmp); - return err; -} diff --git a/external/libtompoly-0.04/pb_mulmod.c b/external/libtompoly-0.04/pb_mulmod.c deleted file mode 100644 index b960043..0000000 --- a/external/libtompoly-0.04/pb_mulmod.c +++ /dev/null @@ -1,35 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_mulmod(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d) -{ - int err; - pb_poly tmp; - - if ((err = pb_init(&tmp, &(d->characteristic))) != MP_OKAY) { - return err; - } - if ((err = pb_mul(a, b, &tmp)) != MP_OKAY) { - goto __TMP; - } - if ((err = pb_mod(&tmp, c, d)) != MP_OKAY) { - goto __TMP; - } - - err = MP_OKAY; -__TMP: pb_clear(&tmp); - return err; -} - - - diff --git a/external/libtompoly-0.04/pb_rawsize.c b/external/libtompoly-0.04/pb_rawsize.c deleted file mode 100644 index 43ccc76..0000000 --- a/external/libtompoly-0.04/pb_rawsize.c +++ /dev/null @@ -1,32 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_rawsize(pb_poly *a) -{ - int x, y; - - /* 2 bytes for # of coefficients */ - y = 2; - - /* characteristic */ - y += 2 + mp_signed_bin_size(&(a->characteristic)); - - /* all of the terms */ - for (x = 0; x < a->used; x++) { - y += 2 + mp_signed_bin_size(&(a->terms[x])); - } - - return y; -} - - diff --git a/external/libtompoly-0.04/pb_readraw.c b/external/libtompoly-0.04/pb_readraw.c deleted file mode 100644 index 8e4b70a..0000000 --- a/external/libtompoly-0.04/pb_readraw.c +++ /dev/null @@ -1,55 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_readraw(pb_poly *a, unsigned char *buf, int len) -{ - int terms, x, y, z, err; - - /* zero poly */ - pb_zero(a); - - /* must be at least four bytes */ - if (len < 4) { - return MP_VAL; - } - - /* number of terms */ - terms = ((unsigned)buf[0]) | ((unsigned)buf[1]<<8); - y = 2; - - /* grow to the right size */ - if (a->alloc < terms) { - if ((err = pb_grow(a, terms)) != MP_OKAY) { - return err; - } - } - - /* read characteristic */ - z = ((unsigned)buf[y]) | ((unsigned)buf[y+1]<<8); y += 2; - if (z + y > len) { return MP_VAL; } - if ((err = mp_read_signed_bin(&(a->characteristic), buf+y, z)) != MP_OKAY) { return err; } - y += z; - - - /* read terms */ - for (x = 0; x < terms; x++) { - z = ((unsigned)buf[y]) | ((unsigned)buf[y+1]<<8); y += 2; - if (z + y > len) { return MP_VAL; } - if ((err = mp_read_signed_bin(&(a->characteristic), buf+y, z)) != MP_OKAY) { return err; } - y += z; - } - - return MP_OKAY; -} - - diff --git a/external/libtompoly-0.04/pb_rshd.c b/external/libtompoly-0.04/pb_rshd.c deleted file mode 100644 index 2662ab1..0000000 --- a/external/libtompoly-0.04/pb_rshd.c +++ /dev/null @@ -1,38 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_rshd(pb_poly *a, int x) -{ - int y; - - if (x >= a->used) { - pb_zero(a); - return MP_OKAY; - } - - if (x <= 0) { - return MP_OKAY; - } - - for (y = x; y < a->used; y++) { - mp_exch(&(a->terms[y]), &(a->terms[y-x])); - } - - for (y = a->used - x; y < a->used; y++) { - mp_zero(&(a->terms[y])); - } - a->used -= x; - - return MP_OKAY; -} - diff --git a/external/libtompoly-0.04/pb_shrink.c b/external/libtompoly-0.04/pb_shrink.c deleted file mode 100644 index 68a3a58..0000000 --- a/external/libtompoly-0.04/pb_shrink.c +++ /dev/null @@ -1,44 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_shrink(pb_poly *a) -{ - int err, x; - mp_int *tmp; - - /* first resize the array of terms */ - if (a->used != a->alloc && a->used > 0) { - /* free the mp_ints */ - for (x = a->used; x < a->alloc; x++) { - mp_clear(&(a->terms[x])); - } - - /* resize the array of pointers */ - tmp = realloc(a->terms, sizeof(mp_int) * a->used); - if (tmp == NULL) { - return MP_MEM; - } - a->terms = tmp; - a->alloc = a->used; - } - - /* now shrink each mp_int */ - for (x = 0; x < a->used; x++) { - if ((err = mp_shrink(&(a->terms[x]))) != MP_OKAY) { - return err; - } - } - return MP_OKAY; -} - - diff --git a/external/libtompoly-0.04/pb_sub.c b/external/libtompoly-0.04/pb_sub.c deleted file mode 100644 index b82a2e8..0000000 --- a/external/libtompoly-0.04/pb_sub.c +++ /dev/null @@ -1,86 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_sub(pb_poly *a, pb_poly *b, pb_poly *c) -{ - int neg, err, x, y, z, characteristic; - pb_poly *tmp; - - /* grow c to be the max size */ - y = MAX(a->used, b->used); - if (c->alloc < y) { - if ((err = pb_grow(c, y)) != MP_OKAY) { - return err; - } - } - - /* do we need to concern char */ - characteristic = mp_iszero(&(c->characteristic)); - - /* sub the terms */ - z = MIN(a->used, b->used); - for (x = 0; x < z; x++) { - if ((err = mp_sub(&(a->terms[x]), &(b->terms[x]), &(c->terms[x]))) != MP_OKAY) { - return err; - } - if (characteristic == MP_NO) { - if ((err = mp_mod(&(c->terms[x]), &(c->characteristic), &(c->terms[x]))) != MP_OKAY) { - return err; - } - } - } - - /* excess digits? */ - if (y != z) { - if (a->used == y) { - tmp = a; - neg = 0; - } else { - tmp = b; - neg = 1; - } - for (x = z; x < y; x++) { - if (characteristic == MP_NO) { - if ((err = mp_mod(&(tmp->terms[x]), &(c->characteristic), &(c->terms[x]))) != MP_OKAY) { - return err; - } - if (neg) { - if ((err = mp_sub(&(c->characteristic), &(c->terms[x]), &(c->terms[x]))) != MP_OKAY) { - return err; - } - } - } else { - if (neg) { - if ((err = mp_neg(&(tmp->terms[x]), &(c->terms[x]))) != MP_OKAY) { - return err; - } - } else { - if ((err = mp_copy(&(tmp->terms[x]), &(c->terms[x]))) != MP_OKAY) { - return err; - } - } - } - } - } - - /* zero excess */ - for (x = y; x < c->used; x++) { - mp_zero(&(c->terms[x])); - } - c->used = y; - pb_clamp(c); - - return MP_OKAY; -} - - diff --git a/external/libtompoly-0.04/pb_submod.c b/external/libtompoly-0.04/pb_submod.c deleted file mode 100644 index bfa2f8e..0000000 --- a/external/libtompoly-0.04/pb_submod.c +++ /dev/null @@ -1,35 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_submod(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d) -{ - int err; - pb_poly tmp; - - if ((err = pb_init(&tmp, &(d->characteristic))) != MP_OKAY) { - return err; - } - if ((err = pb_sub(a, b, &tmp)) != MP_OKAY) { - goto __TMP; - } - if ((err = pb_mod(&tmp, c, d)) != MP_OKAY) { - goto __TMP; - } - - err = MP_OKAY; -__TMP: pb_clear(&tmp); - return err; -} - - - diff --git a/external/libtompoly-0.04/pb_toraw.c b/external/libtompoly-0.04/pb_toraw.c deleted file mode 100644 index 8c0c63f..0000000 --- a/external/libtompoly-0.04/pb_toraw.c +++ /dev/null @@ -1,42 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -int pb_toraw(pb_poly *a, unsigned char *dst) -{ - int err, x, y, z; - - /* store the # of terms */ - dst[0] = a->used & 255; - dst[1] = (a->used >> 8) & 255; - y = 2; - - /* store the characteristic */ - z = mp_signed_bin_size(&(a->characteristic)); - dst[y++] = z&255; - dst[y++] = (z>>8)&255; - if ((err = mp_to_signed_bin(&(a->characteristic), dst+y)) != MP_OKAY) { return err; } - y += z; - - for (x = 0; x < a->used; x++) { - z = mp_signed_bin_size(&(a->terms[x])); - dst[y++] = z&255; - dst[y++] = (z>>8)&255; - if ((err = mp_to_signed_bin(&(a->terms[x]), dst+y)) != MP_OKAY) { return err; } - y += z; - } - - return MP_OKAY; -} - - - diff --git a/external/libtompoly-0.04/pb_zero.c b/external/libtompoly-0.04/pb_zero.c deleted file mode 100644 index ca51a91..0000000 --- a/external/libtompoly-0.04/pb_zero.c +++ /dev/null @@ -1,23 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#include - -void pb_zero(pb_poly *a) -{ - int x; - for (x = 0; x < a->used; x++) { - mp_zero(&(a->terms[x])); - } - a->used = 0; -} - - diff --git a/external/libtompoly-0.04/tompoly.h b/external/libtompoly-0.04/tompoly.h deleted file mode 100644 index 646a903..0000000 --- a/external/libtompoly-0.04/tompoly.h +++ /dev/null @@ -1,115 +0,0 @@ -/* LibTomPoly, Polynomial Basis Math -- Tom St Denis - * - * LibTomPoly is a public domain library that provides - * polynomial basis arithmetic support. It relies on - * LibTomMath for large integer support. - * - * This library is free for all purposes without any - * express guarantee that it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://poly.libtomcrypt.org - */ -#ifndef TOMPOLY_H_ -#define TOMPOLY_H_ - -#include - -/* this structure holds a polynomial */ -typedef struct { - int used, /* number of terms */ - alloc; /* number of terms available (total) */ - mp_int characteristic, /* characteristic, zero if not finite */ - *terms; /* terms of polynomial */ -} pb_poly; - - -/* default number of terms */ -#define PB_TERMS 4 - -/* Compare codes */ -#define PB_EQ 0 /* They're exactly equal */ -#define PB_DEG_LT 1 /* The left has a lower degree */ -#define PB_DEG_EQ 2 /* same degree */ -#define PB_DEG_GT 3 /* The left has a higher degree */ - -int pb_init(pb_poly *a, mp_int *characteristic); -int pb_init_size(pb_poly *a, mp_int *characteristic, int size); -int pb_init_copy(pb_poly *a, pb_poly *b); -int pb_init_multi(mp_int *characteristic, pb_poly *pb, ...); -void pb_clear_multi(pb_poly *mp, ...); -void pb_clear(pb_poly *a); - -int pb_shrink(pb_poly *a); -int pb_grow(pb_poly *a, int size); -void pb_clamp(pb_poly *a); - -/* dest(x) := src(x) */ -int pb_copy(pb_poly *src, pb_poly *dest); - -/* compare these */ -int pb_cmp(pb_poly *a, pb_poly *b); - -/* swap contents of a(x) and b(x) */ -void pb_exch(pb_poly *a, pb_poly *b); - -/* a(x) = 0 */ -void pb_zero(pb_poly *a); - -/* a(x) = a(x) / I(x)^x */ -int pb_rshd(pb_poly *a, int x); - -/* a(x) = a(x) * I(x)^x */ -int pb_lshd(pb_poly *a, int x); - -/* c(x) = a(x) + b(x) */ -int pb_add(pb_poly *a, pb_poly *b, pb_poly *c); - -/* c(x) = a(x) - b(x) */ -int pb_sub(pb_poly *a, pb_poly *b, pb_poly *c); - -/* c(x) = a(x) * b(x) */ -int pb_mul(pb_poly *a, pb_poly *b, pb_poly *c); - -/* c(x) * b(x) + d(x) = a(x) */ -int pb_div(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d); - -/* c(x) = a(x) mod b(x) */ -int pb_mod(pb_poly *a, pb_poly *b, pb_poly *c); - -/* d(x) = (a(x) + b(x)) mod c(x) */ -int pb_addmod(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d); - -/* d(x) = (a(x) - b(x)) mod c(x) */ -int pb_submod(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d); - -/* d(x) = (a(x) * b(x)) mod c(x) */ -int pb_mulmod(pb_poly *a, pb_poly *b, pb_poly *c, pb_poly *d); - - -/* mathy stuff */ - -/* makes b equal to the monic polynomial form of a */ -int pb_monic(pb_poly *a, pb_poly *b); - -/* returns the monic GCD of a,b in GF(p^k)[x] */ -int pb_gcd(pb_poly *a, pb_poly *b, pb_poly *c); - -/* Extended euclidean algorithm of (a, b) produces a*u1 + b*u2 = u3 */ -int pb_exteuclid(pb_poly *a, pb_poly *b, pb_poly *U1, pb_poly *U2, pb_poly *U3); - -/* finds the inverse of a modulo b and stores it in c such that a*c == 1 mod b */ -int pb_invmod(pb_poly *a, pb_poly *b, pb_poly *c); - -/* computes Y == G^X mod P [accepts negative values for X] */ -int pb_exptmod (pb_poly * G, mp_int * X, pb_poly * P, pb_poly * Y); - -/* is a(x) irreducible (GF(p)[x] only) */ -int pb_isirreduc(pb_poly *a, int *res); - - -/* I/O */ -int pb_rawsize(pb_poly *a); -int pb_toraw(pb_poly *a, unsigned char *dst); -int pb_readraw(pb_poly *a, unsigned char *buf, int len); - -#endif