From c403b660825f0f99451a805408f6a8ef354d1cd7 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sun, 12 Apr 2020 18:37:13 +1000 Subject: [PATCH] hcrypto: import libtommath v1.2.0 --- lib/hcrypto/libtommath/LICENSE | 26 +- lib/hcrypto/libtommath/README.md | 44 + lib/hcrypto/libtommath/VERSION | 1 - lib/hcrypto/libtommath/appveyor.yml | 20 + lib/hcrypto/libtommath/astylerc | 30 + lib/hcrypto/libtommath/bn.ilg | 6 - lib/hcrypto/libtommath/bn.ind | 82 - lib/hcrypto/libtommath/bn.pdf | Bin 345714 -> 0 bytes lib/hcrypto/libtommath/bn_cutoffs.c | 14 + lib/hcrypto/libtommath/bn_deprecated.c | 321 + lib/hcrypto/libtommath/bn_error.c | 47 - lib/hcrypto/libtommath/bn_fast_mp_invmod.c | 148 - .../libtommath/bn_fast_mp_montgomery_reduce.c | 172 - .../libtommath/bn_fast_s_mp_mul_digs.c | 107 - .../libtommath/bn_fast_s_mp_mul_high_digs.c | 98 - lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c | 114 - lib/hcrypto/libtommath/bn_mp_2expt.c | 49 +- lib/hcrypto/libtommath/bn_mp_abs.c | 45 +- lib/hcrypto/libtommath/bn_mp_add.c | 71 +- lib/hcrypto/libtommath/bn_mp_add_d.c | 155 +- lib/hcrypto/libtommath/bn_mp_addmod.c | 50 +- lib/hcrypto/libtommath/bn_mp_and.c | 95 +- lib/hcrypto/libtommath/bn_mp_clamp.c | 45 +- lib/hcrypto/libtommath/bn_mp_clear.c | 50 +- lib/hcrypto/libtommath/bn_mp_clear_multi.c | 39 +- lib/hcrypto/libtommath/bn_mp_cmp.c | 55 +- lib/hcrypto/libtommath/bn_mp_cmp_d.c | 56 +- lib/hcrypto/libtommath/bn_mp_cmp_mag.c | 74 +- lib/hcrypto/libtommath/bn_mp_cnt_lsb.c | 36 +- lib/hcrypto/libtommath/bn_mp_complement.c | 12 + lib/hcrypto/libtommath/bn_mp_copy.c | 85 +- lib/hcrypto/libtommath/bn_mp_count_bits.c | 55 +- lib/hcrypto/libtommath/bn_mp_decr.c | 34 + lib/hcrypto/libtommath/bn_mp_div.c | 418 +- lib/hcrypto/libtommath/bn_mp_div_2.c | 81 +- lib/hcrypto/libtommath/bn_mp_div_2d.c | 134 +- lib/hcrypto/libtommath/bn_mp_div_3.c | 104 +- lib/hcrypto/libtommath/bn_mp_div_d.c | 173 +- lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c | 34 +- lib/hcrypto/libtommath/bn_mp_dr_reduce.c | 110 +- lib/hcrypto/libtommath/bn_mp_dr_setup.c | 31 +- .../libtommath/bn_mp_error_to_string.c | 27 + lib/hcrypto/libtommath/bn_mp_exch.c | 33 +- lib/hcrypto/libtommath/bn_mp_expt_d.c | 57 - lib/hcrypto/libtommath/bn_mp_expt_u32.c | 46 + lib/hcrypto/libtommath/bn_mp_exptmod.c | 148 +- lib/hcrypto/libtommath/bn_mp_exptmod_fast.c | 321 - lib/hcrypto/libtommath/bn_mp_exteuclid.c | 93 +- lib/hcrypto/libtommath/bn_mp_find_prime.c | 36 - lib/hcrypto/libtommath/bn_mp_fread.c | 69 +- lib/hcrypto/libtommath/bn_mp_from_sbin.c | 25 + lib/hcrypto/libtommath/bn_mp_from_ubin.c | 39 + lib/hcrypto/libtommath/bn_mp_fwrite.c | 61 +- lib/hcrypto/libtommath/bn_mp_gcd.c | 159 +- lib/hcrypto/libtommath/bn_mp_get_double.c | 18 + lib/hcrypto/libtommath/bn_mp_get_i32.c | 7 + lib/hcrypto/libtommath/bn_mp_get_i64.c | 7 + lib/hcrypto/libtommath/bn_mp_get_int.c | 45 - lib/hcrypto/libtommath/bn_mp_get_l.c | 7 + lib/hcrypto/libtommath/bn_mp_get_ll.c | 7 + lib/hcrypto/libtommath/bn_mp_get_mag_u32.c | 7 + lib/hcrypto/libtommath/bn_mp_get_mag_u64.c | 7 + lib/hcrypto/libtommath/bn_mp_get_mag_ul.c | 7 + lib/hcrypto/libtommath/bn_mp_get_mag_ull.c | 7 + lib/hcrypto/libtommath/bn_mp_grow.c | 77 +- lib/hcrypto/libtommath/bn_mp_incr.c | 30 + lib/hcrypto/libtommath/bn_mp_init.c | 53 +- lib/hcrypto/libtommath/bn_mp_init_copy.c | 39 +- lib/hcrypto/libtommath/bn_mp_init_i32.c | 7 + lib/hcrypto/libtommath/bn_mp_init_i64.c | 7 + lib/hcrypto/libtommath/bn_mp_init_l.c | 7 + lib/hcrypto/libtommath/bn_mp_init_ll.c | 7 + lib/hcrypto/libtommath/bn_mp_init_multi.c | 82 +- lib/hcrypto/libtommath/bn_mp_init_set.c | 36 +- lib/hcrypto/libtommath/bn_mp_init_set_int.c | 31 - lib/hcrypto/libtommath/bn_mp_init_size.c | 54 +- lib/hcrypto/libtommath/bn_mp_init_u32.c | 7 + lib/hcrypto/libtommath/bn_mp_init_u64.c | 7 + lib/hcrypto/libtommath/bn_mp_init_ul.c | 7 + lib/hcrypto/libtommath/bn_mp_init_ull.c | 7 + lib/hcrypto/libtommath/bn_mp_invmod.c | 50 +- lib/hcrypto/libtommath/bn_mp_invmod_slow.c | 175 - lib/hcrypto/libtommath/bn_mp_is_square.c | 158 +- lib/hcrypto/libtommath/bn_mp_iseven.c | 10 + lib/hcrypto/libtommath/bn_mp_isodd.c | 10 + lib/hcrypto/libtommath/bn_mp_jacobi.c | 105 - lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c | 167 - lib/hcrypto/libtommath/bn_mp_karatsuba_sqr.c | 121 - lib/hcrypto/libtommath/bn_mp_kronecker.c | 129 + lib/hcrypto/libtommath/bn_mp_lcm.c | 78 +- lib/hcrypto/libtommath/bn_mp_log_u32.c | 180 + lib/hcrypto/libtommath/bn_mp_lshd.c | 90 +- lib/hcrypto/libtommath/bn_mp_mod.c | 59 +- lib/hcrypto/libtommath/bn_mp_mod_2d.c | 73 +- lib/hcrypto/libtommath/bn_mp_mod_d.c | 27 +- .../bn_mp_montgomery_calc_normalization.c | 73 +- .../libtommath/bn_mp_montgomery_reduce.c | 188 +- .../libtommath/bn_mp_montgomery_setup.c | 67 +- lib/hcrypto/libtommath/bn_mp_mul.c | 104 +- lib/hcrypto/libtommath/bn_mp_mul_2.c | 118 +- lib/hcrypto/libtommath/bn_mp_mul_2d.c | 120 +- lib/hcrypto/libtommath/bn_mp_mul_d.c | 102 +- lib/hcrypto/libtommath/bn_mp_mulmod.c | 49 +- lib/hcrypto/libtommath/bn_mp_n_root.c | 132 - lib/hcrypto/libtommath/bn_mp_neg.c | 48 +- lib/hcrypto/libtommath/bn_mp_or.c | 92 +- lib/hcrypto/libtommath/bn_mp_pack.c | 69 + lib/hcrypto/libtommath/bn_mp_pack_count.c | 12 + lib/hcrypto/libtommath/bn_mp_prime_fermat.c | 71 +- .../bn_mp_prime_frobenius_underwood.c | 132 + .../libtommath/bn_mp_prime_is_divisible.c | 50 - lib/hcrypto/libtommath/bn_mp_prime_is_prime.c | 373 +- .../libtommath/bn_mp_prime_miller_rabin.c | 152 +- .../libtommath/bn_mp_prime_next_prime.c | 136 +- .../bn_mp_prime_rabin_miller_trials.c | 63 +- lib/hcrypto/libtommath/bn_mp_prime_rand.c | 141 + .../libtommath/bn_mp_prime_random_ex.c | 125 - .../bn_mp_prime_strong_lucas_selfridge.c | 289 + lib/hcrypto/libtommath/bn_mp_radix_size.c | 111 +- lib/hcrypto/libtommath/bn_mp_radix_smap.c | 38 +- lib/hcrypto/libtommath/bn_mp_rand.c | 79 +- lib/hcrypto/libtommath/bn_mp_read_radix.c | 130 +- .../libtommath/bn_mp_read_signed_bin.c | 41 - .../libtommath/bn_mp_read_unsigned_bin.c | 55 - lib/hcrypto/libtommath/bn_mp_reduce.c | 141 +- lib/hcrypto/libtommath/bn_mp_reduce_2k.c | 53 +- lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c | 51 +- .../libtommath/bn_mp_reduce_2k_setup.c | 39 +- .../libtommath/bn_mp_reduce_2k_setup_l.c | 42 +- lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c | 46 +- lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c | 34 +- lib/hcrypto/libtommath/bn_mp_reduce_setup.c | 35 +- lib/hcrypto/libtommath/bn_mp_root_u32.c | 139 + lib/hcrypto/libtommath/bn_mp_rshd.c | 91 +- lib/hcrypto/libtommath/bn_mp_sbin_size.c | 11 + lib/hcrypto/libtommath/bn_mp_set.c | 31 +- lib/hcrypto/libtommath/bn_mp_set_double.c | 47 + lib/hcrypto/libtommath/bn_mp_set_i32.c | 7 + lib/hcrypto/libtommath/bn_mp_set_i64.c | 7 + lib/hcrypto/libtommath/bn_mp_set_int.c | 48 - lib/hcrypto/libtommath/bn_mp_set_l.c | 7 + lib/hcrypto/libtommath/bn_mp_set_ll.c | 7 + lib/hcrypto/libtommath/bn_mp_set_u32.c | 7 + lib/hcrypto/libtommath/bn_mp_set_u64.c | 7 + lib/hcrypto/libtommath/bn_mp_set_ul.c | 7 + lib/hcrypto/libtommath/bn_mp_set_ull.c | 7 + lib/hcrypto/libtommath/bn_mp_shrink.c | 50 +- .../libtommath/bn_mp_signed_bin_size.c | 27 - lib/hcrypto/libtommath/bn_mp_signed_rsh.c | 22 + lib/hcrypto/libtommath/bn_mp_sqr.c | 74 +- lib/hcrypto/libtommath/bn_mp_sqrmod.c | 50 +- lib/hcrypto/libtommath/bn_mp_sqrt.c | 112 +- lib/hcrypto/libtommath/bn_mp_sqrtmod_prime.c | 118 + lib/hcrypto/libtommath/bn_mp_sub.c | 81 +- lib/hcrypto/libtommath/bn_mp_sub_d.c | 133 +- lib/hcrypto/libtommath/bn_mp_submod.c | 49 +- lib/hcrypto/libtommath/bn_mp_to_radix.c | 84 + lib/hcrypto/libtommath/bn_mp_to_sbin.c | 22 + lib/hcrypto/libtommath/bn_mp_to_signed_bin.c | 33 - .../libtommath/bn_mp_to_signed_bin_n.c | 31 - lib/hcrypto/libtommath/bn_mp_to_ubin.c | 41 + .../libtommath/bn_mp_to_unsigned_bin.c | 48 - .../libtommath/bn_mp_to_unsigned_bin_n.c | 31 - lib/hcrypto/libtommath/bn_mp_toom_mul.c | 284 - lib/hcrypto/libtommath/bn_mp_toom_sqr.c | 226 - lib/hcrypto/libtommath/bn_mp_toradix.c | 75 - lib/hcrypto/libtommath/bn_mp_toradix_n.c | 88 - lib/hcrypto/libtommath/bn_mp_ubin_size.c | 12 + lib/hcrypto/libtommath/bn_mp_unpack.c | 49 + .../libtommath/bn_mp_unsigned_bin_size.c | 28 - lib/hcrypto/libtommath/bn_mp_xor.c | 93 +- lib/hcrypto/libtommath/bn_mp_zero.c | 37 +- lib/hcrypto/libtommath/bn_mp_zero_multi.c | 35 - lib/hcrypto/libtommath/bn_prime_tab.c | 102 +- lib/hcrypto/libtommath/bn_reverse.c | 39 - lib/hcrypto/libtommath/bn_s_mp_add.c | 176 +- lib/hcrypto/libtommath/bn_s_mp_balance_mul.c | 81 + lib/hcrypto/libtommath/bn_s_mp_exptmod.c | 396 +- lib/hcrypto/libtommath/bn_s_mp_exptmod_fast.c | 254 + lib/hcrypto/libtommath/bn_s_mp_get_bit.c | 21 + lib/hcrypto/libtommath/bn_s_mp_invmod_fast.c | 118 + lib/hcrypto/libtommath/bn_s_mp_invmod_slow.c | 119 + .../libtommath/bn_s_mp_karatsuba_mul.c | 174 + .../libtommath/bn_s_mp_karatsuba_sqr.c | 110 + .../bn_s_mp_montgomery_reduce_fast.c | 159 + lib/hcrypto/libtommath/bn_s_mp_mul_digs.c | 122 +- .../libtommath/bn_s_mp_mul_digs_fast.c | 90 + .../libtommath/bn_s_mp_mul_high_digs.c | 111 +- .../libtommath/bn_s_mp_mul_high_digs_fast.c | 81 + .../libtommath/bn_s_mp_prime_is_divisible.c | 35 + lib/hcrypto/libtommath/bn_s_mp_rand_jenkins.c | 52 + .../libtommath/bn_s_mp_rand_platform.c | 148 + lib/hcrypto/libtommath/bn_s_mp_reverse.c | 22 + lib/hcrypto/libtommath/bn_s_mp_sqr.c | 117 +- lib/hcrypto/libtommath/bn_s_mp_sqr_fast.c | 97 + lib/hcrypto/libtommath/bn_s_mp_sub.c | 122 +- lib/hcrypto/libtommath/bn_s_mp_toom_mul.c | 215 + lib/hcrypto/libtommath/bn_s_mp_toom_sqr.c | 147 + lib/hcrypto/libtommath/bncore.c | 36 - lib/hcrypto/libtommath/booker.pl | 265 - lib/hcrypto/libtommath/callgraph.txt | 11913 ---------------- lib/hcrypto/libtommath/changes.txt | 122 +- lib/hcrypto/libtommath/demo/demo.c | 740 - lib/hcrypto/libtommath/demo/mtest_opponent.c | 402 + lib/hcrypto/libtommath/demo/shared.c | 42 + lib/hcrypto/libtommath/demo/shared.h | 21 + lib/hcrypto/libtommath/demo/test.c | 2522 ++++ lib/hcrypto/libtommath/demo/timing.c | 535 +- lib/hcrypto/libtommath/dep.pl | 123 - lib/hcrypto/libtommath/doc/bn.pdf | Bin 0 -> 430812 bytes lib/hcrypto/libtommath/{ => doc}/bn.tex | 1336 +- lib/hcrypto/libtommath/etc/2kprime.c | 111 +- lib/hcrypto/libtommath/etc/drprime.c | 85 +- lib/hcrypto/libtommath/etc/makefile | 50 +- lib/hcrypto/libtommath/etc/makefile.icc | 18 +- lib/hcrypto/libtommath/etc/makefile.msvc | 3 +- lib/hcrypto/libtommath/etc/mersenne.c | 194 +- lib/hcrypto/libtommath/etc/mont.c | 56 +- lib/hcrypto/libtommath/etc/pprime.c | 615 +- lib/hcrypto/libtommath/etc/timer.asm | 2 +- lib/hcrypto/libtommath/etc/tune.c | 632 +- lib/hcrypto/libtommath/etc/tune_it.sh | 107 + lib/hcrypto/libtommath/gen.pl | 21 +- lib/hcrypto/libtommath/helper.pl | 482 + lib/hcrypto/libtommath/libtommath.dsp | 572 - lib/hcrypto/libtommath/libtommath.pc.in | 10 + lib/hcrypto/libtommath/libtommath_VS2008.sln | 29 + .../libtommath/libtommath_VS2008.vcproj | 966 ++ lib/hcrypto/libtommath/logs/README | 26 +- lib/hcrypto/libtommath/logs/add.log | 32 +- lib/hcrypto/libtommath/logs/addsub.png | Bin 6254 -> 5921 bytes lib/hcrypto/libtommath/logs/expt.log | 14 +- lib/hcrypto/libtommath/logs/expt.png | Bin 6605 -> 7290 bytes lib/hcrypto/libtommath/logs/expt_2k.log | 11 +- lib/hcrypto/libtommath/logs/expt_2kl.log | 7 +- lib/hcrypto/libtommath/logs/expt_dr.log | 14 +- lib/hcrypto/libtommath/logs/graphs.dem | 1 - lib/hcrypto/libtommath/logs/invmod.log | 8 + lib/hcrypto/libtommath/logs/invmod.png | Bin 4918 -> 6294 bytes lib/hcrypto/libtommath/logs/mult.log | 168 +- lib/hcrypto/libtommath/logs/mult.png | Bin 6770 -> 8308 bytes lib/hcrypto/libtommath/logs/mult_kara.log | 168 +- lib/hcrypto/libtommath/logs/sqr.log | 168 +- lib/hcrypto/libtommath/logs/sqr_kara.log | 168 +- lib/hcrypto/libtommath/logs/sub.log | 32 +- lib/hcrypto/libtommath/makefile | 267 +- lib/hcrypto/libtommath/makefile.bcc | 44 - lib/hcrypto/libtommath/makefile.cygwin_dll | 55 - lib/hcrypto/libtommath/makefile.icc | 116 - lib/hcrypto/libtommath/makefile.mingw | 109 + lib/hcrypto/libtommath/makefile.msvc | 121 +- lib/hcrypto/libtommath/makefile.shared | 165 +- lib/hcrypto/libtommath/makefile.unix | 106 + lib/hcrypto/libtommath/makefile_include.mk | 166 + lib/hcrypto/libtommath/mess.sh | 4 - lib/hcrypto/libtommath/mtest/logtab.h | 38 +- lib/hcrypto/libtommath/mtest/mpi-config.h | 8 +- lib/hcrypto/libtommath/mtest/mpi-types.h | 6 +- lib/hcrypto/libtommath/mtest/mpi.c | 200 +- lib/hcrypto/libtommath/mtest/mpi.h | 14 +- lib/hcrypto/libtommath/mtest/mtest.c | 492 +- .../libtommath/pics/design_process.sxd | Bin 6950 -> 0 bytes .../libtommath/pics/design_process.tif | Bin 79042 -> 0 bytes lib/hcrypto/libtommath/pics/expt_state.sxd | Bin 6869 -> 0 bytes lib/hcrypto/libtommath/pics/expt_state.tif | Bin 87542 -> 0 bytes lib/hcrypto/libtommath/pics/makefile | 35 - lib/hcrypto/libtommath/pics/primality.tif | Bin 85514 -> 0 bytes lib/hcrypto/libtommath/pics/radix.sxd | Bin 6181 -> 0 bytes .../libtommath/pics/sliding_window.sxd | Bin 6787 -> 0 bytes .../libtommath/pics/sliding_window.tif | Bin 53880 -> 0 bytes lib/hcrypto/libtommath/poster.out | 0 lib/hcrypto/libtommath/poster.pdf | Bin 37821 -> 0 bytes lib/hcrypto/libtommath/poster.tex | 35 - lib/hcrypto/libtommath/pre_gen/mpi.c | 9541 +++++++++++++ lib/hcrypto/libtommath/pretty.build | 66 - lib/hcrypto/libtommath/testme.sh | 394 + lib/hcrypto/libtommath/tombc/grammar.txt | 35 - lib/hcrypto/libtommath/tommath.def | 145 + lib/hcrypto/libtommath/tommath.h | 797 +- lib/hcrypto/libtommath/tommath.out | 139 - lib/hcrypto/libtommath/tommath.pdf | Bin 1183099 -> 0 bytes lib/hcrypto/libtommath/tommath.src | 6350 -------- lib/hcrypto/libtommath/tommath.tex | 6692 --------- lib/hcrypto/libtommath/tommath_class.h | 1709 ++- lib/hcrypto/libtommath/tommath_cutoffs.h | 13 + lib/hcrypto/libtommath/tommath_private.h | 303 + lib/hcrypto/libtommath/tommath_superclass.h | 146 +- 287 files changed, 28273 insertions(+), 38374 deletions(-) create mode 100644 lib/hcrypto/libtommath/README.md delete mode 100644 lib/hcrypto/libtommath/VERSION create mode 100644 lib/hcrypto/libtommath/appveyor.yml create mode 100644 lib/hcrypto/libtommath/astylerc delete mode 100644 lib/hcrypto/libtommath/bn.ilg delete mode 100644 lib/hcrypto/libtommath/bn.ind delete mode 100644 lib/hcrypto/libtommath/bn.pdf create mode 100644 lib/hcrypto/libtommath/bn_cutoffs.c create mode 100644 lib/hcrypto/libtommath/bn_deprecated.c delete mode 100644 lib/hcrypto/libtommath/bn_error.c delete mode 100644 lib/hcrypto/libtommath/bn_fast_mp_invmod.c delete mode 100644 lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c delete mode 100644 lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c delete mode 100644 lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c delete mode 100644 lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c create mode 100644 lib/hcrypto/libtommath/bn_mp_complement.c create mode 100644 lib/hcrypto/libtommath/bn_mp_decr.c create mode 100644 lib/hcrypto/libtommath/bn_mp_error_to_string.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_expt_d.c create mode 100644 lib/hcrypto/libtommath/bn_mp_expt_u32.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_exptmod_fast.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_find_prime.c create mode 100644 lib/hcrypto/libtommath/bn_mp_from_sbin.c create mode 100644 lib/hcrypto/libtommath/bn_mp_from_ubin.c create mode 100644 lib/hcrypto/libtommath/bn_mp_get_double.c create mode 100644 lib/hcrypto/libtommath/bn_mp_get_i32.c create mode 100644 lib/hcrypto/libtommath/bn_mp_get_i64.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_get_int.c create mode 100644 lib/hcrypto/libtommath/bn_mp_get_l.c create mode 100644 lib/hcrypto/libtommath/bn_mp_get_ll.c create mode 100644 lib/hcrypto/libtommath/bn_mp_get_mag_u32.c create mode 100644 lib/hcrypto/libtommath/bn_mp_get_mag_u64.c create mode 100644 lib/hcrypto/libtommath/bn_mp_get_mag_ul.c create mode 100644 lib/hcrypto/libtommath/bn_mp_get_mag_ull.c create mode 100644 lib/hcrypto/libtommath/bn_mp_incr.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_i32.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_i64.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_l.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_ll.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_init_set_int.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_u32.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_u64.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_ul.c create mode 100644 lib/hcrypto/libtommath/bn_mp_init_ull.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_invmod_slow.c create mode 100644 lib/hcrypto/libtommath/bn_mp_iseven.c create mode 100644 lib/hcrypto/libtommath/bn_mp_isodd.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_jacobi.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_karatsuba_sqr.c create mode 100644 lib/hcrypto/libtommath/bn_mp_kronecker.c create mode 100644 lib/hcrypto/libtommath/bn_mp_log_u32.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_n_root.c create mode 100644 lib/hcrypto/libtommath/bn_mp_pack.c create mode 100644 lib/hcrypto/libtommath/bn_mp_pack_count.c create mode 100644 lib/hcrypto/libtommath/bn_mp_prime_frobenius_underwood.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c create mode 100644 lib/hcrypto/libtommath/bn_mp_prime_rand.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_prime_random_ex.c create mode 100644 lib/hcrypto/libtommath/bn_mp_prime_strong_lucas_selfridge.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_read_signed_bin.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c create mode 100644 lib/hcrypto/libtommath/bn_mp_root_u32.c create mode 100644 lib/hcrypto/libtommath/bn_mp_sbin_size.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set_double.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set_i32.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set_i64.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_set_int.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set_l.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set_ll.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set_u32.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set_u64.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set_ul.c create mode 100644 lib/hcrypto/libtommath/bn_mp_set_ull.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_signed_bin_size.c create mode 100644 lib/hcrypto/libtommath/bn_mp_signed_rsh.c create mode 100644 lib/hcrypto/libtommath/bn_mp_sqrtmod_prime.c create mode 100644 lib/hcrypto/libtommath/bn_mp_to_radix.c create mode 100644 lib/hcrypto/libtommath/bn_mp_to_sbin.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_to_signed_bin.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c create mode 100644 lib/hcrypto/libtommath/bn_mp_to_ubin.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_toom_mul.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_toom_sqr.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_toradix.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_toradix_n.c create mode 100644 lib/hcrypto/libtommath/bn_mp_ubin_size.c create mode 100644 lib/hcrypto/libtommath/bn_mp_unpack.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c delete mode 100644 lib/hcrypto/libtommath/bn_mp_zero_multi.c delete mode 100644 lib/hcrypto/libtommath/bn_reverse.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_balance_mul.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_exptmod_fast.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_get_bit.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_invmod_fast.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_invmod_slow.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_karatsuba_mul.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_karatsuba_sqr.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_montgomery_reduce_fast.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_mul_digs_fast.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_mul_high_digs_fast.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_prime_is_divisible.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_rand_jenkins.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_rand_platform.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_reverse.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_sqr_fast.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_toom_mul.c create mode 100644 lib/hcrypto/libtommath/bn_s_mp_toom_sqr.c delete mode 100644 lib/hcrypto/libtommath/bncore.c delete mode 100644 lib/hcrypto/libtommath/booker.pl delete mode 100644 lib/hcrypto/libtommath/callgraph.txt delete mode 100644 lib/hcrypto/libtommath/demo/demo.c create mode 100644 lib/hcrypto/libtommath/demo/mtest_opponent.c create mode 100644 lib/hcrypto/libtommath/demo/shared.c create mode 100644 lib/hcrypto/libtommath/demo/shared.h create mode 100644 lib/hcrypto/libtommath/demo/test.c delete mode 100644 lib/hcrypto/libtommath/dep.pl create mode 100644 lib/hcrypto/libtommath/doc/bn.pdf rename lib/hcrypto/libtommath/{ => doc}/bn.tex (56%) create mode 100755 lib/hcrypto/libtommath/etc/tune_it.sh create mode 100755 lib/hcrypto/libtommath/helper.pl delete mode 100644 lib/hcrypto/libtommath/libtommath.dsp create mode 100644 lib/hcrypto/libtommath/libtommath.pc.in create mode 100644 lib/hcrypto/libtommath/libtommath_VS2008.sln create mode 100644 lib/hcrypto/libtommath/libtommath_VS2008.vcproj delete mode 100644 lib/hcrypto/libtommath/makefile.bcc delete mode 100644 lib/hcrypto/libtommath/makefile.cygwin_dll delete mode 100644 lib/hcrypto/libtommath/makefile.icc create mode 100644 lib/hcrypto/libtommath/makefile.mingw create mode 100644 lib/hcrypto/libtommath/makefile.unix create mode 100644 lib/hcrypto/libtommath/makefile_include.mk delete mode 100644 lib/hcrypto/libtommath/mess.sh delete mode 100644 lib/hcrypto/libtommath/pics/design_process.sxd delete mode 100644 lib/hcrypto/libtommath/pics/design_process.tif delete mode 100644 lib/hcrypto/libtommath/pics/expt_state.sxd delete mode 100644 lib/hcrypto/libtommath/pics/expt_state.tif delete mode 100644 lib/hcrypto/libtommath/pics/makefile delete mode 100644 lib/hcrypto/libtommath/pics/primality.tif delete mode 100644 lib/hcrypto/libtommath/pics/radix.sxd delete mode 100644 lib/hcrypto/libtommath/pics/sliding_window.sxd delete mode 100644 lib/hcrypto/libtommath/pics/sliding_window.tif delete mode 100644 lib/hcrypto/libtommath/poster.out delete mode 100644 lib/hcrypto/libtommath/poster.pdf delete mode 100644 lib/hcrypto/libtommath/poster.tex create mode 100644 lib/hcrypto/libtommath/pre_gen/mpi.c delete mode 100644 lib/hcrypto/libtommath/pretty.build create mode 100755 lib/hcrypto/libtommath/testme.sh delete mode 100644 lib/hcrypto/libtommath/tombc/grammar.txt create mode 100644 lib/hcrypto/libtommath/tommath.def delete mode 100644 lib/hcrypto/libtommath/tommath.out delete mode 100644 lib/hcrypto/libtommath/tommath.pdf delete mode 100644 lib/hcrypto/libtommath/tommath.src delete mode 100644 lib/hcrypto/libtommath/tommath.tex create mode 100644 lib/hcrypto/libtommath/tommath_cutoffs.h create mode 100644 lib/hcrypto/libtommath/tommath_private.h diff --git a/lib/hcrypto/libtommath/LICENSE b/lib/hcrypto/libtommath/LICENSE index 5baa792a6..b23b3c867 100644 --- a/lib/hcrypto/libtommath/LICENSE +++ b/lib/hcrypto/libtommath/LICENSE @@ -1,4 +1,26 @@ -LibTomMath is hereby released into the Public Domain. + The LibTom license --- Tom St Denis +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/lib/hcrypto/libtommath/README.md b/lib/hcrypto/libtommath/README.md new file mode 100644 index 000000000..be5b20783 --- /dev/null +++ b/lib/hcrypto/libtommath/README.md @@ -0,0 +1,44 @@ +# libtommath + +This is the git repository for [LibTomMath](http://www.libtom.net/LibTomMath/), a free open source portable number theoretic multiple-precision integer (MPI) library written entirely in C. + +## Build Status + +### Travis CI + +master: [![Build Status](https://api.travis-ci.org/libtom/libtommath.png?branch=master)](https://travis-ci.org/libtom/libtommath) + +develop: [![Build Status](https://api.travis-ci.org/libtom/libtommath.png?branch=develop)](https://travis-ci.org/libtom/libtommath) + +### AppVeyor + +master: [![Build status](https://ci.appveyor.com/api/projects/status/b80lpolw3i8m6hsh/branch/master?svg=true)](https://ci.appveyor.com/project/libtom/libtommath/branch/master) + +develop: [![Build status](https://ci.appveyor.com/api/projects/status/b80lpolw3i8m6hsh/branch/develop?svg=true)](https://ci.appveyor.com/project/libtom/libtommath/branch/develop) + +### ABI Laboratory + +API/ABI changes: [check here](https://abi-laboratory.pro/tracker/timeline/libtommath/) + +## Summary + +The `develop` branch contains the in-development version. Stable releases are tagged. + +Documentation is built from the LaTeX file `bn.tex`. There is also limited documentation in `tommath.h`. +There is also a document, `tommath.pdf`, which describes the goals of the project and many of the algorithms used. + +The project can be build by using `make`. Along with the usual `make`, `make clean` and `make install`, +there are several other build targets, see the makefile for details. +There are also makefiles for certain specific platforms. + +## Testing + +Tests are located in `demo/` and can be built in two flavors. +* `make test` creates a stand-alone test binary that executes several test routines. +* `make mtest_opponent` creates a test binary that is intended to be run against `mtest`. + `mtest` can be built with `make mtest` and test execution is done like `./mtest/mtest | ./mtest_opponent`. + `mtest` is creating test vectors using an alternative MPI library and `test` is consuming these vectors to verify correct behavior of ltm + +## Building and Installing + +Building is straightforward for GNU Linux only, the section "Building LibTomMath" in the documentation in `doc/bn.pdf` has the details. diff --git a/lib/hcrypto/libtommath/VERSION b/lib/hcrypto/libtommath/VERSION deleted file mode 100644 index a7d6788f4..000000000 --- a/lib/hcrypto/libtommath/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.41 diff --git a/lib/hcrypto/libtommath/appveyor.yml b/lib/hcrypto/libtommath/appveyor.yml new file mode 100644 index 000000000..efe45688c --- /dev/null +++ b/lib/hcrypto/libtommath/appveyor.yml @@ -0,0 +1,20 @@ +version: 1.2.0-{build} +branches: + only: + - master + - develop + - /^release/ + - /^travis/ +image: +- Visual Studio 2019 +- Visual Studio 2017 +- Visual Studio 2015 +build_script: +- cmd: >- + if "Visual Studio 2019"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" + if "Visual Studio 2017"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" + if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 + if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 + nmake -f makefile.msvc all +test_script: +- cmd: test.exe diff --git a/lib/hcrypto/libtommath/astylerc b/lib/hcrypto/libtommath/astylerc new file mode 100644 index 000000000..c5ff77940 --- /dev/null +++ b/lib/hcrypto/libtommath/astylerc @@ -0,0 +1,30 @@ +# Artistic Style, see http://astyle.sourceforge.net/ +# full documentation, see: http://astyle.sourceforge.net/astyle.html +# +# usage: +# astyle --options=astylerc *.[ch] + +# Do not create backup, annonying in the times of git +suffix=none + +## Bracket Style Options +style=kr + +## Tab Options +indent=spaces=3 + +## Bracket Modify Options + +## Indentation Options +min-conditional-indent=0 + +## Padding Options +pad-header +unpad-paren +align-pointer=name + +## Formatting Options +break-after-logical +max-code-length=120 +convert-tabs +mode=c diff --git a/lib/hcrypto/libtommath/bn.ilg b/lib/hcrypto/libtommath/bn.ilg deleted file mode 100644 index 3c859f034..000000000 --- a/lib/hcrypto/libtommath/bn.ilg +++ /dev/null @@ -1,6 +0,0 @@ -This is makeindex, version 2.14 [02-Oct-2002] (kpathsea + Thai support). -Scanning input file bn.idx....done (79 entries accepted, 0 rejected). -Sorting entries....done (511 comparisons). -Generating output file bn.ind....done (82 lines written, 0 warnings). -Output written in bn.ind. -Transcript written in bn.ilg. diff --git a/lib/hcrypto/libtommath/bn.ind b/lib/hcrypto/libtommath/bn.ind deleted file mode 100644 index c099b521d..000000000 --- a/lib/hcrypto/libtommath/bn.ind +++ /dev/null @@ -1,82 +0,0 @@ -\begin{theindex} - - \item mp\_add, \hyperpage{31} - \item mp\_add\_d, \hyperpage{56} - \item mp\_and, \hyperpage{31} - \item mp\_clear, \hyperpage{12} - \item mp\_clear\_multi, \hyperpage{13} - \item mp\_cmp, \hyperpage{25} - \item mp\_cmp\_d, \hyperpage{26} - \item mp\_cmp\_mag, \hyperpage{23} - \item mp\_div, \hyperpage{32} - \item mp\_div\_2, \hyperpage{28} - \item mp\_div\_2d, \hyperpage{30} - \item mp\_div\_d, \hyperpage{56} - \item mp\_dr\_reduce, \hyperpage{45} - \item mp\_dr\_setup, \hyperpage{45} - \item MP\_EQ, \hyperpage{23} - \item mp\_error\_to\_string, \hyperpage{9} - \item mp\_expt\_d, \hyperpage{47} - \item mp\_exptmod, \hyperpage{47} - \item mp\_exteuclid, \hyperpage{55} - \item mp\_gcd, \hyperpage{55} - \item mp\_get\_int, \hyperpage{20} - \item mp\_grow, \hyperpage{17} - \item MP\_GT, \hyperpage{23} - \item mp\_init, \hyperpage{11} - \item mp\_init\_copy, \hyperpage{14} - \item mp\_init\_multi, \hyperpage{13} - \item mp\_init\_set, \hyperpage{21} - \item mp\_init\_set\_int, \hyperpage{21} - \item mp\_init\_size, \hyperpage{15} - \item mp\_int, \hyperpage{10} - \item mp\_invmod, \hyperpage{56} - \item mp\_jacobi, \hyperpage{56} - \item mp\_lcm, \hyperpage{56} - \item mp\_lshd, \hyperpage{30} - \item MP\_LT, \hyperpage{23} - \item MP\_MEM, \hyperpage{9} - \item mp\_mod, \hyperpage{39} - \item mp\_mod\_d, \hyperpage{56} - \item mp\_montgomery\_calc\_normalization, \hyperpage{42} - \item mp\_montgomery\_reduce, \hyperpage{42} - \item mp\_montgomery\_setup, \hyperpage{42} - \item mp\_mul, \hyperpage{33} - \item mp\_mul\_2, \hyperpage{28} - \item mp\_mul\_2d, \hyperpage{29} - \item mp\_mul\_d, \hyperpage{56} - \item mp\_n\_root, \hyperpage{48} - \item mp\_neg, \hyperpage{31, 32} - \item MP\_NO, \hyperpage{9} - \item MP\_OKAY, \hyperpage{9} - \item mp\_or, \hyperpage{31} - \item mp\_prime\_fermat, \hyperpage{49} - \item mp\_prime\_is\_divisible, \hyperpage{49} - \item mp\_prime\_is\_prime, \hyperpage{51} - \item mp\_prime\_miller\_rabin, \hyperpage{50} - \item mp\_prime\_next\_prime, \hyperpage{51} - \item mp\_prime\_rabin\_miller\_trials, \hyperpage{50} - \item mp\_prime\_random, \hyperpage{51} - \item mp\_prime\_random\_ex, \hyperpage{52} - \item mp\_radix\_size, \hyperpage{53} - \item mp\_read\_radix, \hyperpage{53} - \item mp\_read\_unsigned\_bin, \hyperpage{54} - \item mp\_reduce, \hyperpage{40} - \item mp\_reduce\_2k, \hyperpage{46} - \item mp\_reduce\_2k\_setup, \hyperpage{46} - \item mp\_reduce\_setup, \hyperpage{40} - \item mp\_rshd, \hyperpage{30} - \item mp\_set, \hyperpage{19} - \item mp\_set\_int, \hyperpage{20} - \item mp\_shrink, \hyperpage{16} - \item mp\_sqr, \hyperpage{35} - \item mp\_sub, \hyperpage{31} - \item mp\_sub\_d, \hyperpage{56} - \item mp\_to\_unsigned\_bin, \hyperpage{54} - \item mp\_toradix, \hyperpage{53} - \item mp\_unsigned\_bin\_size, \hyperpage{54} - \item MP\_VAL, \hyperpage{9} - \item mp\_xor, \hyperpage{31} - \item MP\_YES, \hyperpage{9} - -\end{theindex} diff --git a/lib/hcrypto/libtommath/bn.pdf b/lib/hcrypto/libtommath/bn.pdf deleted file mode 100644 index 5be712382b4447dfbb6d73768722026852f8c585..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 345714 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 z%0A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®9A1<@ad%XGm2ga9-d@H-&WX=5jM#!k`{5^#aMJEK+Ewpwr ztvBWFop+%0z_I`Fe||~FuVL`0-}Asn)Zi}%^EsEm6GxvpZ8}sv|Jdv9a&de417?P2 zj>|CLny1i}dhehhyOGUN>kt1_KI(ta_IQwNs$F1v*w^OAW9O@3#S@;+G*zm+wa2N# zFtmed#b+*|o86fy4}Ne?)p%!Uu`fcoRJ{2%x7yN4=}poJ3Eg=e2euv5ahMmim8Fa0 z=Bd*>lVTMP1ia2zb??&V_RjXMd*u>AQ_er09{Eh9rm-;o-jSGwMF~o+4+SI+Bus6R zD~{Qz{-L#$|6{|S9|?*Nrkq={QE@fbflCWkK7Pa!rpc0(?UvfvnR@c}EB-r2BMW9I zym;vI`D?q;G|&9E=~v~GAASCM+`%-yKF86eYVH-e`RlCm@^~Ao_@t-XZamg| zY68nHEiSR1t+N|s9;{@ms0s5h3GNFH={!a~2BM zx;bY`*y%53I`B-!q((*M=#7aL6Y?7#d!L$aQRn2af^Vt*xlBQxzKIiTq;irMM1=au zJ%4>%swQ2{x1r_Gt>;?NjIDmNmPc)PzrjaX=z`_1e=&C%?oRsR+{v=Ad{y8=*~w1L z&m6hf4L>a9l9hO-+;`bUnMcGVW@lpj6#fK8rxV96t(~QL*W`295(nO|Q#MAl3kykz zXRWvX^{2&xFPDLb=bMDws@y+sFKg+z&Cf7s;M`!*a56~cQQ@8izOoiyGsAZ0Zu|b$ zPPc6>SIpYAd`(%aja=szF?6U+S*`tR5u-|J;)YXeZXK6e?H1#HG}XWR^^qJ&vB$4h zOt86^allLJ($4uA4G(Om?>=_!Ph_OFz^xfu*9D31jWzwT>!3*4i;c;`2J;Urc+JG# zzV2zU(2W^CYM7)~JQI%Kt_|P(ll|oC)&JL|3Ef(~AmE_s<~zTV_pbZxd*|!6nDzOm zZr{(m`PMh(%f^-AfeoRR%cRfq?^%8`@Rd^8)1coQ-xe-fvi`A9m)g7AtKMw9bcpfk z7G2&2Rh5GYsKV4f1M1qd16;ISZ!E2k2{n@P*?WQfyO@{7w&WQuUSx= zm+Abj?Zfiy3CX2!|$90y!;J13-bo=nJmavErJKpJ> z@vbknZ&>>A)eY_io7-P(zPXJv@eSY9r+up~6@)fU_em`KmbH)}IYYPaV9lb^_dhPa zWqP-Zv$Q~b`>}O3@18A6@SE@NG|%(xl|Ns*zLxA|ieCC%cSpt$T0S6b$>CU8tw zpQ|G!%k=chBR(!;_H)WMU$(}a&^N0{n$d6R_lDQEdt;Q`w%T5a9^45leqBPn=5|5^-;*|*_yoN zuYQw?(hO&o;BynxVi_W3?zKu!yZzul$M%YwD;H$imGBsFtbJkE>i*}3n(&m>JK2sp z6|b%A`V%3Sn|}EI43WiGj(_VccDG)5@5MDimb}$<_w!!vm3Plrc;{qm%+7!O?R?f2mZ=>9hCb11?dmeCk@_p~WR`jc#>1t~5ye{L#rMsdcrxx2B z+`GqHMSgm~v8lPXC4Xk!PS{@{u_~x+qtX%ogI&Da%1e1BeUMCEoNE>s>}I@p&;0#& zIi{b>t&LwC+;Y0Wv%D?($*%Vw?`tR=PW2bRpXhw1ql8;-vGDabyB(SKT+DeP8DMiJ zes8U9(!~jihjf|hSnf_aeCqOyKEViw?iB}}jQ97X&(r{IOwrT;`Ba=$3s>~y=ojQA@de>L)+W&5*;_QGQ$JN{>hGf|WP7*%$HD%wf z1(Q{6s%j7J@sLS*H0{Fbn@9P>(J9fzQ6Cku0B0G`bue`Wp)9lZU>|7 z@&)WO^PA79Bz8^_3;)X?@hMYhY3H-Z$a@D<&E^-$);djabKN}ci0zzr*FL1%^+tw> z7lf_-II%CRzx{w^_>mbQZ|yl&{HyFSG=-ss-(>lTq$AEX*fyi=-OMqvy6Ky zPc2UEd%yPXj7=PKCtYQY(+_lDv442D=5?O!L)JFOMCHc^GoyTWc9z|~b@I-^gA4rj z+=#mS+4r6NBHfwcZ1*> z->@kbd=q5(CQK+aQb-s3d3)8iYyVz6v1Ux{NbspRR?!(2kSg1B{QQ&y*IC})NY#(ud3jT`|_#~ne7 zUYE!uy`3{7`C4$tWZtm8eslm48X z`$e)x({;y#A|=Jet&BnydZs2)kGGwYGc`!%c;55gzNYKo3_%xdMYk47lX;DqLW@+> zV`uO-f8}OU^-@>fwfSO&l=}0g6)v(njQ=P5Z=7-FZjQjTl`|eUTAdeDJUH1?IOzKW z&4r$aOg89V518GfT&VLw$Lme}g>w?&7ggi_1U`T5$`P_K^ov#e?hog5bVa5nKW9EK z$+d04;}wcMftT}`e%1Df_uam9O?|?Jzhw(1Iz2clm7w9UyXw!69gPvcITmv||Ga3) z{mxA2|Cu-jc>|Aa&%*v5N|S94e7Mr=?vu?yHjEo{KbqD*yq6KTSAX-D3a1@QZgF3$ zb)9u#O53Es=Xz0lJ-4|rd}w?7AntU>nk`qkPu~>(E^u%C;|s0@9=S{Tk6-x88N`r2 z{q!lV)$(Ecn2t$JIkREGqK4#ez87ElRn;|Zn>s7up4isfqwmyCv9D4t+2-LH_wC|W z>1~f5R7WhnSflx6-%3`Ia@K2t3mFbpb*c)Uzi3=>nqLKxF6f*H6MOF8#D`?9=ediA#9?*V!cPCIoBLGR?A?x#7#ttvVS! zx3zw6?O}{vZgRK&$CD>)QkG{ct(49z_{ihKxt5VFm_04O$hm6jxo}lS&4oIN&X;4= zco@~(f7yhxOK+UfIPp?V_e&+lG{24P@+SB0x7M^iFjAlM@`*;qm*o$8nOhUqO=H{5 z&Rpwq=)1A2!QCBJeLV{g&Q`iAJa3WQs~;~AJQ7CsVKHRbljP4E9LZI@*eOH2CA=eyN?Zn8Ri^Sab3AR!8B5bUzmH@p?>TqqQtO1ei!L59OEqWt ziRe8qQ_b6X^Xb`7EMDR7H0E4bb!h3-jE&mb<<4^c$2aEu-?z!|AglCTnNEcjDQ(WO z4;%WqXZXxL<-V}v%9Qu5^JSkqCf^COWC(r`JhLoO?)-6;*2?VLtJ0ZyrOq?9YPu-} z-(;=&{fR5-=ckIWZO1aUY_YL?_j^yy<2TPz%Vtc?b5_V)8OXM#HTe2|`>M`w?F*P5 zv0OF(VSW3&UCW;HHGav@O%}*{MyUL8*q!I8qS7dKh`VON6g~wH&XR?UO5EM++2GRA{DxMk^mpKdAcROs)nLB;cB|m8!%ZEK8>%uH8&$%t`t#sC1ypcVb({tnQ zC5zou&K>Q!_*^L{^HAa6)9X{W%!#qRW}&*FFK+v>gs%~|G?U*w?fWpDp@Zwu%Abdd zBNa7zZcF`M#;L|}=FOyaneI2e9quf*3RHf?BXyo}s?@Qrk9q-b)MXSazS~7k+MuWJ z&r*@S9bGv=rpG_j>Nuwmg3;t6=SCjiWu!w!B}~#x>(Wmfm^Zl?;dc{}>&Wwx99+ zYFgfPh1ro)I`)~Jo^bWb`|o_!yT0DtFFdojVy5iO+skGJbQTNgEwHrNJmug9!DU7I ze`?IWgKCC{tm2&IRvP`6cRp&lxGnJfF-enohdCFfP5Q#{LSeD=5252vr(HB)>wRt@ z#kbi(cbCNdy|(9G{r(}@%jnnoWFEsUhW*At@~6}9^De(Uh2!ZqRzF_N!%JBc&lOqq zHQ#QqKlprY{=cg~WS;R}(fI$G+49G22elxlR)=%uJq)61hxb3_Na~$(H%VjK?#v&l zQ@`x4vVWvEXVd<;J0h#sY?*yv$L8-x-%i`h*IM*nd-EATx5NC}_e#s;tUp_FWaKgg zN@t%}(YeVseMiy^C62T0EgDnQJhw>vIjHi^%wa*tJHAWvAC#!R#@2N}9uUUSbpSOm z(Yg-cC5D7gb%YLIBUYH08iFRegHTqMK*V5;YKR+%URh#jW~^soWMrsdY-FToX>4Gm zU}$ckXJ}$#u3&6zqGw@YYC_D?lC;e9(xOy7bBsH@O%0L9_rd)QP>4bMIu@pSmL}%r z3Z^DTdWKjQFc^YY=fJ#%OSg%!xt^t|Ip)S8BO{PqxU?Hu8i1D07%3Q98tWODW3k>8 zyc86sAJJVw>Y<-g+UH~@%Kw&jLD}rGDM%s z*m?HX>vFv*O4fc8ryp$ak*)i4?r(sR_Cs~!=DND=?6%{Ur%hy9>&HdYqAt$-e)n*p!;Z7g+n*hsufeGFLz;7m;H?lX z!3g$}C}Brk0quv1Q_tT2SK7S(ePhRbhw{sdS43w_t&ePwI6L|0!qkrsJ=;a@-3n~K zl(A&)Ym19pVk+i-fAb=`;CF~&LEPU>a~@@F)sSVo-+d~=mjCZ&5tST6_F%Szm#ym+ zEH|_GXl&X1R-r(w=eGSFzFMBw-zMI-pSq3Z=9d3${}1v1*?+5Th8dr;&mm49n*$2< zj{>e58!H4{;(WbFoq5{rZw!J4rF9aw?($97vrkAkAj1)Km?!9*hL*Y)bE1ByqRsU{ z?&YadzuoThwD-)NAyK(LGSlM}^Z&c8&dn2;4nAOIxPAQf#eFvpRhOS%|F`&?s%)O7qgYv3|4Qk^0s*k6>e-_p~B-kDd#ei?BTi9X4`GHetz$|_Vb3r z9toQx`E?TyHr<`LDR_df#tD0}d^~DEex|ihN=nG}5tJaLkyduHqnbZDFdY;ps zDOV(pe3A%bzGl&#{Q10~v3O?w*+aWqKmFXlC#`(xsqhIgC!UMfm`v0v^0A!1Feg9g z>t#W`XqKfu8!ZF^AH@gfF~67D8RB;QT+pl-y)9-xm)%b+tI}DpUU=uVpJ`!}X6)N1 ztbcaJrY6n&SJ%(3ko;k7oaHk2yv8h@?Gq+G3r&7iqBNKLz5@T!4^xA^sxqe8nPvJ; z)p@=AWK-pnsGVs?L^30SH}zH5ER%7!^XpZ9-R(QaWZ`U+8jn6s>!9X~22G2X{7tl) zVUo8ZXr&c=-QW+yt(b)sy*lJ9~2bXtY6N$VLZPPF#1{oSUul-SUe5F^pW((Loq)s-CF~c& z_XQ@Dx~DBup0nsi_jJ7?^(7OZ-E>`d$@L$f{wEK4=IVb554;)d#N&1yUwXtleE&N4 zXAh=Vr#RWZo~X7a|Ns2ee~xTUX>Y%ny=CW*LW`s>$qt)Y-)DU(n4dl8J7)`DWbL~A zUl;Z)_+Z~(&>xSb)-wbReZk5_NR5MbPY|R8Lap@-K~t}U2h2x`jEEjc+X}rQ>HGSE&!8KU zg4urs6q z{yoWug=Afm7pn>zNu|FQl-EyqxqadXoy*hGtrDv2q;0EZ`-P{q7|EPp*UxhHQ-9;d z$^M(SpO2HaO%QQ1oav$=TN(GK?qlA!SMN`TXo?=mG3s4pQBnLePpOIDc*&~=k3OmD z{{NZyjjuzY_)FHcm&=uoJ~F8Lz@>Zs@j3+);f2@y_TSueigjbm;U(*? znK(usX}+RfQM=nwK9j+_NLmh-Ya$yLd)o zllj>ct8+ak+Q&Wv;h;&3l^eTWqL{@7!)9GRJprWWxz3y`%d|SGjhsx@Ud8!Pk_3-HwO5 zQztIGInBlC>1F9XaaZCFy#VPoZtM$hz5Kgr(Y>Gd-o~xbX+4v5eu0G9ldp;MTqhmX%DeogtGMn> zg+*_>=Zi|Sql=a(&s7dGpD1ws+@F$9(|VYWKRxySK^ZhV; z`E*Ca-E|-T?=i1D>)|fjr^r6FZ2^n!@{LKH?hHYbBqc0!1+`ri9?qYjRuN}0ed$-( z6a79P7Ac8q*@)>iIK;9oF?jj5!+7eEv^~w7=}MkYDr_g|bUxlOcfH$t_xi6pu6oYl zbCpw^&XK%q>Z|jzO^4>qzGS4nKCZeZ@Zg=;J{|VpChKxvpDn6Ud@tkod_S=K9)s(> zRz+(Q*E5bg1Nu#`_h@fyKXsh-n6ZERop+Pm<{o(7*PX{{ZX&?=diMF-Le4jy&41`M z-~8y_qbBTC$3GW$o&0vX)8&GKlnBF$o?b)eC)YO}cbIc!+d-8Tr_HA7UesKanA+Q6 z#*>w_X5Gv3zMAshubTp0nRcuxd~=qq^h^3ywtrmBxfgwl>&sko7*20hWq6}!bYTBJ z566Gga+#7h@gH&Y*s+Ga!Ts-v!+z;K^BP4@8Rh8k>O*{1-;1nsGd~2n z8HqMI%Zb`Kzx({~a-nRSfACw^3xywSmO7qx+03(Xp2V~CMcwncbXI=du;bOeZuV_F zqQR5w6Haxsc78g2*zbU6>Bmmy9RF?MF)JqXH9Ir>x+RxbSL1O)Nzb>Q>x9b-hloG- zrk>v8@t3R2Aark=l>6HwuRYf^J_us3o_{q~di?_%i-#5ob9(;Ik2iv8Kwy}rBUVbQC z;k;zir|jBYA3t}xS++gXN@ z=7KiP+f{$-&s?}L<9*cU#Phu@uXYx;9Bkje^1rOZEaUB8Yd$k6Z7$&rIz8*!y7Mj# z`;@t=jvD%>G_82^w|5Dn(e}IF1s3@K_%F58Invfo|AlwzigW4VXGD&xHT(*_(&;?? z`qQgSO0Od{64r=pVr_e~B;;=5hr{_SoClQ`6xfKZU%t@uK&+UlY3V@~j8KLH`>;_vd-b>4?dc5j4r?zP$+md;-F-C?h`nVgc}Vb}UY9~f`lx^*-xR`zl0 z`L`~Ig(F`E-~XE;<5+%j;|IR5|BMm$#lx{R!9d+XSZ#}=2?nZ=(VAey4Lo3Jf*GOr z;|)O$fHuJh_v1l|VXg(Yf$&g!`U?~Nl-60OxC%M)`@Uk)XqxvX zcsoamXEyhQr)zbee|&H49JFfBCAEW0pCG@hXT(&hN>vv>cpPgS4r(T06)j-0!4zd~oiyL#y{P z<{iECRafVomx`)#{Mvni`@h$eYJ`@GGGxok+~MSW`{#4;8lmM^KKywQ zaq*qu?kO=oIa*6qmb2_$x8l=*4bC^-@b3uxvL#@R`_1ZxPs*p3Z?j!{VAJ}8jxE)j z|3A98^~G#q(a9`j7F$1FZ2Bl*rl?j}tdX_cFsG||!8)b?N&&tNZQ9*WU5@ids)>a> zbY43_aP!>dCj$1btmr$-$nfTClU(AC3&&g^vUKgl23DG_00U*=w6>wn{rz| z%KX6G)2U1f6=@SSZHmi6TJCSW@u_F7+~NF;sehKuEPAuCscWA_P^YqO{Gq(a62?7; zRU*Xle>JWB&G6EHV#(PfvIpFg9oj_xZ~fbH%Kq$UWz%VsMFg+)=<)Ubvi+i&aa{Dl z>OAYOG40P@`PB-ny0zPFPGMh-UD>r94G+)NHAW%|e69UkEc&m!kKDKKOCr;r?|Iq3e<_YJN>x1w?xk_vmV3@%1ci)AD5s4l_rU~I)Qdfyi80BFHVxMvKi zAz-cr70Xz4LjT-rIhwcfGWISn)ewm++;VDC`bo`C_uuy|5jnZ+ zZi$2$OTm%HKP$@ryxTqbX3rt{*^#b6nP+@J=Lc-ADRxZHzVYj26YEsh^_wL$_r}E8 z?B29_%92^HZ+`lA;zH5a>P27v^gn%_9`4mA66~qsD>}n%>goCMe|FV;t=lKyq@p=f zzh~pgZgcyyk)K{Y{Vjfd`VQsEtMA{7)mvX*`JItBZch~7IZow{tKZiA-+ON2|Df|T zRGhNxIvG-YykGuto*tp}pt*4B9?gQOTOY)-_esu;G1Iu2^I`MKz-5!R|K^$=+d2RC zDvK{SgFM=%8P6;_lzZy9pS-%ghW@cz=c-keUdnH|@N*NJzUYs=H|th?>aG9hA=>(N z!}q=ar~frrA(wY|&b?Cyr9Mx$VPl@FYoQ*}qN4ZylvvPV-%m@|Xw_Wud}p-n<~zgb ztfzFIOi?Xwy}rh2mG%BJ($gRHo;IwhHD*_=+y3g5?mup|S<&x#laqwYVTE2nn{Cea5kJ18Dy zH^rsMdLuyO{!lvt<#q$_+6YULj5p6uoQ{bdT{PZwq# zp_50NOV1p5!Ej`&MQ?V-ikF!&(K&ked$QBmw>eleIW!-5E5mfQ)9H1JtyTApw}s9- zuI*j_@wD*~kL_>-qpmE97Z1XFKZ*T|{4I;m~evj8dP=r^kkt~YLx4|y>m zSAAJrm|LL}hXKHubJ)<4%miubBJjyE2b` zx$D-qx0mQ&d2iEyUy1ih?abX;{F=QVRVFuSsLubSu7VF z3*D)=+jz~3A0K{x(S7h^Mp^ymc$v*N!~b71oIIN|@`(J~1&@!{#XY_@VM_3vE$+MP znfqNYVH?ReLhf1NXs>{~YFzq3sm1xFMaikf3Z_Po5qf>!)RfFbr~C?qXi)Fa#Mnr| z%)}y=OFtm7C^fG{0b6?oqs0Mo0JObAs2gd7v3U#Ze01G7+bhWZH*kXii`^zB#(IX> zPN6gcFVclI7;tGfHZajM!P12_LfI;XOSh4siJm2B(mSs-CkOfXX-J5}EJw6fkQyZ@ zJz$)z7(7iE69wp{A;k5DjX~`kn2VrI7jqM1qI<(@Lw)mSI|%IktZktec=OHo_NwgJ zE`6&)roPndRbndZY3j|MyyV~axp!HcleOEoZAvLiZ<|^9`JSGM+K0s(O=fr;OV*TF z=5ze0kbE?Ket&s=F!Tp~}^$#V?;cd-d9N zQqj4K(@%yvT~sNyZq%#4Q*%!3e%`W^v1PS&nQodhuifxkyMTAPZnwUSE9u9mD|=DF1vsIqRB723A@kF=nJkY<5!4kRJ~ZEA@l6D z!Ip)$mExcCU#Pq5Sn0XM>F2UjyA`^&9W*R1{uz7b+THHz57F;6gZxvyb{=v%) zlylW`k+q+BQ_f7UJGQpIP!wxv2JChk{t~BG>aQUrWVzc2~Z1Im79kD?G3Hn&rX` z&3Q5XZ$N>}zLG?lV#e$A`PSaDI&rRiXN?l2X81hZzxb|pw{YJ!1rLFM z{`ou(e9bj$OKK778(fe7f8+R+sK3Dok zM7wY1L@hC=go8`|@^ig1TK0H~y2uiP%T9c){C*pmFC^dD=F6|ZKdqeO!@p+lvwPi} z_ug#LJ)HmiLcQUGJi(^!V0rnp2i(Uv+RvW&&F*<>$9pV2L}O5250-DRm$=}ph1x@e zWKD8a$nxon^lxQqiPBAhY3H&QmPF*0bMM^K+#jbK zBD^SBz|)&~e^1S>O#6E)ETkIxZ&>7hl)N9SyYJ_{U#frnI~;Y_|I3*fA>K0SlK%R< zdu!_|_U!z-rLO*K)yGe(TyvCpUD(o3`7aH;n*7+P^U2otwjpecPB~vM+`ar#xUt_L zaJL@cfq#*Es`aOve|T}7`-g?=_CFl^Jr)LCI(^rvTO|3&eR;9{y7$VyL>=L6mH7~S zi9>kGOW{5Hc1Etg+WqyI#AYL{&8$Zh)|koF1$;1%HE~VM<`s;@N6Oqy&GwnO20 zy00Bq#0^V}wQ3VsR~u&aUCmLkUfrz{y;{?=clE-Fi{t#4mlhndIvIH|;6&4P3De`* zW|QV#cb&BMy6vRpp?{_?+iD&lVtGE(v{5IbH*jiK;?xxnk~uk#x(f)Zb7=9OF#EzO zmzQ7EyW_0%licK;xv#X8TU&qJJoz?3ykpYlHH#*&9yiQ7RcO{U_pxi!+Q(BK6qnXm zq+Ori)plL;-?QrrA4)CrjLFjA&nc2AXEc4#rqp+XceAm)-mMir@1I5o^_!=5pPH|3 zYG3%^&!YyG^hW|GoE{~Fs8v*3ym3EQ;&&p0SJ~ZV&Vv<;CmdX1cl>dk!-XfNV&{r# zSOg237MxwZZF6nY`QwNGDyOi7ZCZJbgS~q@f8xJKYh?-&Vm+;nIN6yvhFaBBS@CT? z$nkRRqsQ$HsdcxwU;g@1P`zcL<)y>SMQ7evvd^09xh7P;QKzCOFym9+{p8{p zew(n>vg0QXX9?;)Z)IrJd2wKc*YUT7YyMo_@XpZ4ZyZ^CJLn=Z*UUhIlki5hr@QSe|CsZTq;?&?@{12j`eFEt*+2`^s{Su z@2M|wv9+l?7xxIo6|dXFve7`!H(+w?1~u72lPj&ol2fX)E&Ml&Y*Jud+%fH8O`p=m z8|&wvGkw6~&U?>u>Mxn?zn9PXH~;#@ExrQPry{Z&CMtf@NbWAVaq#F1BYED}u00FV z7DcYg6=Kt>-j|ly9g#Qf5SJ!T$nM&vbhgmLLXvY+b6#%i5Y}lH3D`1!O9{8G*khL> zF>zM=%<8)bLweQ;ANjm2`GU;(n;P4uiEA!;JSC~P>=lt?G+&;2EXa4*Di_6k3fx5ot0sSDd=k=ozUBa5Gxt~F%*)mxdECDxES3tMXfo+J#qxjOy?6h2 zynn}aZpBQw6?ZCoql#B4PGB{an96B)W$w%MvXULmu|`E%iW69MB|dUphpXA}2Hj ziXNP9pppOU`bKpxHFfW+GmPhb_Hj@=uO1;CDww0kWq9~f>gJ_c^@Z2!WD^`cWSvua zIM{TTl+5c@cqGcnrX94YPsrx3#;@?x#+y{jckfBuI>SNC=h%u{&#L_Q-+sSJ$ZUW8 zkDpUEPyA{6IOV6s_KwtZZU^W8zVmt6obA{7Z!@~`N>@*4o2aDZ7huxx<`U=8<9``X zcfEdt>(Qmju7l&zx#;xzj=H66az) z4|TnBDs#Q&>@Ha}$G!UZS&ajSRyohI=h*p`<*Vv*1%VTX6cVnmHXk@TlgFvE*qmd^ z=ZM|^4;h}AYkb;@-|EOA4im?}-1>J~&Za&sziN2e|B;`!B?i+>fhwZBy{newv7 zMX<0*7JPe0Psnw<=J{{B z_H*^N?9O_kdhLnY1lHY#S?liRxLEJ*cDa~$s`$xkt1E9$R@r@*+-ovNy^<@kKzi}2 zT^SWTJ%^&wC4MSCVzK9cI&0&q^X~)VncjYUcgM`T^V^0Uw|~wKxXbl*&UOcpO%Kf6 zLi6t5+j_r8YhR{at=IZni`5}SSCULFPQx6Qx(cY$&G5hm$ z`Teo(yMN8ilKjn=v1!7IW7GCCc{R25UoXhHn!wHWbop)z4c2DCi^n%U|I4qi)AJj) zwil>r0&8I4XnTR$AZTqb&=`9V(QPlJ)!N43uCs!vF{sxYq+n_S>L!C|P#X|LgZfY) z8q`Ju(O{btOrcFEQxmXb6iiJZ9aU2ksCgz(^Gu=UnL^Dog_>syHO~}ko+-%RK?E9YpyruD%`=0VX9hLT3~C0N+AtbSo>o8+uJu~nDk(Ne!#%2~43Wg@8dZv~JmI@{Y#(GAE=0rQp)C}EW z;M7a5!(bt1Y+;~hY+-D!U}y{tGGj|aJtJd7OQKzd8Du7)^h&nNEc7hREG-m_%`Ehc zEiFtH3{4F5ER9SRjLj|ej7-dk4>Cg|j35IgP;wn+YN}^yWNM*cY-*-wVrXolU}$Ep zXJTQfU~FctXJlqb)VZ4AL}qA=;V@8+Cf8v`W_spE7Dfu7xjhpQ1AGFdg|Uf(v8jok zxw(Zg(Q#>His3R)9wygi#-@4}pwm~4jg9n7OpFZ`3{A}SEDTI66pT$kr)3(F;4;kg z4=Sa|b(x8Uo~gN|xq`8gfu4z}xut@knSq|Ev5BREv9W=kg#l>Tl;8=j;K($>j7(55 zN3O$+jPwkQjLj54mlT_r8(AnA8XN0bnp;>X7#mvZ856H^5vb0a-dLvv#VLla{?LjwaN z$icy8rlv$kCT8&uZfub2FcV8Xa}z^L1tV~(H!@N%G&9sQvotqUFfupPGqx}wYMU82 z{hMGE8Q|s**)B8DGq85)5~4p4z%0cs5?7#SJsnHXCV zUtXA)qn8)p7BsmIGcnUMGc`6-FfuUEGXsrhf>yVf8CZavYN%&oYC?QXj>Tn^6#gcl z1_h`wW?`XcW@KorU}$Oyn!mDCFtoG;w`hqkFfg+vC8a+o$_zjyn7NsrnX#Fnf}ydg zp0OFIu(bd=+JyL;+!WJg6qWwwdPc^^#tMdJCVFP3peBZ;o}mS(-DqyAXJkx*!;CNr ze{e^P++=11Zmyat7@8XCnVFe_+Wv-mMh1rF3ZPxS28O1@H?a*dG61-1NVdyN^-N8T zzzu6N3joOBFJp&6%1w%tKJ##|?69rI_VPIlnq+n=du4iOvOnei=&;-3O z19#`ibeNH)g`Op-L2Y7S0`B@68ye_Yn33M`#q5)SM;FL-mW73$p_#d{f-$(`Yi_Dw zY+#^gXk=unU}9jTXK89cd`uc)#v}zTf6!G8W~RpG3Xq2G9dsApmU?oWbxzMwS&2F9Rnld*!axdo^XKy=}6h*89XhlI$DOfyS8 zV*`+TKs{dr3sCdbP|wH|+(|dnv$QlMz8#Bkn}jKNkcwQFSy<|sTNs-{yS|2?zKEfo zxv_=0g0ZQoo{^a)@yQIcg$*7yBim)hdWI$-2Z6f2#-JkyEKT(cEX^z-U0(}h;=>Hn zW#EB4a$RO_q-SYhWDM#0nt)n87AATYrl34(Y^Y~sNqkX;#bFeT{1};=>KU3Ff{F?Y zJrgq{P>0SO)Uz{(bbSpCh;Nr+_T$VcX#0cuZ=mWC-1Rj#wFLJx4UEiLt_$( z42;nN@Zc-CaS7`28i8j2Ell)GEG$hFz=epVr4jfh8Y3e!;?qAy{6U&w+v z;zoY3B!5bZe{*AKN7vXw&(zQe6jY{qW|kJ_3PvVopb=1_i+>Z0kst5~KADLOG*oA5 z2uft24koB&4Junr%)xgInd+GslQ1NU#bp$<{f$8(Wd_=nU}&UgW?-aXY-#`+Xi)&& z;A3e@!dMv=cY)?O$P6(fP*fU&Zd?NOFb%zP=R(qhCYGEgoZhs-n*J-cLNVWejPng)XOFwH<^tBIb4fu*5> zp}DD^sR0QsM$94uJXc0`n3?FAg8Crf9wun0#S&EPf;w_$#(D;ZqztiOMkYnYzmc9X zsA&P3yD_sc29^INpf)79hiPC;LWPMry9Az1Bs;`FO>0YYXy4b^7~C&0295H9`o5&O z45O3?mqo((yfS&dELi1+*-sKZqe4tc0qFU?nlo~KNPiX4qk(`%lF8?#!mS^sbUAJAZUsm55jL$T%0_p@)lzUlAN!k*sRUAy0w zKj&Wib>^`a%lHNC&at;UMB9f5(MIzyK zvFDC`@*6g87rA)yVCum_t9_?6G;S}BUUzf<{_Edgzn1=Y{#8w5I(z2^z7D3RE)Q0^ z{5YVa$mO;uU`@J`xGz_$Nb>Y9!()14s!t;Hj{Mk_(8ILtq{XYG>73o}#)U;w3;4EN zj582!O|lidqGcg5}D*H50h zJ%@Aa`4;m8ne|%1#)-Ty4qPdksUh-u<_XuyMv6yoq$c%jJnh0+xx1=HLd~g}`y!`M z+EL+-CkHC)KJMs0JoOOkgYACzZGY%wZ<%HjAky_Ul@pTQ1Q{N?v2;<(8S{q* zl5!@qG(2XC`X^+Ch5cgKylFusw_~)Y_U1>N9`o9nB(JyE+*sy(;p*AibNV~WLYeoKHbQfpxwv}{UD(Z2#P6^BGiOGp?k+99 zooO&F{C(&4xqWOgpD%bGdl$4Zt2}zk=IWz$@=>`8NneU;A`9l|S9Nri{;u(r;hS?! zu&H!%y82o3rp<95=EP`Sn|sbxeeSeJujj};&Yr9HbKg?dyzSM?d;dIsn`IgEN~WUQ zk#Bpb%yZX&J8bVa)INB9$Man0Kza+@sT76Ss9eUa{g5v488sKVEjK`Yf;W%uW3bqB%BysA}1~c^AXd^M~0>881jV?$WXFbLYtTF-_~` zyYk@g&YM1+c2t_fCR+IE#i7Rn^Y6`hAh;?7lqhW#MS_;NY8?yM9WiCi@j2n=cZ+u_ zuuQS>740g0UVQP~&)@zpcTCz}UHwd{k4vds?}o?1hY-!A6rx$)%KoWRM_Ya4kUrtEHJZ}lrM z*AjhQ_I%OYyYtKX8}mNz>v~stGV!BH$;r}7oY$l?v&w2~a`!uIKmWSnJ8wu>fxL$3 zYuhJ_VukOo`+t8u!--FEnNuH3iqg6^`-H2naPvw|$Bz&6+^)aqJ^V4{=tGX$9jWu| zX3h9)u{dPTpF6!3>m1h!f7u?e=J)LGvh%s`*|L?-PY~HE6DuaO{Bf#E(gM4?Eeogo zka&LK)WdCEkN3QMZJ$5&9kaZwmo5L&!cWPHO6Oni6RMGk*18rvvHRP~6*d)?5srRm zueXS4M4Yr;8L;O2q;9n|j-M>uHGzhA!V2ez-}GDSG{0Pa;lsn?Pj*giQb-Q7Ie6lD z>H3Rb75V2kJX^9n-|X?hEni;0Z?2Ho;5ly!o36kYx4erlc^5xye4O=JRrvbsVi%j= z|E4c%uQ}11aLH8d-r5tp+rQbAcB$?OS);Z`*Q=zz{Pw#q5jS6dJmTIs@3&t+-%-1s zppCx@x43q`Ti<>C?iZ6EuIiePn$AyzYUw$r|x2;&#!dYPUH_*>;16NL{YvC+Fy(hwJ;mnLc<1#^9NNeH1HwOeM zn1YY=1ks?n6huQRU{gy_R~E#F)TE%nKJc0`@TFHl3TEKl<{%nuvI4001(G*|T*IJX z2Hu_pl82aQ2EJqg#D|z?W&n1%f|&ux-$4pyhLE*xpsikDbHGQXfy6;8V?Z>-eP-aZ z=Rkaj`^>;+k%0J6^T5ZR1u2+;4@f~X>6pyg2pmI{UjhI%Fj zW~K_JMuvK(7KTLk&M{lG;5Z=DU7%TLGa~~F1rtlq3<-Fe$x_eM+)TmL5H#XW{LqvM zMzhfp6z1f*%hVKfhOCK#iG{hIG3Y{KLo;(d0}CTF1rtlqkVh-x1TaYkjj4_vqa&#eyU10Dc4Dc)yXo3(ljAv+Op=V~MU}9#ZXJBkW zd?LdVVxWvmZirc!fsP6`QZO;Lgp4;DT3YBC7@3{F@las0xgX-wXie; zFJm+{H8xZ*F*4ILF*YYYUz(!#fXz@20U1ap)qKMrHP)Ifr+t#v6-2k znHlj@6DH_uQX#Dza)ZpoQqR;FG^u1_tY=|r0m_+%dM1`e&~>~9X2j=AEG`4JyU2B! zv8kT9p`nq2v9Y0^CFm|x&^lf-GcywfV-q7ib5j!5K4XbY3Mv4|swiXd1fivgg|UJm zXnY;C=M}V!*WA*K_?(F`We91Sk{M){MtbI!pb2sVb3IE-(8^~66FqZNQw3u~3q4~K zW8xE;A$qe6(o`nXU4{l0dPWxDF>EtE17py_XCnhWBNIat1!Ds<@YER54Oxu!Qjo?w z*)9W(@|%FhJxxIEL~{j0Lr|Mr!N}4?&(fIq;=&LkSAzQzWID^zSkDYJ00^1`HZ%e) zdp0oDGcz;-O#&O~nV6dsKV5E&zAD2Ee0nsw4l~s=1+B0FO=KFH8<{8=8kp;uf>zjo zmhc)FkuqD3-i$Rfq@?9%$Gp= ze`E%kp@{`(Nvbh;4X+WXQw&=5Z)R*_3SPu(XlOu5bqPKvom`h08tPeqW77!SIk8kQ zG&0t+0LLb16|bo&@#!D4@dNH7lj|~5Q$1sIGZXMKUSrVFpP+u6v9X~Ucpa~yB`Hg6 zFq#xdCY5vjO<#5Hkfs14}(K3q$ZEtD&(8@j-@J#8S}ow**b(Sehsp zT3G0rfC^SaP{C?uVx|D+*nNyNlq@eGXlUS1KlA4^KlFDUg$5mWXl$w~! zRdMTWP_2(}x{O@1^v4UDlQ@6;pP+9YW=%`lQhS%YiVPgk=O$F^n9G(2p-egCw( ze~b4&ue|rX_Fd)u3s0qrj<5+!7Y<6UKVgk3QYPEdQ-#%EHvou%_)O2jj1hH#0Xb-+V#PeWs(HmRq2Y z0N4A;>$g9Dv$at%Vp7r<2d!>4i{lT)SVY$>F_PSn)R5$n!FEB1Wm<>iH1TN+3uneU z953ql9T2Es7|^rwLT?oVPcPdfn>n8u&i@NbQp(=u#uaX06xPP*qcxeSvZv(w{g#%_ z#|nq5_4)$NO^$TuY<0?LV==NgAXNCfJftQvXn%F{;_p|wCskg)%lo+5?(I$8-S*2) z#7ae;op!bA-;pC9CocPL&0O}4HBaf$n}2u29osLR-ZHuL-#NADwJE>#q4o~&5C>-qHwO}@!ID(ZRYxbo@je-ho9wl^h$E`5!762RZ_ znrXlNY`bkc7AG%!<#p#w6Z@hAF`Gn zxOYF(-nTrz@@n^^qrG>x%bBn7`emZATJcfPAHmmW_Dt|uAHK=EuIt@fnWTFwcgL50 z{JGAS-#BYqxY(LkZ$3zS>&FZ4|2z5aaTjU#;2Q0m^bVohE-(5&O8z@}ZP7pWNqa^A z{toZ`KFw}Z(rj0^YM%vaiZw?J7n+98@96r!XYG!SHGkOO=^ni}Z}mO))JE|Me?CwB zWz1&sxb#=-^a_N?YWw6|w9RZ|er{$v zDf3q^>*(2p!tW>c-I(`u*ACa39n7U$WM@d# zd&cr=T~KK4;$2mzBBg`MzEwTlDttJrOcP;5QXp7DLkta+Go4kqAzgT0)PPIhIkCVaH8VY< zM8V9$m`fjI3P?`Z(9#5Au3utqD!P51C5bti$&PvHIjIV|h9-Ij#-?2Q!6m7=VG5SU zT>24E6HSZ_A!ay%PtwyhG*!^G1nny^GBr{#2k(t=%SlWxRxshx2L(WIYKek|er{%7 zX|aA%Vv#09vs-3Pssf}ALcTf&5-9meSzOT;;8B0jtjBP|#>SQkv7n>|@*^a*pe8U_ zQsUBg$xKU2ElSM;9bp))V4wgALj^;9y}bOAl+-i@LjyBVh=MvcFfrsq_)Nf4N-)zQ zmAavVrGYuDQa4gCGBB}(@ldOHBQrCiZ^C&SRB1DXTYQ^~~D(h=cSvBjlYJ1;Q z3psPgvu9@cj5F8HNThfxZwi~1oiTCB+!W4**#+J^Rc0w=Yk5xE>N#!S!s`9eckTDT zU;qC5-uL$JEzcLv`@HA5Olj(LXR9!aF8&O6MdOl$T?WPnZrv2)yv&}k>(?)V($Z|H zjzj^C6lor26Xt|v%L)!CHgFu^Ww1EI!)I=6(zt^8nn;#G?}OLJ85Uf#4);9PAj-K! zaD#-=gPz16jVk-t#GG090ynTs5M09@A=ue)JBwAefcd3DFXy8YMFWWjfX#jbvzf!)Oa|Gqx`>1-TrG_6T_LM`Kti+K#r zixZm^|Ga+a?&iS3qcEW`L4bknqwMRKlQeniI1k8sNi;0Kps-r{D*Kle5>g&&O%-kY z2g^lcP9OevW_|7l>xA#-qQCdC_UzaF$!GX;-%0b1m;AZ^+I)VTd%>u3>DEu<0}98a zKAm@bf7_jt>tdrclU2dxyMOG>O^jH2dLJg)-FEE34mcid|sVet*sTaIpsqW=@^c9k{!9V%f|i%7*EuOnIi9dtk-(lz&Ow`7)l zpYdvcg5aY4?~c9UZWeGlo$E?IKIw#NAG>th4K$lJf;h8=~8*~vBTtO zK;`GP8+8Q_eRqAb@y^DDrSrSLOTV@FTVQcxVZ(yn;?Ld5Po6%T+HqBcj4(wjMlY>$^_cfinXfp+9g(eGI(6X6>Mx?s(la-9T8?X89x6|voH?Jp2WuyJP0GAafvtu4= zops`UTad|f#OF1O+1;@>)~ToVlTCngmpPuu<5FHhsO?tIVr zUvl@9<*$kA71#dh*`^*Y`)ICW*pp;aZqbrcHs1u@9>`YQOOkvxcdmwZ_!^e1_)Ydj z-Vb~KrM6YvxTD*wy_0MDTICDW5V37(L&*#M&ZTTtjXm8vi9?si4BZ{6pXl}cg?R7hA@|pt` z$7dWot{r#p{bd=K*H;ghSk0c6B!8Q;;rGPDYmHL3{`~D%YY-Q7%yeGThV^XDQm5|i zzp4{9b8dXhFHWxS3-e9Rud&q2Undb7)hVMVTcc7R6QQT-UT|mg2LBC8zarYFg!dF4 zt7-XvuD|;11AUc85z(vTZPu^f5pzYTMAa_miMp}+_nSgJXLl}i*{L3NEZXvN)7z;} z(sgFKDa5mAoZWcV&MaW!-5J3gHWLe@HT7#v<5nw9O{zIzf6K43=HRu+i0Xn=dzlCO z<{MP%oP4z5#ImpJiodHrzAAjG`$-r3ilo@AN#V6|NPEhyL3%#)?Pe6>4A;WuDMrOLvroj>lJRSk)G^&f1;_j{mM%*3kzFT ziQZEAJL%mwr;M9_l{+^_gc+GFwbMI1sla)2ilOwkcDE$%ul744T2i;p$AR&irC;lyQ8SIrFSA{*oi|CNl-N`8~_GN9@ivy1Vpo zpifrc`MaqtF7r9KWN$Fuw@X~0ac%9jD{u3ipY;Apf2hu$?0z}>4bIE-@i*!<>{e4lYZ^eaC25`4>$klT z2>gDsZ)IL}?Dq{xwTt-Uen_33ayL)sPWSt3Q%=l2|Mj2E^qsy89gZQ~Pv5S5vhWz+ zJxk`b&)(M6{y1`3>2#i-|P_E+oibd0UqWiAo%(k4(q5`&GgVn(`+id0m z6^~wSebbz5bZFX}ux9QZQ$A>2bgArPs#+NT-DhQWUHXhC**B#uk9S?l30IeW`NsHy z)T=AO@w4L(FP<;Gq;aiR%Fc!k-Orq*W;;*v&hyo&e*CYE=l%D(%o!)+R;Hdl7xnl5 zhsHng59*y5yjcuQ*jif_{&fDwy7~R&C7>2FbVw;RF9p%!rM6m zjoJs{>YP~^Aoa~a>t|5zsjST#l@lR zGePN_86fq{%nYE0LV9Lswjp=T3}Bry6LZ|1G9wcOT_Z~~1JHR|CJN@}py@O$y|Mz( z!RI-tX(dUS>H1(!5vbP)=Ygc0P^92IkW^A;I-0h0{o>Nx+{BX1{JfIXiV~F09=JP# z97Leg5eyVSkr{1bYM}ta__}(gmgWi|Y;J6(0K)jx(o)XQz|;)64+lzAuy}@~Lp*&r za3Dj&4mHFTj9{HO1w%846i6LBz`-#C=YgcK1iylj0o)V|1JuY+uz+_RQM-x87?*Dw zDp*)rz&eIT3dV+pI7Whv%}vaR9|_L1nUZ_|+&eYJlNn?ka5A~&V3bQB4ilrzy~+nbh6-gznAO5PRA-hJP<`~JNC_rG8Mw7p(hYtjGz zzeWG&9siDNmN8{=UOe<5*1^`Mk7MH0iJ^=oKEAx7jIV^)k_Ck?D>i5-iS=K06?7DJ z2#btlH2CzL=>Z4BvK31G3+i-|8u;$1cQlk1t1}5%O}g*d)iBN657{Fc>J$_ij-1$V;uMpF&Mb}{4S5kV++TL9I?vIT z3;46S=i~REt3?@v{;XKW&?#@G%DBptNA9^OOM*kV*b2#cRZ<>bKmAX99bRZ#udi=B z<$L+h_szeyo1Kz=E&9ctWzY70dqEY3WfeRg2mX3(W&QspjVo!xzkB=3csn)pb)vYR zKVxMQh_sZPac6$%n)!0mSdu10DBY4RaIO5=X#Yxq@AGQmS3l~0G-S=azTNcd#DB&& zO0@QUA$4?QiEwWu*kq1FSQ6c+|XAgYNGS>)Su4l&}3*@&*fY2EFwR z3piLp1h{*&Sf@{CcS>Q@;bWe}Fu}!?XX?R+omX@jN)4tngxfSetzPxXi{VPU6p!5J zz5f<3QQ&s?yC~fcIThol$B}=AJ{LjVL1AaIcR&;zm`n~ z3|+t3mrVLw=VT$%!1ll4zg=u@u8k%Oo5O=oSLRO*ox&>eG;#Vrao)H73Jn&I`d@qd zzR-WuwX}_^Nk!o7r#z1Su)VJ)##OG>cys6Oy(BhI`-MHf!>wO0o|m@bl#bsDxmxEH zuQoEdUb9?mVY`9f;?lHUc_+hlpMw8Pjas-?aoU9y+vlv!xie|!%xONWU%0ZX-!k*^ zR^I*n?Tek|$L)WFc&_j3$n#;lVmxJ*&Izq&AN7x45a;E8Tg&&E=l!gz<5k?sRpr=$(s92UD+Lw>zAK!D`s*p7@-|_AKNAte#)qNXNHI4`Qyli8hqTYY#bGu9E zChv`@&n7cV@n#yST6`71%74`6io@ndZ<`K3EB&Dq7NTnFySV0M^MvC|>cSpNyf4`0 zY#U*`=B(qkl-uv;@|B7u(VuZ8c)9UnJ-JXGEPovTXXrCku$J&o0Rb_Y49a5{FdfB%+VRu*j++aVy-#6G3a zCFg?H<*s&VCv4M#={hjku@pnlAP70X#(%YRNwP7X2ud}32cPW%Qn4JEL!jp1k6I(|QsKD$lsNB9_L&|>pI7gj$yIcl)mUt)PW;n#bL*Rw z_bsf*&0r1jZ0jrVN<6DP!KC9tdf1Yq(Q1#?GjGc6t*&j|?74WIuXe%W-@gRqy||0( z*KjpfeqF8db1BpJnLBkhzY*w-{B$UFv6W5j{A)QSm6ImM?_=RTt@pobDq#+UwyTBKF;~| zCMdVQ?u6aF>i2toef#V4mgVA+Ib2VFxL%sxb?ElYzpQ(Lx%RYOb35-?t9CJ({qglH zrW2huRdnt>8Ik>Mt>PEmx%YnknS3!?{N5`!Zu_a3xprEX3+&9-SD6G}R?*P5>zh-z zclF1Q)t9dP5?Wk#Jm_2a?VgyI8Oa>qny)l)JbNOY@b1lvsVRxeqd(e|$cFoesCR}R zfA6ibRwJ+|L-f(laB)L1^Dlx&?)je-%UHJjT!BDQl;6u)_D5gd`Ca1nu5$TouTL*7 z_^SD$UG<~I0h=(w7-HpBkKA*nv`owpUP+|Ijpa$aTUWMo+sw%}MyKra&CY&wkt{PY zyplQ7wli$j!X@hI=RQ2{tug$+r|EQHuTCZkzU*UpLti9y#4<-oL-9$(2{mWwNS$3_aT{`)|gwmuIZ`<}FpKJ36&!x}0a; zw&xd@O$%EwTlMwZ61K*5yO$WGxGg*b?pgEOb^u6lHC z^VRZ4pKaD{-VwU#+C4GDkV%)1C6~KcE8Ub0F*;e{oc+zZti%I@!4W*vUQl%MWeyo!)PE ztvOxxdhWl6ZBuTa7YP$R#H!4Ej77fQBj-f$Z26zI&tgwboW1iO7G8C2yBiB~SH!bW!%Bhw{Ue&HigAg~gotcRq{h z?C)FQLeH0c{+S@Je?a|B^%dd$Gw(c~^6td$zZT1DRU6wC6t?x3ov>FlnZL+LPhOq1 zU;mBAoSaoN@5dF3?OU+#q;WNiq1cZ{f@$9u96NnD%GUeT+pHWRiSEyPH4kr}w)=g_ zlxLaUrI}J&-u(#K?!g^**yGl^)n3=xy!=Fdn3o%w|BNCi!w?Y?9@0~HY;>a zYkp@+Ghb`0#6#~(ymeo8-F>-Iz^Wze`ORDAlTPL@%m4JhBVBAq;4FpH8sBoPlgew@ zk zsn2gCw?&Ft=Y&ieX!Zpr0iTp zU3J4@+fAK^|AhJEEL~UYmaDsIdWF~b3k$#Kd3mH? zUaqok!HoWeY)&4t3q&#mH7m?Q1#j1En#Z)f|4wOqWkL27r}^xa^Ta+|&RDqI9XCPmLoDYw6cT@T&8)#`iZdUNYL zq3JvJ#ce$&*17TGdl9$u+&}aSxh*OR{>jBApIOo9*WHlw>d}#iRbs9n}w z`nKYAC-d^WeSCA(n>SAIT3hU8sWtoWOILO6DBJiWUL})c9^I;DTKePkx()8D-@Azy z?c=T3aasD_Gz;6*T{m*tURk`EZOd!S8q+lOukWh$6OzTA=uG^=!BLTsZ2#f**N2OWS4Pp54A&w!gK$ZV1iN^pl7wK&7IWkZDn&w7vS-KP)u zU5->$x36V-r4fB`>i)m1c};y*TNVCEntp$>^T4tVchh3d6zR4mm1ia%aQ!Fs%!lde zE$@HUXJzA+^Tl?rUANTGa@o2oB}Spf^92sZ&gr#QJA6C+)|FSvk7LxNc3<1!H^-=B zj=<~>&p2k?d6n~PhQ$4%s0$s*tX$rDZYj@S^51^hd3ml-TGy_i^S{4&Gp#-|sntq# zYFw3#asDeCt&5Aid=_!kmp5H~@#I~O&GVi~L6P@sgHE*XzVrUf%tLSDEspfJ^xv0w zdg_&cvzn4pXs?NO_%yw)2`qQq zzDKv8m)f9Tb?#ME-g2F#`|PxLO`BmFe6@L7u27}u5h)?lN=?=cnKS;seY`vQ$UgqN zS@NeMdAZ{rbYX_u?NN{A4w$qj3GK7hX#FcMKkYx)A9s!g zdmTg?JHERK+C=_ioz_2rgDW*Jr5Lho2|mVz*|!JH%Hthl0`I#+9%C{E^`zk|0E~=~ zMwvis&QV6093$MreVw(PeSJN#tN;MtCx<+OVgeR{4L(2znan_w{6ww*K(!Bfm5qVY}1CN0%P0(|z~u*VDPhYdx?3;`?rQ>$;!cr`^Xt*T1Xwa9d|^VMX>v zuZX6zjGGeJ#l!r}{1me^MRRis5&TQovoi&u!RWmItI>G#vZqufWQ#ZD9I; zf2w!*@&9r~%noxFE?gnGP;uspg@U>V`4s%Kyc`Vindk)SqNvKmC6$@_;+Mbo=lA@dKE0=z^@h+3 z23!6;HCNIEI%cX%eMxZWoPKNeWT_VkoF5jjRXBX!wAr#Dc0qrD^YkOrZ*lQB{!TaF zxpU>sg@+Z4f7gGh_qMt6#&2DMc*9c57p_m1rCa*?-96Jbq|~fg?_hn% z!T(i%?py!AZ^X~OrBRaQ0RvOS-=#(WrvKXCwR6GTx&JdC=6qLjT5Q!6GdG?kBY=Cu z-n}=w4|$)>d;Btkxu9a=kAI>v9Ce;2nCEsIpEz^#nQP;@Bisy(`#COnHpnvkPmIf` z68}EEFfJocT$D?!>4aLvjPjl0P3OEHwl1)p8ppBg#wmT4(tt|E7f(XsIbJRQCNI?RYvq1{EB=pL z7Z_ixQCzY68n@&0kl(EfB1_^pUakA?6j1(GylI#8pY{dfTDvWeoH@kz;FCSya)s~p zU;bCxur734cOhTw$W11m%9{x6Rb-g+&hPIX}h!ZLY6>XrKO4 zzvbD6f7}ZvZ~Mu;FtMRt(WK>WJclpiFYbkgar<7*nR7vcuU^rF?T3ELv4TI`3-?Xf z|6%^)-{MZ&?>z+x{pDV0c;}x}2G4i#Cr!Vq{OUF8zw$lNI|sMY`%k43o}^43CqYl}p3^uhWs0&*m=dKJ~ZpjOD7U z?vJOxDO?a-bL-3HX|rF3?Fu)Z`7d%;*Yjn{Z%aSem3cqDa+Fbj&8;J+3Opw{I_6*V zykED@YVnqDW}k$3&+sd6|0OS}So7!Crk4tHKU}zV{f@~ji%dUNL7RuC-&uIh7ntVW z{5R)t;H(HS|ATASRh0kKuX`1W%KiWy|?yp`=>8Wc_d?KSa)@KzE^I+ zqrFcbeE8s5u&rnB%7lup6I)+CI3wI}aEqo-K%eS~998}Q$}XLM7PNl-Yn!5T@Z7K3 zDl66ZFJDhtr0r%Y7<@FP&U^NKKA$$@>kIxKS)&pYr|0rT=Wr+Yr8mD-e*H8sw)(T| z&GIuE>VA12qkgUqNIZ2^SnU5BZp)}Q_H#C0KJ`6tXOGDJ?{l^@+;3mmkz!JxBxAQdv?_18B*Sz z=T$rRa{Xj{nzZEVvYO|A`j`}$pHl(!wv>!?qEmvAS$MC{CmhAvP zocB-f96tOo*nfjsy!?i(;jesOeEZ9}oLzZk`V80e2VOBm=bTzUb;YA_i!X~~uNFMA zZhC*Na+X1C;X1a^Ql9+=1;UbB4l77TUX~r4=2dzuv_feAg;1?%VUX_#?>zkSKm2j<`}9c&(!ek zp6TU3S6pn;&%FLE^diITa(kb9rO2Wf4q^B0U7J2^b&q!J)lFkQS2n{bSofCSyd7Or z&UmyhJ@UI$YEx~~ZNIPOZKvW&D(+( z`wLD?&L~I`a}hc+$)oi9AGL2Mc4~$lcwEV|;k|3S;!me-20g2;zOX3h6S}O*CzWzk z*qzP&7JI^*>tEc1B-a|>)YzU=mNu(xj?Bk}mpdl?D)x>Ocz3Z%g`=oE@Je z{&VWv?wuZZclyHMMHS7)Q+Dkyc`p6)-^VBwd(DnH2WNb|xT`X!%Ie+kaAn@>8ZI;S zE)~x1uRGlNCdYoMPnyLPiHVonZ^l1gAtK7vxN-m068nR5PJDcLscijU0Z#6iV)0X^ z8G(VqH{6443j{RO<(v}I#h;63ANJU=p>oR0xp!uI=Ue5hRsVHacd62ShMReB{^&kk zQxhF)tZF@T%kG~us`6G|aBer?d#-cun#)PWZzWP+IyMNERm}Y?yw5V_r?{q$`Oc6Y zTf2M#zPo~TN2|J?|CCsMq_FI!$W3Li{u?HY45S~*RiS9j(=d16)c<*^IkSH z;(fQU-pROn$Y-|p-_^7fb=XsG6 zuhGecH-%-T9xYYMttzisQf%PI?!5E&JV-*GG!pz4ARd`{>TEDgpJOa~4$H7EE-wA8ot! z1MlmNC;GoKZmpfWy7BIY(`P&Q?)}?ewS>*fnrCfQocsP=%jM#JC))gJ?u*^y5v6f{ zilW4{9kMgq?>O*yXN&SB-q`zma^fFNE_c)BSJS_$>&fVZ-C&v~a9T-7_KHHIW!}FT zv%H$-G(O9kyYJbjg=dW(zjh4>pPb)%__&FbbhD4+RwTblod!zNH>>Se=ui|PNxv5#qAoo!_uS&a4^ zJ?QjA{KtHY;G!6fFNy4DqSyaSXp*18n!P08>MJ3S3p=~HydMUu*Ogy*&1e_%#X^3X zmQKx@Rh91}Z@!d2ix*f9Pyu~-#s)jYSH(ckDG+I-uRYrtl-&- zM>EX}S9(5;@rX7slR0qzgSG3y&%Uoby%#Kd|ES=3oM^_sI|~l3cC7sxeXs80)+rx2 z+9i1(PxV+-soH)pDgW6*u?d}*{EOud#t6uFa=5im)ViMaQhegdbt|IQyg05|RJi`% zyzhk%=3Or_c?EEU84EyqTa08sta4UYR`Gd>wiyU-YFwbUTT9T6*|Ouu+Cq5?bD6f)9Y?;vlBL0 z!@H$s@uiQ)i*9YqdTE(@&m^q-Pl5dlMVVK!8DRu?FG@sUSIaU?Cn6N#NQ)JR(d4t(zN0z)UT^@WlJ?68v>BS>E zPW2mWO7FiXWOlXgeRf5R#_AcpYTpc$(pSpIy=B^_<1uwblhlb1=`+tM1(g4YZSZ#I z@m>0dY3}lqXA@gqIY;g2PhH{XP@(YfUy0eK_p1#%UmZJc(VPG6c7Msi{MP9{$N19! z*l)QQcIFpb-9On7#r(|1HQw9uHH#PTShLJ`&BD*FXS<*LcKfF3@wnlj;{ACKmQCcB zIV9Ha7h*Y2<#$QMjtf@8#o-rCgC+^aE!`h#*HHa>$rq_(*AuU_&i?uR+{IqzRa3N` z3eNa2T{WG0KJ943I`+*DujhIF)?BB=xBuPRoUL2tPUx4+$?=x%(yFPSt=ee$e_q

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

y=bH&1vO%a25Bdj(SJEZTs}A zPU$s%a#{B2ki~N2EBZ?9rE2<2*MF7qE_kxWf5|bYy;TqAKCSM*akjq8j{CM{{=~H} zbiaH_n$pVPRJo2TTt4xr@PW=?-A1EFOR{6{E|^=`=^VFqmDc=Y3uYLtbm=0yh6 z^Um8I|NW&dE&U;Hk57fSyPvW0^+^+cF?_tFa*x@5nR47RwkfLvooZ|>jCNNyv|GuE zJgGXd`j)+vrQ`yAy@u0~Jy&D z#lcc&QJCeKCs*71TY@ZeW z>uNxx!m`JWj(d7S<4=hQO{}m!sAE)iUF17+7DQqX*8*c0KX|du}1-ZKW4(@lFm=19Bojf@zw7Bx{Bk1-_v!Joi^|7ad@op zYyNDWD0Zh4x^rB)6IJKU@-tu&xxaauMy)|Qya%Z~P)g8aT&8+Zd?5`DVAs-zUQo-m9$f{0RSo zTKR>VHd_mV-wT+ZT3+KCUbRZxy>>--L_tpf!PXrIypp?Kwt4z}eHGr3`gbbc+EG1EB$`6pRM$kce7eY|3<@R^`i^yNm2`l)h#cm|D zuQul7JnjwW3=Wrso?`rTU8=(QU!v}Yc~?usG}t~fnLleY{`A&dPfm)huwTmDlq2%< zevd7yxvy0B*&Lp8|MeNKLvv63+R-xWc)hShPQ{ihb?S3xcx9ID47qKev2;JrIpxGQ zdx8A|?5EG47t5YJamt6}HHW`lef7E~en(u*#`T9n!y8}veZIHiU{~hjD|=KwIm~m{ z-`8jO{c6^_Eu1MVKDXMLHZ0m5&UyTMrw$e6jP6iTlBJ|WHIuB_+nEUv7YjWwq?$fp+f9Fn2FTUoR{cUOSgp&I` z|6D8BbpDn66BN{3_CzOlsn))<&LbGTfBCT7VC9Ko!gU>)^>fe*stP! z?TOEN!3SHMc0Wl@ti1cUPj>DMo*C<%@8ADs`X%w@Z?*l~+m`Rh7ks@uB;VXi_{PH9 zP1}E8ZR*k2uHA4vvfIFE&w|p)&!-)^cqG?s&im$1#ZhW|&N?gTgcqkxH=pNy?DVTtEqpC=g(<4e$4(yv5e-#v&Z-E`8z3;<#%jMs4HMdtGSV`9Q8tnVUzm+4sNs_#!uG z*N1xxIRkko);udYa(AnLr(N9Fz6;%LF4uNHiC>*{Q?Q5K@X`C_J(2Zu&#j$T#F)Z$ zweZ<<{`1dIL>%CGoxcClEZ0cSt?SQ5D?9wCz2SdVV(YPo_X20mZ?|G!8E^dlBA4mI zSefv!U?u~#Ve1U7p|Mc?`t;O?^epH1VnRdQp+ z^-p;g^uG8#`_pmW_YaRBn7a8@&ynw2{xGX8+n+V-e(|gcmDNEOz4zC5+;tU}UK{SS zXYPiI9ey|DYhK@7B-wPX)BfnA>3i#$Ra2)$v9Law;o}hTEGl^8WWn-z0Y6x0yDz`7 zM{VQGS_NsLwA_UzrpLA~&GdiTA5ngLamUWBueLWgUkq9B*tIrXM91RRyt<}nz4%Lo z1}x5V{MuBGl&x5LIZln+{&w)QD{^0+Bxr1|m}MwA*IRZUgPllL?0gxE$;()4Zhfkm zXS(U$(m#3Yc7#TqntkG>m_W`#{rQ1X|6ZN^{Cd$BQ>I5QFE-fwEzkO3XY0SPboJvd zWBI$yt?s|h>lWLeme|E&8?mp6fBrqoL~ZW8RUfC`RLHGeax#jcI!#sSuUcQ>Xt8khAtFXmgn?lz`6c;vx{H|1EoK?6`@7A=c zrAd~S5}&s|yz}8l;D_~6I@|sq=0Ejc|HFS5Mq}#*oyIo~-aB$r?CE}nKVN&4Kr4&U z))ON_xHF!$kFVr-0ii7|?GSXUUE zo8h^a-3+?G*udNX@7Y0VX_@+krTHbPDM>kygM+|l2<4=vl|YVcfe2<)7G$L65k8G2 zvn*A=II}_@yzE)uQQukLMc+-|9eikz4`|V=et>?kehA!3usxXP1>rs|s8YWQWr;I* zy(!8PXK>7cmpGeRf?~zO0<=yT#3F=EjX{wPQ)OaktN_9gzOku^f{~@E0!R%yHh_yl zSP&fu(%cfX9^Tx{T*1N+WP_Qdv4VxMi2_L6*aEb^*+9X}%tXP`+!!oopkQtU5e4}G zqz_>hhy}7AM1wGh4N_%d4qE$cpa7zcjiBzdGyuEVK*7|^5X=IF1xPha7f9U1&_uz+ z&=Txdu$-Bp0>nJByVTnllp_=@5H7GZf(HgDe<)ZY)`5do zd841Mg|?R49QRpU3Wi3A^NI|O3_&Mv;XHuI#9YBZ0T$PgwcDVCfwYj@(8K_K8j-Pr zsWE(2w}PRixe<6BH!c`Tag${Lkuq z-0S&Y>+b*FyT5$ze*gIC@3M2wJAHRPr_m(Yta3qWLFJDC#tANpFJ51+5MXW&JTkG- z@ft%$Dl5~sCV>MjObsE~!P?nfoR0Df7Cv;6lR0#Z!Fkq2rjtw?o;%shIO)K^&vvYB z#}2m12N`Pu)p!z}gc8m_WU%8Ft~tQ|$a#-PhpSS9!hxol5*y^X8U>ju5B6&d^)QLe zKds~VV|tj%k;jjhF*x5@BG?d}vXH}_W5a?3rklb?&o>pQ|K|>l@3!W)knv|Lca%H- z!atTx{29mptL{4=GVwfOl+)mTq!=Ikcft8LMk+YQyEInoM#Tu732iin?mAUS%A!?&W+59P(mdiS0sb)Rbx%vo;m=l&w@JFYzc z8b9V#6qsyicUlzSFsEaG{Jy4rR;M@<7wJeGynb*FmqCS1+k}SqtbJ!1B?KA-#YA`= zF7Ajo;&e2uVL71O$=nnum-x`=>>386E(h+Tt~q{;Cn7|Cv9lGPdFD7@vi_epJG+V1 zF^PEBWZ@bSmbE^N+{IpZ>IG&p$?-dFILdlx^RK4nM4L#CuC^I12N|biPL_$fP_o15 z-peUFyb4$EarP+Q_WY+dzg5U2xu++J&)q5PzVU0z!TN7G6QA987j-vxJNxp(2hl$5$VvtZLm~ESMgCY9SkQaIE~+Lmj6=HcwfovGvcLrOw|c zJ#r4764kNaZ{b^}-kZT*ODjJ&8n3V3e{*xx6@Ol*s$cS(*mua7DgRx;eKF_p#o(Do z*X9;)HdXq>w=r|FW0~Tm?XgpiFRU65B+P$>C5-PU++vVf$WzFt) zzpoUm*!lC@+8e%0U!Qq#aj#@qto*dH_}R-}pI;ZS=eFkFqQ}lP*IS-l*sQZz+&f(< zk8fheve!TVYvlD;lv;j0^3UcW-^=p-JdscQX7$J{*wy}g$Ay&81&fze1h4H>jX&Bb z5dUd=`J+VrUtaI~@8+wp%si5Rrj5gzaw|H}-_y`&3vp>-7}%D|bX2=h}JS zSe~9cb6V~k&F^oObMud%>76jqoq65w#VW7u-*(SQzx(g!uD_jJZ*IRm<7=Jvc6ZkI z&TZl?Pi?bf;=ZU{E1tCe!^NP?6`%Hgub#VmlYF_Rm}S{j)$kR?+*5Ow{;Se1ySAfX zgS7hJXNT6lf2y)haJu-E{r(wI-<)Q}e|}ixx3egNY5U2~(-X2%gB;(7>GWU85z{KV z{rlGT(`F01UYeyxOf5IL^S1C<@9$^#%Aa>ePtsqyzc|V$F7kS~&XsP#w``&>-%h!n z_42F7Rt1eOUouve?AY?^4*!8YG22h6%LWF!zg)BRqGoAbmaz4W^*#3vU;1l%!tv_s zcJ8nJr*B>3iD*+;w6Y;<-@cI5q0d&jOyN>t`7rH|)zzDi&$8NDcQeoZVsvD)bK>!8 z-_?oEk53-tRj(J7uU(h2^~)KB-TSXSt80jOezWIeR_R>rr%~pIGguuCJ(w`v_u}gN zS6-j3R$?;UA}z-3%dblus=ei%( zTa!;+t^DfaUVChY%^siCk4vw=oAJCect+U5H=>RYe`YE@oV-dVaCUx4%)WWX`^+b< zemZgY>{+SS7Zxj5&;7e;;didesi!){KJy;GqpPaQc-b_m(x7DTS__@2v4wly9NH#q zX}nOVx8}dY?k`VtexLNY8(Xm7DQcekl?B!EIop3)t@cZ4OK3g$F8f|qx^CpmNTrj- z5BXlrzWC$qtg_pS)i${Ihwdzl6cqereonLdR@ai)={}bi%n!4(uV@Q>zhmvLFaN%{ zg}vQm@#f6WMblSld#Ch0e|@iZPJnzci_tgVc}3N)8sv7~xw-0~g~#Q+i}$MZ>V6N{ z{c-Yaub=nAXJzkg-uOEIio1Qr?bLZS7NPbZCfV(+>hC(ZJ#>=f->QG}zI~GUc|_tV z^SN>pv-T{B-SM(n`=;$!XD`?oT<7JuX8T{eoq^qE#g|yu&O7%ed#dc}PjA$<@9g?~ z=(Ofaxs@_Kc^nsB%scmWZ{<~`7nzT_Qg@zt%E`}@qW||;(Db9SN?t6xo^$WLYAPQQ z-)qWndD`U_leQY3h(3Y?Q^S ztEjCN@VREmy~%33&1c`a{5hoaR{Q<9x=#u3e)eCt`t)4#$QK6nE$yG;?OOJ;{L^Qd zA=7d2aDZO3xZ4l)gH4JPvGm4FFt^ST?2Umsa409ant<9Cu#;R(4G|kYO+c+-l+KvH zr&ENtH>fjahS?c20X4Ug`vgW{5m;M>jLsN}byz!N7RIDoP&*+!90fj~O^Xz$BhPowWD=>EdLufoH@v%@i5{2p#z6b9O4$38XlaS$hN`2$hcb}D4?UM;h0_+-?yY=dJb_6-2D97 z4mSi@5}vYbF!;P_bJKqTO@>8$ee)EwxxK|1wrZTUpS*+NP?^JosVg_yI^4T)R49Y} zTw+!ZcR;DZR;FDQMocZaxr|!>Z65LjFj_G?<~bOoQ5KW#GmtjL|W z{=N^)6i<%U4o-2ulBP|?OFRK_KJ<{|H)tH-~696&7LQZ|HLWg1*du5>2p^o{rJBB|K__JQ)biM2U>nULcY0v9}EN=hdYzmdl zjh*|S<-nq4d}U?F>Xl>|)V%%Oy%+qQFYtW-k+m}aBsMi)f0UE`Cg-O*Q(ULGz>^Q^ z3~?>Zwjb=zFm5X^{BL}Y@mtwO7RLXx7{koU3t0bhHk6)Sd*|OQ#%rZ)?_bqR=)C4B z`F(mSvrbz6*Ye1B^*9K|TDjz4QsrZ<~KS zH)H%4_=H88P)Jo`9G3Eaxh}m+sRl~m=S^nqsdwKq) zmld%8lL?pGF#n`H)9;!8+9PHh)HV3c{r~30{U7E({wChER`;LNhSg8wIl{L5;y##l ztzPlQ$!Gd3-Z%fXCakvaPGyWw_W4$?c;nPVeU@m;f2|4H%l8Z9u>RuyZ}}f2{8XPM zdM8MD`+k9(r~lX^4~EHs#6Rn^L|6W8P2d%NT;KiYzWDZzj^=iAX6uH=slCiKTOtp* zPrUiP-p9Cu=gZCO zcjvk7o*B26C2IQ2PxGw%mXsfKU-8!0`1)~~30=Y2i=Upn<;raNyxE=A>q=5qb%C~u zfbFh4UfW2;IWbW}Gq=5ZxUh6ej*3>sOTVXrZyv6GmvOT5eONu~@5uJU+b`(GTa@fb zvZ-r4?_XuwQen{A%aRI`DCmW9MU8SD(af8(2e*T6P`Y)3f8Jt}8^5lxn zd6}EzbM{BSn)PGtt#50O3nx9R6h7GUP5s`z2{NX4So$|VF(w|YTZ@qri1 zd*gns3jMgmd!t-yvWTqw%(_iSs+~^o37!q_S)X$~wtfD?`xok$CZ0SmYc2Nedro|y zxJ+P9ae$3rV)^gD{=z4Bgt~A1;F6D0Ze24gXyq~y=Wv+=|K-vioSVHw_2%|dAI^ML z*Y}^6qT{f#(0zl$3m3QbGbSa*ZTTPYN3i9`k#@7KfugsA87ACimvlIjKh-*=qU1rL z@2@_?$4cd zeRHDc%qscvA?Cq@4L$1fPVK9ncy0gH#mAY`W_lj`zVb%myX+Z{1(z#5iTZQma`=Mv zsquE)$I^YzeLU6m;?X-Tu2%`#wJ+aKJTf)?ci7C1X!V7>fs2I1Vd)*?7 z(>l79i8H?}IDg^{SIxz%cV=eP)akc!-$+x9?W>+Q*X`$r3&++(JUe-K$Hj|(cek8a zy6?fv>GJGc_x(2FRap-SOk9;SbNVw!tW@sV-Py*IxO!%FjK^-@e)(I#GY;E z(=^D>o`3$HP{Oit)@ z?<_mDfAgE-)0xWV>os)5HhtRctMj_GOjvNMn0wt5vySQAA71yG?u*?Odqj7ZtNQz* z+AOiOJu}KA3+(uHA7(pU*zV?YMk@E$^scQws$Rj{x!20BUaN9pTGIpHQVZXnsjM%b ztg&oP|1*!vPxo78L;_1uo?U0u&ECwYOOpk+ZnAu({3X}r(2TZ*&YefsSZbGku?#u* z^_$~^r@UV+>W|5uz0yC0cai>=Uba1P^X@N5ZhD-Xb9?KiSxG;?xYafo-VdPLUX)A;-RsWAYPM6>F>{_u#i?)c(c%{@thkRe-1xYyPb#}t;d{5+*DVkFU-}AN zmb97p!D(sDbnT)%yUkpySWX#gH62SiYQKHI(b1!kt2g#{*ft~_Q8nYQtiO0C?0U$( zmy+^K6E4{FCu$ttr8oQTAC;s0s?YSk99!k>7o3#$B=CXlTUlYyI}tP`C%Wo-`Y#J9DQZeL%@PZn3;)m=a7(c{YkM-TGa|3U-AOjz^}(H-_p`4? zFSl2o(5YG*_PR9U$+_HJS1(S87tDF0CDX8GW#z9@c6O6>s&8)^%?p`#!dO_AQ~#Uh zTIa8mQ`PGA?f7ReUq9i1o}Buso!cd{5+)s!SadLwJAGd39nZ+wl9l$M6HHF5+j;W0 zW1^_VC$|Nsm6{?KTuPfOo|(l{9;w}Evf#4a*}!`(o>LC&x)C$z-epHH$KQ}dzzlc$wWeOxVE z=W44dv-*Ts-_n)KjH)*lnjC$*rr&dRe4wU*__>e$OT^~KUv+vPAh7)8owtQ+p0Yjt zdbKG@M3#Ml*K+p>yP5W9EOJxUoxhw@^J}|;#xe~Z>r=brk4Ma1`M^-7n4?O;?mT-a zS8}k;d(Vxt0c zxRau$N`2Grg`JIE<26ft@#U(VpqxjXtC{<`<}Qn$|03I^D)QLX@cgx*y6#?^4$oV= zYu$_YCxX~>v%~i^uF-jO;qS~?7_$;_6{UoFGNQ4y*CH{7`RVVAi+uOhLG~3AC*gLsn zf8VlCXM0*zvJJE6w|6?n^DF*aArzGAu!Ga{-Jw8@(#&($z13FyIefEvt9!a^qzlywc8bJ zgpV-4=Tx<@w%XCLdQFeQf%Vxj`!5BmaPHmoAn^vL{fP(bts{5;6^%^1r#1fouXtDd zL(Tck7MqqmX_nKOf5kTU(ro`N^178_yLq43E%~**ME#Vx?#xNATyDPgUAN)I@iy^O zd~aq8@or@O8<_9n{B`n-g1q%V4>tCxFZ?c>@i_nPEY_FV1(P()<~_2W7hpy>p%;0srmcMlQC(TTkFP@TX zKTNwIWpd8xKwHHP?LQ%3-w2f3I973dImO|b>9|c!hkuu2Ygy*GpFMW^k#&h0N*m+# z^EOnd$WPs!KlixcBJ(iY*}Jb_pL_X~jIPn+y0X@YKd!IN^{m-)dFJe#>N8I0XCG3l%*~SUm-b`L}NYmeG`(_g|OI0H5}7ksrjfs(4r%isfy>p!?hEgD|%PuE-(pn z+8gqSZ|?O2g8s6~^Do9nXk1BuE+Qipar(xK4*PfB-3PK6yu#}~OjpX^>9yJ6#@|~H zOL{!6@7=M_>CQJ(Tl-Ci<7;cKGX~^|@!!0DJVVW3pTt*Rh59Sc?;Qvhe_3nwu)?`? zS@rY^6|ZmF8fgcgJk?7!dT;(jL{eJWB`Iy@xs(%=8TLOfl6hRZ;K?=ZUyfX!vDbBU z&PMNB=P0cgkh(K+NyV&{j7Q&W*U#`+zth;O=jz@(tH+)yd(Sd7Sd>J*O0b@}I_#>* zy3G;6i@qsqJ?nXNe0_z`sl8?Qx15dMJR@b7muT`Ik2bWM1c|Eh&*R`%O-y{9&N7jDEs{F)CpMyL8&3wRaHIGI9BpShK=LYIZ=z{d|cW?VVo}Gv7Y=dgYq^iNxM%lWwYI{g|NoTIjRf)NgOk zohYrm7HpsQ$@uSjTaDcvdG34CI$!=OwsZ0CS~tnT>>u~vbZ3oeGw(0l==aCBedi1h z)uPI2FDn^hZ#-P9YjgF_z2^^?aL)Qt6&DzASTHsFh#NmowNh<8KHzC_ znQ%NU^!nt5|Bt9zt&f>!d%iWdyHRn$_vB`c3H3UwpHw|{>Z@d2mHT|3H0zUxiKl8` zwMksI)_>)luk=fCp6bJ;$GIgerk_<5v@e_4P~~Nwv3=u|7^B_2p3d+0+g;F$>4KTWQXX6n*!{ z{}6v4BTG z)xR^U#J^4!u`il9|K&NgS6j|?ML$2&V^y8IS>rK-wBYXsIi;ojZpXUjzwfS@a?+qj zJC5yVRNh?Xu629FU+u1Zu9-i%p+ul$Z8N_;X8{%I|I@y$dur~hql)$xrr=??ik`Rl%&jlTT7ZuT#~wexFCy&O*- z?MhkwcA4YMTH$%^D}`;IOgd?DA>i%u*t+#{7vJYGbEFhr&ak|=X6xfGzOlFd`UbR> z{*L2z3w*HNU(GIeqDj}xjiJxnk6vZjwTu}stoI#7TUZOy zK6-yiOzK$Gvgf5`#N(PR1~&EPKhEh*+^eS2w8uoSeg%`zf1|BZzD#W!+9j8LEq|mP zE8IW%)UVg=tQ@PYCbl!ihB$9szru6ns(H^BY`7NrXPcXdxyWXnl$kpd^Ls2G9Gh}^ z>V_=|DF*Fd4?MV%oOk`kap`9{|BaP|_?{QUU9P>X@jgV?UbTgz<(Q|(!N8B9$rTG+ z?T>n8?oRs~ZL@8X&p$r>=rg--Yad*>;Oy?trYOz_F-AD7UIyY~~ z9|_St?2&&ow@E_Ddq2nhkerG;N}tnxgEiNeEQt8jex&=D*R;;4=BLSOE8|0V+?w8h z<$j8q?hj_CD+Ujr#uR6Stk2K8##0}!zkczoeaSly8ARRx5GJ;z=F63zTOQUQ`L*&k zd%1V!|2t3Zj#x~u&UN6gPP-=kYWCH2;_4qAA4V+Ol6a+OiPp;$!?ND|tE%^}WZdVN z6`aD@zRW_rd`&FlvI*HeRfo8q{>suev~K54~zXYo79nf9-%(thi%>)0>3eiEAz zH`h&5<-P>whIY#m6Aj0w-{x*uTysol8b_ge(3UE*L<4g1+{`{Q+^em(_H0L9`g8$X4;(>i!XfLH@j`lv3=~N zOLolr%kxITqJ8b7g}%};&$Oa%-Y}bPoMsr$7#JP*>Z&f=McugzCY+yT@M~qyGOr(h z`IdfrJ*RS#-NaC-e|zGV&k$ML#gWRjcDHUx(C*5;^OLQmYqHMG@-nUHI{H{|uBGYf zCCz@Dx_&*Ct!EL6Dq9$SWv8Jg+uWyB_v&=?Caj+J?aDLd>o0Dl?C3dnPsMuXm(~;3 znJLSrvh2QNWI8kVo7@w|9bC^7*k3tp6&K&vsT1*7x@X14auX+!YeH<_RN^*G~K4 z@NiWH{#0(FgxKT_H09OZz{L?st)_}nboFNYq!SF@{~5*@<*d0 zQSw*gwm;S1rhD&^y4h3z(8z^*(atZ$+Z+#U@qTPQYx`HZLr0os>DXOQ%n+Nu-c(;} z?pBG~wMB9A^H>c9_xDPy<$Cl(^x&iN8=QCUy*~V6(WRdb4h4ad)jC@)?0vhfa<^A$ z&)l4Vx^AHdT8YU5S4FnDCkF8(o=SdJU=nou{f33LHnKes7@YCVB9R94G#t(l5D86|<)s1bVwMk^(@*ce{ZYJ`rWk)7WKKOp! z^2_>l?@wF5m^D-ViBx#3KmQC*-CLn1ci->^8j3pJVZ6L1eBVBk)Qgh7%-pXx<61~V+#ywq z{X)0a{^lw@Ev~O#Q;%*{|#Eki7h>ezh9+gr9!`@9of8A)a!1 z@`9JAa-_P=D~(N#&$gV>YSr8GoUu?(cJ9-wovppek44z_mY(mp9pkV4;G^vGiywX+ zTNr+Q%Zg>X8+(Piew>y_{;wx{E#V2X;or%^8;TF@JEiv_df&Q~gr99%f-fr{b??kz z&AQ+5f5nzHPvKWIOeq$N4~T^J?HEDHuq=dUs=xx zJ$x-R-Q8q^&Y>sE?wS4A@1V<)%2z7wf4C{VB$H*sABBKJ`LEnm52BIrt-)WTv?wZc1wyB6O_Rjf5%72(ApD6Gv zv-+5Cxu(%%*Y$0p(lX!Wd;6MC-kcG4e(z=XZ^iF5>@0Xv{qF|Pb^EjKee?gQ}m@=lrvN#`wefw%sbm%4@byuGC#`Kj(I(3vjPF0G@#8zFYX&dT90$<84&oWrAy(vXarDN&-%9)>KYtR0ul5Z2+_tSQ3@7ok# z!Q+b)KAk*2XID4d_0>&t{{Ou?J>d7#$iA*?CfAsLB`=6tbHC<5&HGI~zn)LLwd>`| zlC_u4uihfCVQJv}UVo#`V~e^B7;gCe@(wwc8!ORM%NKL8v_Hjtw&vNr7mJrgy+~78 zkup~<@YLk1H{WEZylmy(Ixn2jBmRBqRn2QFXMKJ0`tjl~uljmebH(Pcl)tIXoi=sp zEJ>f{)ed^k?%%iC6_a7r6RhiZac08DoGtp@b{FUAb_wd<-Z@b#-Xd}N&i=dq)b4$} zH0SH(CliXcI83nb-nc7l<@6^P0s~j)NzCHaOs#sJ!|#6fN`Kf>>mN(*mwui2-esFr zz73<$>uQtu9T$$J&e*y3(aY6uCtuvKNQP67@7m!#D=mXBTc>GA`9C}0S5qPV^~l6I zmyi7`{M7jL!R8emN<2D-QPVs%&sSHj{nswR(c)bn(itfeCTYLWf60ZbVQ;j1-FAo+ zypvqRE5fzuUwNF-%Fs{yH|S`6y~!BArTD2`*MjWC*|!aaPyN~&^m1n38i!El-9f?DdfSyL(x}E7w-G8GT3CEsOZx-pQR?1vlmTM|9y~e!a~z1|FfP) zyr(R*XI**6bn`OpqGvqfg)dgQU!HI1bl`YIskfc5$JT2%Z}9#W-s^NuXYqzPojlVl z&GYW>d--mLQPb5W7h01#=f1Xf|C6%&-%-x$Kl=YKMR3eg)7mWhGL*SSIsf}V@eXeH z{^fHM&uMY}>szzZw6(%3G3LqJBH86Bnu`}Zx9nTq@p%?^^!3jRW@Y;Akzsak6MWXh zHo^4u?_W!-u9`UgzZ2)X#Xsq$*t&yqET45>*ezI7^=SUN_!493)rqa2ui3u3TvFF^ zruM>z-+K;hOgwVrXL8F;zr7o@*5utR_--8+>y&hvv#6@jZ^xfKhb877VfJaw@>jc1 zes2AhhV%atgO^<@xeygKOOX58nfeRXPE4;w4_;Vau_rUun^SK(&$noW}p&iD~5 zcH`3wkL9^c9-N1dgx_DHo>eku*ETovfC}NSYagr-QciyIos%2Y(lQQC}wbqpD}Yy!NSU7&iON+`09|!gh^#_hy;C z)X$SwhAJQ0Ug=P>F%eQ=Qf#k`x6%C%*GT{2czg0b-_KLIKRv3u{A+pHF$0|= z@0L$;uyRameXC#DmTnP0Cp;^@S1b0A)}g$lKpXS({<6z|E38wVXKXOrbH#$Nr%#TD z?B-KpE#1+>T${b({A;&-!|NY@+_0}NJX#+nRTBSY_gVjCGcLX?F*f;EEAV~lcX64} zFE3<;9y{+;>$$vsp_-KWX6Hri9qc#t`IC)mkKa6DTGtb!>*k_+D!Oy>#+i|VmFm@+ zRYni^b8WX*y$S1H^da$>yt<^2e3_#DACXP3Ka>qnTXGB-V0V%$nG{R_&9k^hSR*IS;@Q2qb6@ZofG?g zbGJaj$tf#Ww=1r;`!`K8F@N=Gmsu{iJ8MoX46T^k^VmsPyX8j9XW!mOg7<@D{v-ud zm3GvILhpR7o^y@u87^R1@Dq$wPFJ9nqI z>|VChE0$+i?=E_HP-XhFvwvT&{yurP|JfWVt_L-{dafzje+)i#PBP4%@!sE+hqr~b z-|m0)t>38=(>}%LB zdfs%C?lw8e(rt0uVvb*wo;odZn`?UZ`IKM3Uu!I!o|PFLJYP60%Rb@t=UFCGr}7K! zwRbQ!@4j+RsZeXJ!;={w@(y=S;lG;U>)^3qhDP?X$_o9O51XGF*~#DbOWPXTbmC^n z*12uWf^!|(n~oMZizwU?@5*oe8J#riz@sY-@7jYclwUH>Z*g>suHApZZjR*4nVRZX z+)^_5*D1`pc+G3_ii0PP_^o{PMSISiAlW-n3$Cdynto>MoKpsOJ{bL1s4_kBN?Tb* z-C^18zh&M`T><+-Gu+lpn0aiIiDoWSwy26u4*r=NxuYRlJwD~5LdKen zZ7vy8dBfv#1P|Cg`1?3*_008CS`Wn52QHp=j3w-*=?B5NmYmZmzxz(J! zxTt7psiKRV>Fj`6*PZOY=)H9N`cxvXF<_=b(IoCPuZwHeZa(_VAlTN~WzM9tOIuSU z{vGT3el#wxt45Dw|3`~GjKRD16!<(?8<#%sh|ackvK7DPDz1*JKA}1D_w#dG0w#A& zx|Dxt#YN*z*Xt&Ui+wjv%Xe*&UdVdDGvIq(^{!PF^Lysy>+vu868P`gyn8zmt9~E6 z`>XK8R}t=O-v2nR^UvnF?a=?#{B2rAF_-fCLgBReoU$&7%^kPqzV7>)f0X^I%ryZH z>+=FU3-3qW)SWqJ&Z_WlEWDnJ)ZRV$C9C!A&vL#Ti)HB&S2SXGCVaoG`D9Y}mA%>T zTt3uu**y`=+k2VWq`}Kba?+;{YR7xp*{>H0#M%9N_P?gsPBJ%P)*V4 zn(x=7SCzY58`Od>&ysHcaV1<-HtfOHMW6O=c+V!_m;Yn)a#ODN6-vj?Y~P#wPUO-7 zQ}fiNyCh!ptIs1opp$Rz1sSsoYC21L?3q^l`g&Y>eN%!!SM}%HENd3LEL-*`a)+pfSMaJ= zvfnLTi{5&p(zsBe#Fy}-@QlxLxPsc?M{QNcvNE)ZF6rUT`RS@0LzulYh(+cHB@2z&9<+Odj zL-cNV=&vItO>fJ$oSg8-Yu1%TUSHR7yO-uVncQ9NeN9W*t0OG+;S}bNA)NWsTei=2 zYRO&El^Xx(7a!|i7VF1p)su{$ZJ1#2WRupR*Qtv(C4IiVid7+S@nt3FlZ-NNjxDoJ z6rY>ZtE6PL?7D*4?p1~F+GKcE=O-=EY2vjGvX|peUiW6L_^xaLo?oZuP2{p-x+@8Y%f^Vt%zQq+WhKPpeVRN*jtjkfyl7j;@5#hHtmf5bVgWzzn-~l3oDLQd9Zn(%NF7EwV$%HunK?wy`e8?KEAxMBEw;ORqQ@dv7U>i8HFaiGw!!=CPvjne0kZUZB+5+ z%(O#iZrMtFpS42Y?jOtcR_XGph3n$~%oR!%Eopn3pn68sC;d@I`O$mI>)t+Hbat6g z^6UDk2K@T}r~HqcC=;;h{-w61X5W5GNEV&@bhNx#>Bp&Mq5O_vt}2%U7MfgK8+1*7 zXHN2o#^W>3hPQ1qo|KRzHE&Isc(c*AZrzMx=JviHpBl{GBzdqgo12-4ELt^ZcJ{6P z+h0vS*CRduqEPuMuIK+6n2ud8U#M_w$$_0B9Q!Loy^I%$y|ieK+1zp<{_~;^*NDJL z`h`Y1$^v$lMk1SLEH}|V>Ga;t?!9<-q7IXG^sUf`=UXO*ZasF@H*3XH|DQeA()!k1 zd6#7RGWE|r>CJ)Nx;*6N*+kEn4=ykSL3nevM z6ApS`d9M|j!x`8kF5)*kq^iZ|=dI7e9e$UZcsfMv1vmA{=j@;LChXv`>2b?C_E`Sz z>Ao?ea+WBYs&w$xxeUunY;GE_{}8ru`>gYC?nE43_eEO&JzL)Vf~rlC(dNImvBop= z7e1``WGNgN@sa;W`NF*>3yiaF3#IvAEKJN%<~q%D?`pdCk$VXzpPbqd?jhK^ZngII zi^e4{?4EzRA@kLF|AY1Ck2$M!J-+?JvpDQPMN`fGjZc4Vb-Ay`l>R~fcV@Gt#!^Ys zKc{{!n4o9(dH7B|-m&Z>Q@lh)$#&f$D{ z{fe(&Sf{PC&RJIElN%s!FSO%#U#i*3g*p3f*1lf5`;zkKO?OwUYt5?h)qD6tBHqLO z?Z@9&HW$dAi{oD2T@jpXXI6ReGJlA!*9n1~e|hn-BD)2jM|Lx-Mt^eLbMmcCS#rn2 z?|iqdPH_1!T@#w&?vz-ZpS<^*$vZoqpZ2_e<`(W26;!$(zSuORR^q?bg-A{HCvq{J zCjX|%?GRqjbxhUZ!EvE0(-W!$->fRz*}bPs^LKI3uQx$Et@&(yi~k)tq~7}7I)-ry zzuTT|FMn#?ThwwkfBv_nC2I=%?>{w6VVfzCR=i$h@lxCNRqoTH|8@TUtG3;`u9?xO zo4G5qX!2UAZ8K`-O_~2hqAs&*`+iTih^RT|U8gZjT4n9LUt?GBty2fCiXAih#@@1b zmP2;#{`%i#8*zgey)FBxuj=Q z%+%CY_a9%BJ}_)K)SAQ+B_DNX-CUnPpZG646sw&7-pOFy{)1bpKBpZJIXz8?&FSGS zajEU{vWt%`+7#sebbj@OSAEkf%lI=drxsp2`hLNWACt3n_}499HMHA3A!PEk!~~hY zlXm&}H5?XQ=`D8Z#N8dP$2@mUno;v?d+aoM?RncQmhN)(57Bj%?a=l+sr_TC;qs6d z;r1KXY6gE}y*5K)@_n--ivqp>7C7A%;XfSR=D)>IS7Diq+YN>UT}Qe28P0;e8M|cy zD{U3cf0%5k37sk4DiG9M^+_`Dy_VCQ>RVT9>?4-`Iq36Z!UONDn=cMeSi;uLao+Kp z#kBhc+cvAL)M`qSOkR~~p5^yox_epYEm`hYXuc@&nsiqpd%u#t-NovOHV@l40^fT&`JA1te@y6qFLTpUludcdBpB?)2jZC2Sei&zaAs)*M@TX62IJiSuvI zn6+=&k2I$WiMFM|HWIe(a6p?5=6qZSeC&=|h&! ziEmgHX1$v1T3G#mX5xGEva%JEHIx4_2?{pj;m|um1k=iPm2ahL~H!$zf7}G9$4?T@kuh7f-;?}pDex)b%-Zsxt5%HKYUAoUI>x*a5w5SrR z*6$rJzlgjD|LO8t!{DAw&}F7sR-&6Py=CtI>GXMPL7JqB;gmmHmbst&x!r>0QSz|^ zVO93ew|w*~$`KK`wv)&3iCdo7{Z$Hi-^|4rlYW(@E?OBZ^709*hw?db8P&!QlI^1V zTejTa#i4P$__|t(XI+r}36|)?-|VN`zn}Qr-f?Qy&0FQ6J(gaQ;aT!*zFE>+WTXzb zzj`?(j(ekHddB<@_McuA?~&g6^OoOQ9lnK`&!)6+O0K>?g(XUP(v{a{=MwW>1(IjW zS_W^_yy7ILdVD$G#Ij&ZH(TXXLGwDbG!8Db_y5hhFl3M4|F_2^qFud%mj5{Lu5(2J z--;SWk7Y9Z|5i><-{hChq^~($ea&-IRUgL7+H=<3?0Y@y^2b0Q-;h~x<)#~W{!RYC z`^Wnle~k*aW!aO-f3lh7+wax9V@`hE{%GQ{cMkSbpX?U*ae03A{q|3%P9zEJf3Lo^ z+$3UciekAr2hW7XOv_ZcYF{;f^EcS@>liE7f*)@c*Kb)7d?kQk>6!|bWecUV(~sR1 zHr30q-`Y@c!wzg3g+L(@K+VYwEQZ1r*F z4}0dH=JPOIxlr4haa)l@&4hK?LUJ3dj;!ZRllGF$R6WL!k-Am9=lbKWrACZX|Aha# zmlkvTk&5vRzGlul`9C#zq=Pt*Pp$4Rk$Y6i`M6KkU~$^*<4oL(F@M63yPGD-g%u}s}_Cp4C|winC~|qtlx6PzIiN* zi&uY`7=M4dF2{nU@81}{b8re&vbVZzHAzh`nQcJ8%h zfey^lr-H>)+z+oxJI}gfLGuOMllzZU-+21sNV<>ZeZy^it_6bKg51k1?oOR3HA(cz zJcsk|q7UXyG}*@59lLLj&$_z$#9V&uQ!{uD-K##h$Cgdt!DNZQZ$^|r5hSocZLcT>J)$JcUU+pi|eXFT9Eo0WVjl|9jT*SB_$ z%#4)QnA5NBCQVfqyU;Ybep$z7-$|B|OJyG}QFgk%{E@u*U-P|e#xqt3oS(E}+F`?K zi=WD{JpCXLb3y)Z`|<1F-lS;G5o3AQDa6aQO>=G@-`fhM*az0FZ7!PoPns%Tij}y} z8Oh>w_t}OSlQpyilh%nDcl#{au8~k`_}~7IAOfOb2;nH``NGu9YEm6?WPpwGK zNz8?xpa43vBsn#&L_aaNAhoDCF)sxo1wLj1a>NPfkOc?}BA8fQl3J8moULDwQ(CN_ zoS&PUNaXPn`f2&4MetK4^ovu=QuFllGV@aPlk;=(^Yn{Tb2A~VoYdlC{nWzJ#2o$f zqSVBa)FOS*X(_JyZu;)}p8DR9b0hTq^+ESOf=)~c)sN7R)K4l(OwLX%0lOH=hPgR8 zGc!4}D7iFOzceo;wWv5bzbF;rRj_KzLsqi%aUZi%paw+lwE}(t4pj@k9Xaqk_CKmbPTN6++hovOg)?Gs*BT%IQ-m7b* zU~Xt&zy-am(^vudR2Op#b916kb(x+TGCOwrI>jBL`f*L7(^Ye2|@wu(qb|Gn<+Q{YY8!WSvx%l(B@WOu#5GO*rSd+hff`1 zT*1A$$w^?IjYB3o`+{@v+A$4Q0^%HZc$uCZeEOWdX<-=00@WjIuUbz3p01p#o-GmZ zBtCJ&>d*Uw^8|KqUlN(Xn>k6gV+%){rDX-vL4oX;I9`b$?xvDY^@p$2=dFA2>cN7< zhd-`=tDk@A|A}Y|Cs~{StC^m?c+=Hzpz)P~0n58D^Ov$ssGk|!-mq|8-~XARZV?s^ zYnRN;kx_8S6X?INxxRIw9#;TAM+A4*hE1$d(H1)#{`EP}Iq*M|rLv;__Jdl@wM)_z zPXCM#{%gH5m9f<6MWvNzw5s?3)81Va}@q>Fp!@h{*bRap-$!YA;te|ofuAJ^A@+-v#?BLTyeX8 zwE)wnT?*E}+FK{`6gFGfx=e8UXF9cBNy#Bj{YAa;C!U=izZxfSr^sil*%-?*oU zza_`xpS+Ocw#6SDPNa#*bKLB>#H_eGpiW`Qyj#qQU$4k>tX%%l!Nc}!{R_(=|JRKZ zs&4VOT)AASuw>plX2pJ=_l*|_!}p@I#z%A|DMH0Mh5)) z@6wqZ@))1={QSwv(x`N(#_oUg!l~Lae1%Sb{wg=@dHFvrTjSGi#>NVVH3iR?C59z6 zmYw{1@aVozKa*7@-so*v>DqYst>e~}NjBBqNh?rNPy)yFem-gd74yL;kP%RM3nm(zsSWtMeEDY^WAUUcTdReje8yPS0! z<{wgdJLOAW->U4wLv@V`q9PO5_L)u9s%t)c{9WQ+tESWQ^Zf18XB@cqMYg??QF&hK zyWa-0?wm|5DxBur-rM`(UdP&x&m$z?$d}g&ZoOi@XA93tm)!anI<_}W&IP=he3$KH z^x@W)JwI*YUWC-BexFFS8f$`#A*&WN%P%apBc-z^i^k<|IVT`lmR{f3wcYy- zbene_%Z@wQ^Fn3&_S^g!Rq5aIY+ru8x~1{;{j-Uy{PL~@?q50UgWe6DlZ&eV*S&U^ zwHNz%uyuP#K-tEEP^IF^hR~^3Lmi54@14W&`tBzGt^V6HZ->m_ zdz)s?{;nPSd*AVV=E9Gxw|I)KZogE+@#oU6MD;y}52MbhzhTtX;FwsdyXH!&@tu?A zJF+x1+$|=qFWXc(%WC(&Q+L%~_2@oXBC@*cZ<)2~zinFg3M#g~UmFo_CbhDo=-0Qe z6}gKlgMPgX_Z3VP^jR(Ay1n@6(V130N9Hul>uG-VP-;i*?e`ZOJQAGQzgmAgY$x%ANoblIb=13aiy z^Xa5dHJC7YhsK*Z&H*)5g&oVh8%p16KU14063@Et(zJr8r{TA!Oyo*B#ryj=$CTjS z^J`^dr!7sCPnlJ*;bZ5tM{yT+^Ez1Rau>I^Uo7jb-+%AY(Z0{-%KT3b@SFTPrh6gP zyHw^zkn1tk65DBMN0JiEGZvfuX4Jp9Nn*>ZV<9uu=PisXzW4iY%^y~m$=gpAznSro zPfqYc@%7_g`L@AV1a7;otIV}9m;L#rb!ULo(@gnQ=WK7>3BNc~$#92O=-cIAl(L-P zgglEoAUvn{-VDu}d5RN4|CLAeh^E~yzBQx!-_$lg|KDquONdm2oRRKupLzUY)f=8a zOJ&?175M}j2Ccc6AC=$n#rMvV*!$dD|9;uI@+I#QSyA`%M_jp|V?zW{nfc`J{cQV zvS*!t9`U@VyyrugyRehvf);-!jVpa-GsJDDH_UHQx)<)oV{&cr9bqo`-t_v^ zzY{+b}(CCUbrf*T5Af+v_pKC1*GN`U7C3A#nO(3@TX~Y!ZRbQ;v#z&7fDN; zx%DD8c;jvHnwiOadm@-0Cw!@veCfYyndRTVFR~u4W!joGUHtLCS-tmy1(VnPjG4LO znOJ0q_e7>}03*X!jr;*EM%A7VQtbNPRjw_#M@`Y>MxV*wv_h889 z;4@3qOk%|ol+U?54s4bxQj-up)Ah2baoMTuJ{tMoOWZ&By)OEFxad#I(l3V({W3ry4G?x&6y>4^cQxChskqpJ#o~p(d?{q##+}JqaWFmC(V1i`J-X<3pdMx z(%N)a!DHv1v(?R6uqp7_;wRrGO*s2*Po%=jGh(wBM;;7(a?|wPDa%kZws-R7x7^!8 zy*~e*abaEQo^7(1n&Qu==W?>Fo#?i%PSoM>#J#^HL$)|SFn?sd`q_o{D>wmouG+|0<@Y1WzERXciZF8NmJ6jxWATrhdnr+CptYw85J zz9d%Xp9}I%nVK9X#I94>V!bYicgy3;F8B91SKIC4GBH^GtME~=(t*glYJtG5yS6-< z`sDJtIZ=TZ_xneEn5uQAf9@n<^4^)biBdhDzIqGmRTl%Szwvz{%qyL?Ckk}PNb3Rg(AHxj&G*lShe0l zS!s90nQ5O+-@f?K@#r=t%Nv`V%a4}0AMNQ@dvzuGyXOU8<>b5m=2zW(g`UaISF3lc zX;6Q+r$zF7Q?zHohkMK4`EQDq7WLid`o z^*m49pnu@qgNA@bA%VH3>=_H*NwgnnUv%F=FW=<g${H(t~wssEM=W* zqEaV6TVSuN{d}3auL|?R{IqYJeVw}{^>eh+&8L4qaK6h@cH6&XVx80c-><$MJr?GX z=k{->@98<#4qvYQ$$EKV^3weCWt|2GVw{|3zjmI@S)hFT{>_J7)9Twan!1AvvrZLg zuIB%r_G#y}xoWQOOngI%KVN@zDs0XIza7TkSGxyXm@aU6`7CF7udRy; z6%W65taNh!rzBm@t2y<*k8D{~ciLkmKgV(At|jj)jde=bnm6#xR9Z1LV_%+CWb~!U zr(|#1yY;g^TPIMLQK@bJB3bAB_ny4KnLBS-wp{+m_wkQ^FFM38C|TnGw{-^(2DcM>h=9`=jT_(W$tPGw)CUt zzi{47;z{}^OCk++PEDQsS3B+Ny<6{A?Ybo@@JzJ){;Y~4-zr)eUKl;vo#6PO&Em7d z)yy2-$7;19|F=KMx9syh7WgLozlOkLUPA@9tSgCOSMR^lsQ6pS`t22eOnuGFY05W) z6W^?fdpD7%z+%e{fzvarcPW0E;#s{iEa6>5Q1JZ1lm6}d7Dzu#yL>~h*ZYR#qfa~I zwi+GiUSBn5o%!DtUyLfE{e#2y>@d}Hz4pm?&b`JM?a3dJY_2!cf@1g+<$X(lMKpuoeQtcmO3`)er@g}7Ozif{w{Zd z?mzK4@bd3h-K?BsleEBWJxk5A_0wLg_`gAp%jRyiGKch)cFmicHp=B!ZOx#pwD z28Z7}I?KOLn`)ZZlky-apzm<*YnGCvi{@v(^L@UuC9`66l+gaNfbQo#epibF+aG6M zwzK~oQFg(xNkON!i%HjN*SFnqcU?G?R<-W_^iD6LFn{qm)z~#h!b6^IE&h8Uy=tP# z{N((}R|_wOF0vQRxUwmvK2KEBAw^4ycV4fk*`&+9F;eeU7`?+}c7CoC*6Loh_oa01 zJ+bwzQvF}|`Ayu@el#(}t*g)^xZ~5W#J97X1LnIwuRW$>S8?_8E|;t-v#g)#*4Ok) z_^V^0bj$+mUMJqZwngad!D$nogoo>|v_ESZx!~DD)2^ek5zALCxZ%rm^-40^fmJqM zI_quy?*C1To-fqkcs}vQtCy{epZTW$pJLX(w7dG$vAK=UR(hQL=&eBKpr&zbqoO#Vpw z#Sr-~+D6TJl24bto7JIX{`%K`!P+xr$urc2b3K~9?#0wEc>Teuddh?CXQ#!TjN=V| zVg2%dX-Rh7fol@YVJ6bs1UKF~Q5o?t^oZ@Yo3~Rv)MH$P?CsONSJum(bUbD9X`(!z z?#Y<=`ZL_CS?;gM$qHgx8t2ifdhUy!*cTBURjxMSRpJR6-{OL8{<)<*>|~vwd6K*Q zu3cq`mmL;?6?RttSR-z12=Ut(+i`YzO7PpC zc|TMvr)XRhTbNUN-Z!B^RR7-2l?zwae}B1nxxiFD@$0)a{av3+u4Z~x-ovNMc0BK) z`MEb?A3r_Zo9?6^+JLd^a^bsGuREn78S(>WrHQ3yq&{ zo!`RS_@StQ=lrRKyLAqS`r7^1S~_u=t!hNow5T=vkIXOn_+5Wlcm9Xf_L~JBURZd@ zpk0)uU*q~`m!FIOhBBHo`Xx_)&b8j!DdDAko$$+a+eC%ejz4OToqD;^e=DcLP7^T! zpL^WrW~5&4oEv^6YCBg)><#7}?O6gfAD@1H8y2$uhmF|xAJGfno!<8=-L!9d(-S72 zsavP{+}iS?ugdi79bfC)uG(w$7*2YnvBYf)bKdohaW-S|vGU#3xO4o|Z?K?b~`(gLzu{9_9YKGhVaQTC?mmnD$}Is!j2yPQ+X9TDE`Iu@WB1 zM@Kvk+AaR_LPCOJGt26gf$u|Y4zk*aN_Et=q!-z3Ff_SizvHF4*so=S+w?Eb6l=Q^uO-)_j|)q&#sfcvd90x|KKlGxsWD)KRZ-mG4d`<}VKLo>pnk6LsaDve0vhfN~aPuD$v% zKd#_!e|!0Bb=_}A`@+4t+b1-BDX6XSW0(4Uqvv$o%aR$3&bKU6^b%lRyGU_Stogfb z;YXgoFwU#lwfdkje|VXXLDiGClX8ViIMW_B-SRig-jQs-uG5F|lF8X?Dzd~&Or^Ekb^3vZv{>{JJ z#a*Kzi0M++O#PV$TP84H(p8GPHh*{Y(U+GxF5UhXnN;+cmr3dUFD6ElgIxO^o%BTQ zo^BMLsyFv(x$VZTa|>E~%}R=LoD(=Tr%n+Pbz)#O*nMle!^@llQszDhg1((U`AY0h ztlR!>@%01Re&>?ko{{$Uc)s()j!P*qQ~!D!F}EFmo@SuocqB@`<4_H=_LLPWch-x& z^`5)w(A2K%4-el5GJjUhFnS*=vM@|%rMyYfx#Je~_XJG5=YCk@BoOGo_oMFq?z;a< zo?P=+|9X`s^w9k6FLkZ!Ark$ZKc=#@Kic_qiE5r^R^G`08UVW-DhGXKkV;7<>Y76ZR4{E&2apg{q>|@R?Z(goACNP7u zciLCxNm&wSGWO5Xwe_ESSWWNXa>KLklRq3T-rJe?!+C+|$GpgGEpAzip>B-ud$P1m}IfP2NstIye&2Le?Gs|M5rkt8Kw^W~r{-v-`M0j(sCj3e%D{9}pvv%Ig(5bb13}iM|vWtBFa(d!hZ4al6rE5CoGdiC>#gqTBD%x`0 zR#^qNtF3l#GLQG{U-<6Vhwle`9-f*0^u^H|3o17^eQWx1Fyy5;YgzFH=Rn5j*|IA+ z*ZT47^w_g^%Fb(^AG>GH>FWM@_>Jig_u%Ec4PSQ$^H{xUr#scdz7a#SIZg7Hbk)W-cs#_WaAEcg!)`w{`rg zFGO<6dOykhyg0u#Ns%em=U4u^qsJHQylI^6l9?P7dGGqi=khiB7Sfyci(od5r0&&tgc_SQe%A-c8U^jEdCjm}$&6IU-+y1ME9-pd^Sp2X~Z6W$uI zEx(LoOYn=AQ)9m>eswR^j5_@O$m1hzjk=;;M$-FOqtfq|Ei;{TPx6cUK8;OlPV&Yy zB~@td+vdM~_srJa6-(ALBp=i8%*hCRq}Q?_AZ|nFni#LGpBFzl!gcENx#(P%GaD;6 z6rNG~l;5cJl)YHhyzT6&ivrgsilql8yE@G}6O?9pdR z-S(783D&1V=Qn%Fv@}HNWdHy5$;2!6)9+c?ZpJd9(~sPZ*lWmkqQ=;2WAN-1T#Jmk zTh(8DHLHD=emuJGxK-Z*|6P^$r0oR`FeJ>87d(L zGpz2`%v$Vlcfyg}J%=OB3Vt0^vM-$>8oaH#GB@s%-AaY0Z}ax}7FK>@S9@yTD)U0V zK+QF-%wqQ!7WQLb_Wp14xPMi2$L#ik-pfKuEoZ!p72`ea|L0fVffq@SLU&5ktWOPg zngK+}fat)0BS{gPeiufl=YH?Ff6CnY$MaT=r;;b;eL0uf{-af_Q?vTT z*)rkFAI-0SE!}oX(k|_l--BmUM5Pj{EdEt&I@-_P>=?YErNkq(`uFxT`j10alx`%$I`s{>_c zz725KFRYcBaFn4>xgk`Z`GWcrKl2|mu2ttd8g5kW?$1%1e)8MP?P*j;>iQ}o=QoSmMW9i?Ght2M8UAO0A`o$U3FXb?0 z&z|(#=jPnx{ts(TA8stZ#O%zoI=n|^=^^6^5_E-v5*{ImYHgO`@4Ee zH=DH0%0S_*ANQ}*V^mOG@YKx4?oH3bi7TAkWVIP?Z7KcwCi3FBXZg#I%Vj@SSon%7 zZcArI(=M~M5eIi~|MzD~#K-r6+$Smnr(M+B*>JS|vXvb7{Esy*YyW&%(XW)f#q^q6 z*n7RS-0KYUJ3`NF^3yh4w#0;I|IwE-%#H=`e*VZ5 zN0;1G30)svw?2JNk=EWI-gF0fwXZs=j-D^&;_Xu(OrP^bh3m5Rokg;9vb>znPTBPG z)DL%!uSsm{8GD8GyEK#2#GM26?xcs_z9JoE62oJ=?P!(g#s4M~S!QZKo?-T3iP?jq zhE-lcTTP7C1iwDQSY*h%am98{O?HbvE@>xOh0mwyawL3RdC>Y#Q$eD{qD=SHn%<qz)`*e0QC4Ih>?H1*mq8l?#=bcIN-=ZaP(%$Mq zg524)i9bbnuUiCeInN^}F>_CeB}azFiT4>rKb5A)e%e@&WxlLkuIPbhybyb!%(qvw zwS}G*vCZ=CeCqvHEv;^=%}F86gMTY#J4sZw?VskiR(j{Fi|g$89H+$E)*7#M5S;Qs zZ2KBk_GLFT9gpYki;_)R9__Md-($@wH`edHkuz&a>_n643nU|re{MauKWkm(qL@PN zOCADwaUYtMuV4BR{AG)C&=Z}NIbm(5&z;IPJJoSrEpq+Dk+=CI!OS!NzOotK zveb6#P(Su-k;npx#DeLsts`v86VHoRJ$XH8Sz+h&dnr0$X`fY6PQ3L|ce6NAV4dd6 zzPNaS1;bT6!&$Q`au=*m$k1k3^6#lJ|El|Sxg70bT14N0|B=ETay* zE&MOuH+f?c`0BAf<<8S`>+LCmZ0@f zhy_}pqsrk6vNw9qW{EJ@7COm@sm&q-C#wbTQ-Jh&t^H%!4C&mt`|BiM20 zMtF`pFGwxQ%uhi*a2)IMsnpE$j1tJ=5J!C{@QqTg`fiZBc92#{1?mSu)@ta7gVty0 zN1?7GdH&Ys{_&I#%2npre+ZR;0wbH4U8-x%1jNw z=ei>;0s6ig7;8KEEaP9WSBOp#X9nCfH1f`Yk;zFuB_ zNlI#(f;sfYBk;;Kc$}cDpD~BUkbMXn^dgm+p%F2+x2-KKSC4q8*SdQ*Yx#1nl$mNu&43?1%sdE+b);O3gP;l^a zb!9xkSn>1O1BZo6rxr2J-hI=`amm@c2bvfbG%)BpT)fM8;3VsV2f|Mt3O#w~ypYwy z(z1H@ji}o@7$ufS{P%jq>|xOqo1=SHkwLWBTzbP}Z+`D$_J(DXm+Ia)JDXSG;RA*X zKUNBC=bo}%)9-zTu&IQsRd zNW;VY**y*7lNHoEn#~zlwmBt+msSNb@2~jzKk>Ew?9;ofEmq93{&)4?`>DV3A3y8c z#&_@k)Q3-Aym`k~#<;?w@qpfh|2|h)|DT@2C6V&_-H-W;x$>UzZJQ<}kj-w;AbR5L zv4elt?^wHf&02AZC26nIGMP6Rl^3x7mt}W$`2X@r>fe9g4z63jX2r@?XaB@U|Ng#U z)=u3czNc?X@;vx4_pdo~{pZt4J8x7m@>t%muxQZl)PKK!f6sqsAGV~IESp**m@O(R z7@z6sJ-er&-~OVtf?=OSgDwlpH>QTYaWb1XJI=Wi=f$9}{aGyG>64~U*Y`15GQJT@ zF#o)NQ9ZjwJX7Dh{|fx}4R?R0zMkW--C-{GH6B@>J3vT zKYtofRPdSkM}@_`fAO8u-s$NjblkpgZ=xUm@_tV0@1oxa67)Byo;tK<^3s46u~Eqt zEBE{SbCI-Jtesg^_#(qSqIQ?S?T7q|b26tdE7UdkX;~(*ZEmh**sF~}s@5mE(tCFV z9?HKEKG`-$u3A90|6_2Q+M|_E7f$3n6L8Lfe_3+am3K@>rxgo-eyQ~J>MD2knysJg zCg}J7u#j3;lK1W7q5F0TIk}8qnLDbiMUPr654B`nvw8b0gQ9Yk=TqKq39xXv4ATgE=o`5UOVZ_?yy&A zq0e>U+{~~bOUGM(&S`A$oY`l#Qs9qSXk57C?^#RU2=}FGb~bm!C>omVSay8DRPh;SQQp{}mv)E> z7949nyJ^!;ld~RvpJz{MnX+id5~m*#LT=Gf46}c6gibY4WS9X4O`% z49eWG`1?$TBCnYaXZ;m&*2Vu`>QcNvw9lJq!7NA32VI?o4cES8ADt;3)^w|Op5*NA zeG$>={6|#Lw16ff&Lz4++WL|x7B#NwYWNA**zPI7nf@Akg$BKJqe@`zj5k+(&29Tc24B{gX$ zo?H9m=I12-;5}swCAM>qCic{_M+R-{DEO6q?)bBJ7w;`SF#YAW>K2zRoE7{0lGnBN zXX?gw`+S=JhQ&QM-~Hp_89Fi#TiTwtRP9_gkzXwI)NY+665lS*{wKsZ>+{bk+l#|i z>OZNHVBK7nkl84`Ghs`JxaqBzUoH#%Sv)7{*}^Fm);As$RKMx(dha^X!tlY-(x0ly zJGC@tubaH-^n-^Nd)LPr7>nw6{8&CMVRz-0o}b~op#v8w|c4x8LpQzN^fZMH*as-R^a~Nx7CR_W_!OyNr#vH^f@AX z;(^r?x9=;?bL~I6vi7K0*zWC@q9&DGX{$VZBG#i`$*$0I!Ce@n7ZZp3b z^7ixM#(Fc=#2&3Tc6rm}+U#$ymKJ{WAuH5Hbzjxq-b=YJ4Nrfo(z93GTY7WHY=-#P zTz%UXr88R;ra1e|&o42L@e8p3Sbs(7h>t<{#`TN;?ojOLeYVEVfm+Uw{%v{R!aRO)ciMJ-xeSY<_=-)rVBRTJLZKb?S%>yar>z3!D zEcV*3jbLZn67M@nN^44V=Hy5%oP1sKSI}E2 z=l2zfH~u7=$plWFY7w^I=Y#jQEtUJ%t#do#81eWFZ>MMB)*<;Y) zzqI+*4>iT**L$p9M@KC>l=_Uds8#dozsH)FR#?tN_ex{LD%94CzxtA#|NPW~4VFIwth+p9V`64xoX@)W z=F9r;WfCE&@AgGct6gNjT1w?3*WO@$)q8R>4^5msc1UR`|1I^m<4=j?Tz7Z#M6SaH z-mBeH^>&u!ZAd?UkaL4U*wnQvbM^JbGB4>BIkO$p?E zW6++keosB?tk8|GQ>Rwc$S@SJtkJ%#XqxkI@$IJ@LI8!3dBwTJ}9<}>){9PGA z4Keee_YBK}>JC&0W~aE89}1kdUTID?v)Np$>Qkjl6Rkddp0c`pd+JTkVvH)N|hi-wJ;bnfqhWRuezx?+wQ1&OE3&dVcrytPl)O6Je3 z$}5L?zHa;y&Ke+|%XQH^bkXBD&)b`pcB-?f%kST}aMF5Rw+-tyO-X3)S3Z9Hko}7- zdWXz+@ySh2unrSci^{xpV(FqSuO>(TI}j87PuW0X$Yo)jM>a5vv=+CFmfq%Dn9{=}y*2ais*PBn>JhENw8h1b{Yne*^ zBX4`FD~ewOGgn{kUq5&EtZANdL5l+ov-c|rJoJt_Uv_(vPTAAAwN5{-sV6O{EX$IY z+$%hT&E{r)j^F*u7QjO$A@Rh+F+G>rq=4@0uCGRpN_Y z^uIaKq5VrPE9@QTjzVqQiic}+m$~2X_+R_|%#r+aCW@y&&PvHEw_AJJwB^vH+h+3n z+?TvP`%&3`CU@)W4Rl3(yh*|p;@PNg1X zYLJMk^4i1|cdhsX|JlA}r$Xk>N^V~(%eMYYkH>L~%Gx_DGxzQ`KlYRL%ZhEO`FxD; zl(uYJEO}Je??|8X;`~kX<_l!+X+FJ5E`-^;YVO<^;b%OHagp|PLzyJSJE@7AI^T!B_Ba;uSoHc2huu5Qy8aFP9=+B+ zbJ0hw`Ri+LyomYy=jsJpFQG;A`X64JdZK#L#t+_g8|}`{?*4K6`3%P-!Q%c^bB;TB zOU5{KOqigXd+mBz*%pa@>+6l{k5$ai*%R^R>b}j-wV$u8j}feXV>87eeb4&tpkJ-O zwpG5L@lWjT<&uXlLwD@*{jKG8IHK#m>=l|`D~>N{3iLeqsbE9e5rTRzP zjTZ0nn6>iBeb*3}#uZu3u-SS6~^`+#-d)uS+^G_{Ym{L%x9XI9tcZpCI z!;7=kmbAw_Go2`ZCbYO-_LLniP{o%3Ysy@C!g*XCGvJJ0A%n+(LlPpO_iUlxsLxu z-JB-=^K2T1Z~la+OR~vbRz2+YgN30pb{Ny#re?9Ih;w|sK{=($sOMOc91A*T-Ged?DN zf7Cq1ZY!%+_TH)6n%&C3Y_-9RMTIkt1nkxM<~TX#YS7iEGtQLEbm_P&E^fO=llzyk zV!?@w#b5S@&scKqGWWz(m&teR%+tP1x;>A5EnBp&RsPa-24UsP>m;-dCxraA>z9+g z|2=BL0gk5BiFS8yyG-GWF@5pTI`pSb)M>$OcOEHBTGD*>T+XVq?;~Q`-iqyE_YgHZ z^lQ?O6%|f(M|nSl?$^A}J@aA0r43Q~jsG7sFS#GxT7I7SdxBgJ`p^xaR0 zb159HbY<~%@|gZkcgz7C%JlO;W}W`{ z>1E*OoM6^~Es-ldmRA`al#@E#-o$_VN&b;4yP~C{{1Thpma07J$;o8ib@1!iAM7O; zO#*j>{IznM*2Jy$GT>s?{Ie%Ql@)LAobjyNFsOKr`Tr%{ZI{Hn?g&)YFMG7o^5N0)-aa-}g-6W119FbnoEOsFhqo z>32K??EaU9oTyRa{TMyx+s7!ylR|%47b-d{w?*olwfGuuwd_TX|Ha(f%v%c8x18Kl zEj-cY#ih5Kx4zap^w%zI_4i*_UU2fQd$adcTIQT}LftA>`6;To>1kV?Co;Xhp};cd zzNyol*)d}KHwvuHaQvHcfZnf+^ zu&^w$*w(LmS)NX@LX5g=(I!3D^1NiP{7J_SKT^z5o-efDMQP&A`O!_udcOC3%&XQu zHh0pC)n0PT;;iZKzq4O_cBs{@j9L21JZ++n#`{}_qTdr1bM(j0#xM|6rNe3-0=CXy(VVd|Lnej~oJBc)+UYHQr>aL2fHYSZ(!<;D9gmoya@V7EJ@@+B+INqy3{cJ-@bUtaIu zzF6_er$>qJ+b(&_T7|0>F8o)-ebCqChGOP|a|&lH{lxbj|F+}I+Ki|D8{I-$YlLiU zrp(*6Sw%r?t4m77^SV{4lZ)?5*tpM|9k}{t+Jw`J8{aLFL?DD$M-C=O@b!#9n*H=Qw5EdKKoao#&|H^Xa_CV)MyWdu>^A4pP>N}LR zQDjba{`07krwhxUCVX{izqZ}4vOZt-=*BF6qrY|;^LuMvU*~$wDlMF0vOK}2_qRrv zize?<&*bHAmMQ)1X4$r1(BS2REQ|H-*Va|d;8I?)YJcdQqb#ncbIyvaIeF;%!PXz8 z^@8y)qx7@6>sIdCzcIgiMM35q?fr`lEUfaACp_|%6cSx(o9lW}IrAqc`^?2HrC&I= z9=@agH`t?H?v74)T7D*5P*!OA6dV2}9zHu%ck5?-3fpGndDH!Xdyad@r+v3JUb$0w znvcJK>-3zN+a}!Kn4H!eX7~B+7_6}HzQ3jIn*WKI;7N~`EHdD43*dIqjZb1JpWQF&{MF*N(y8mWY~|z*@Kt@t zlQxwr%-r|2KHT`9;&!gZNgHGj>mG|bZ7{#_%^dwLo7qeJD{^#pH_zES>*Uf2#?u}P zi$|aSZF*qeqG0`b$9BCtv+#J1g=m}Bne>lxW{HO3VUMmGmwP_`wos?ea8s|IxwpK*IcS>>mG)c{W!uMe%9vl9R`mIef8`3s@QFSD0sN#*?UMs3reVrNiq@ z`Ex(c$OoE#g4%_qhJXFa;lDSxeA%(~qtWuOd7jVcTzPZ-SGzjRuLVy#bBe_kHv2omfefHJAe1dr^gn(vN^q~w$oK3=j>&bJq9g5-x*(SHtl?na{IC0 zy1ngoUA>p@SJ<9;a{R7E$id$ZlAnFq8x2ac7Dkk3T&x})c zFfPmERQ&mD#+6D1-?=r{w{KsW;n(*3`J5Lbp2q9)a?a?=&#mz2R%;EO`$zM1Vn)mB zzkl=gUe~%%@lQzHb#dL2({Hp2n{3~v#kI%q&Dz58$%6O2MZ_H4hP};83{?Zy8+<-} zv-ffulk164liG)C=9he#edE}v6H&`&N2SfYw)Okk_sf4J%zwXP`I)^jk2mwLW!W3j z^hV61;D+O&LXLzhGYt2z=ua8t8TT#tFc`C;2JnFx9`cc-}W=#u>I2Q{p*pr`^&mX2|q$ujxbwB>zbq< zIkV{E8TQNP4j-wSHak;A!>?px-{(dt;X|z#+@s$pTHC+QKAUf!GudrYXyxuL$9^R1 zZueRsZ*tQAfN}fVdwbazne?n)_;_DulNM8$x@gu-*_6CrS7+S%SUpX1Z&YubfSkeW z=JUS6U*Fpti|YuxR(1ZP@2bKp7orPW-hK&XpWEjXW53wU%kubkiF4g6oS3dFdmQ#r zoM!r1a%Ew=&E3_yvqhSioc_w*xXhGw$69Xp%I$pjr*&TvINc_e{Idw~)BYVY zAL@6yt(!Riebw_|aqe*LUqU=Z*CT%4JYEyg-Z8u7$G5wQ(b1*?_BwZiJ&colH1(fV z{mo^X%FU? zjr-g+y-lur+qey1w@SWw^{Uw8SpOSAz9R?DEZulzXTULbtvYu`|9?swoIV#lI+`?3 z?%nb!q1{b6-3iG{Sys*EjCeVBW7F3zPgXHQ-wc;~q2`B=)&FIZ&3vL9`TXPGxelBE zMFzW_pE*_YQ}dlaojE#lBB$4^>j&4E{XKt z-7CZ?I!`IP^pnAYnhg>k+g}~e+Wh7+*UuyCC#7<^-`)1`?e4#ci`HX>U5t099g#M!?R!=%V{-YKjftAljTB*l?}ZXK zT=SBp1JpDpP481*VZFtrd_p|y7T>iWG;h?cxw2bs@^kyer_bpW$1jh#T{Lt3nYUUU z8|*sIUpAW_c`wxbU(KZl*Ke`=&OLhk$I3M}u5znav2B|byGG*v{elU-2MlN4yrk7y z_u%>JKW7WC_+@KuQ;eyfz;dc%^?^g-|EA=xncO}l=CD8G{TDY9{`T+QJlFJ=XN>fW zrl;rqC!C!5_EhVxR|#*-xf>@e3jOo)vexC3{q}qNHYtQlpIW65wBpf;gk@Wg{hr2b z#IUzqF{Qj@$KPh*{R!?I7Qed|ZoeTDoM^J=Ubf=`j$gLb zOxbi=DPr-H(p@pplQTjYQ+~(3*IsbefT3%5=DB%|p4V@`nwc7)^#0I;WnmeqbwyJ} z=S4UF;tMjE81VRHYWEEJ0I9FX>LNT}q-)jH9DEV?xhGq)c+E3*!AOUg_M;yYZ}us= zUd`Tf%4CwCY1QhiODwe)=QdwE?X>=h%U$Kg77I#Nne(bomsnUR{P$*u!u0y|2QAXk z-F56AcWn64p73|t%%z_9ID<+rPnf6rKifHbwJT7n z;QFQwEXMJdp56PDdPRGWJ)i2H*plT@x1{Sr8nXO@ zmAzXPv!_LR|1I{|yGc)I@wO$A9o3&6=6!EoQ^372abqicxANbPOflBq$3)Lh?b-A4 zfY+3V_dcGyclmhcjGA3@wugFN{j6+PX&tZp@#w>vwL4BtxVPi|Dz>?~yYed?*?0Er z>wCU_s)={L@oArU&Vx&i{(aeW(*8>M>{CJKb@nN7=q!Hr?rGk>2a+3Y_bKks(coFY z@nK!zHTw%+K1g*X@#-4}89v)}=|zgvj1Lvv`8{_`-fKTMTzK(_%Kx{%4?0?sot&-e z6szL?W%ueXriR~ee{?BDD)-{$$cWEf%{51lygO~s`*HT+$hn(Wx4&4D zAX#kYe7FDT^}AEHJ+@sj>+gld%+GT?yrhD2wIuUzN6ZrQ|Fd5`>A6SE)0y#S-W_=; zwJPkJOnJ?>c+#yqE*ea+zA9qeEJ+{t8XanUEoB$H{`JnETC88B%>H)2 z(>@uSvR6ETnK$1m}U=bO`x97;HT zZ^9M>*K_(Z6TDu$U;MG~ag^daKaHGj_noa;H;!MkPI|hBO-SnMtRm0iXJ9A{t#=Z&s$8UMVA|JHK z6K%Pt5ooC&Y#|zC$sK5^B;MtoptXc32l5#jAuabbG%`b4?`a8Ml&J3nU+)>|;}z@| zs_pFS>xpf>ry;~}r1hR)5ts|fSnr8uA(a+V-(=X63(l6F8(J$4n03TOZmYQ6Wk9uMqcqt+B5r$?apg;$&`!qE( zQvgLUDmF7P#v+QUhBzK*T`35ggV&crNQ6#vV^Cz8TY%hP0zQ@tBxh+3BF)W=70gVG z6buy1O)VA73_&h3vjC9>3Km8d3Z|fSrcgdeJqVi`St^)-u(7d%sgZ$#iJ6&#iKT&p zi8*Lhu`&3dK2sw@1tUuf1q;v`R0FUsuy0LF4HZnxEWztlP0c~}8YqBhuzoXBXn26u z$09991vwv<@*sJGh~=n;M*5(1pkRnN!_CM@KetrD2q9o-#F0TOib1g3=x4@ox$ih{dfIrutZpg42&uKrCcc zurxYp&`PPhK5G^1qy~p;bdrN0!!}-hK2}- z8yXov(m&ckaAx|D{GecH1Yh}!yv!D5EjxUbt%UcrDnY)?)cICSC=x4=~4iz$h08w`w$yA=WhI&LxZ%AU=2NNVeIh-2X9=ht?S z$za*X@V~4W^DY0vf7V-lwLiwY_Uzg_|BMeGyLIiPUQgdz!&vHoC&}BpZ&K!#G1e~^M7iKu#M*r{zmnVKZ*sLUdS`)Km5GElY0-t zM|+lS`XAd5_$~b>5aIZYzfm;hzd(fJJN`oE8BhKTMEF0ve}wm1@E_*~&ourkZkTsU zo@u-5SN_JUSN{n_#Qx=P6y5UA_d)XElppN};(GoGSX};b|HvU8v*b_WP2v21xDS@? z``4OapH{DUW5UmPj%yo#aUXQLRxhw;_DqL*#fTHn^jXRee$!`ped}*)LhSGTAL4gE z)@La{^iiKh|K3Y|mfc1FxDT$2`KO?LW9sX8j%^SB@&7yjSyL(L@vDOe*xm^+Yge3a zPQA%!^JY%m|LA2KC-1ctc=F@?W&WBo|GRz99^_|LxFDL*v&A4g`H$uSrHy(kF8nV3 zRw1aPyX3_6`-Y#cz75uW|L1wK;@VGasc$mESDVOpPu>_%o>=Y~Gp|$T&@9`jZb#1V zyLnXQ?4Ea4^*4RX@)a)a@tIb9d*k1V=k+buLdu-$bWQ3Fk+eOz&Y;D%;wbB1cbPM%X6)bYYT#sh z_fo6xX5nYaW=_YxhckDuC-3-Bznk?xsg5iQQ%Vz_;e;P6apPt}XYsI(*mLW9(&J zkf?UOvx}=W@5hQ6Eb~`Qd#k%X)a`fo=0027)wWANJ&Ou)__xMC-k|d*hvWU*%cfr1 z;xb#k>ER@)zA~NKfY`b0oX776|9WmX{lcEZHzbuScid2z_Tzhvz3$G!Vym5ILU-Ox ze7t8zUdYDj*Q_Nbh`^3L_vnzq;4+WcFP_1ks+Rde$8GqbfEDR=)d;aQ-1-c?QQ zr#Fv@Ifm9%-A(Fu>u9rjdtc_>hs5Z4?5PHM0Xob7#y3^SeLH@#^vKUfN%1dJ{<1DN zdEs}CGge$D>2v$5p!+&ryxdE7eLC5d&0K$|ZokVTiH%>}PHXUnNZnO4?3w&}lfZPh z^J}K0R@XFfCZ)XFs`M(5J?gN2O_#$(riK4+tXRBH}Li`wvjx{^p zcs1L0p2H@_+^f2KJGP%QQqkIXvVD>S_utR$X+bO&LErvxyOdrE@$LLpsdhyn`3&ph z(le%0e$L-0U-e8dwCz2E#;Y@WJ&Ru1Rm*S~mo%J_8u zdv(EbcY^Vciu!XapJ-;e6!xyPe{J_d&Y?}oKYeQd*QArvwTqW@De)N#KRbVsr$JTx zRo_FdD$#_?>B@3X&xo|_J-lGg*Vb}O4i1mJ(1D5@< zT61{S#vc(*XQsP+VOBqQ-2GjJmEQEm#ZPt5)JwPR-W7G$a&q44EgOTftmc{iom%+F z>+GTF6x3yrA;#r_0agubinI>1ua= zO(E}zU2_!QSMkJ%-g3Jyu5t6dzmJ;t=B=ukTjxYfk)5RevMO@F;p@|rS>tv0)g1Eh zc-$SY^ygWmjN-D{OC27io-(UlGt2f)`6Z8an}TF-&3^AWp=f6L_O?aB_mr+IS^PNc z?B>qhJsx{*->-J=v;B4W?do{i7b%h8kw0tkysDKUCAUuO4)eNlAW?1wC-0dVOGRexk$B5-;w_hrl)Pu* zwOOCzJ7;l-?7C^>n8wxgqO0dct`}cH_tHJ9@43wBT{*$=+>2o4C7Ta;O?N-v%vHRN(3swam>tDB@t!;gRv>LNX;GFWM%nx7o%sq9b za|y11 zxWr>;kA6xvnzrwz?)h$G|1Pd67yr$?6;~Pi{2!NzwasMiEA8LD-CoeFom4-eF*&O0>loWMUk$q)tjq}|vN6c;BZvGZ8pZXE7#a3%`5elf*PC;+&U; zp7PpK+LB@S((3CL37L$`y=|*hwzi)#S|s*(yLGUe+~E$cH|=5P1Df{*7<*a<$tzjU zU)o*p(0=2_3bU&*k0+n^Dwhh*w0x(b>sfex=eZd^wL2zSzmXQ+))~EL?em(ArEl~D z__PDRN<6hSzTzelmX7j|{ zzgF>Zfx_-nk?m`Y9@(a-tLEF)irqW1`aK*70fK8u!qtSiv6yxP}tuG`AZQ@r2$rfT2Lx86yI z%X~#$kDfO%3}1BDa{t$36HOPr{(5hh<)@(R>5`rc>U}n+x!wJz8}$8zpiN{<(UG>* zDZiwG*4*RNb8Gr4xVJSv=HIfM4RYlSdZ)iC=9N63ux0H=gZ4P~OLJP4r)<10FgK^7 zl6OhPDVwbDEHl5&M@6)bZeut&dv@DtZ{yNAp+Du8o%LKXJ@3wQXE&{Tp2v(r^t}1w zZI-*P4qxc?cxuV4n4SO5%&KX>XRQ45Qv96cpf@$Q+_$a$Rh`oGnd`mPd`VZ4Yj0Wu zc(wP{@C3e|Y_M;~q_tnWZXB8|z2?^Q0yVktZWZMzl9gfBGnDpvY+P{7L^<`Ww&lrJ zzFTJm%$~j7FY8R_{a4Skbz(1swcE?6ZV`E?Aa$ekT5Ws@n=_}-25YvzJ9KXCtIw!h zn{{$=)PIxZvygdbU&-Dh4esjgWTxU=`|$G~$}pRTdcJJ|Jg z!7e)g$X!-cE+H_o>9wRq-!*UYMC%4m7P;w5c9He>Wys|Z?KrpJ|M*T z>%$3^+?G?fH^~R8IHwkApH1HHd(ScR<&n4FrF9XVOPoB3EeunkS z-AR7?&-RW)?b)+;YnQC_sXe(YzWSo#`@D$pSDeIK?p-o?e6fcX;zG3|CPJI6a z?}BC9&+gHbyHm&!>J#(x*%8Mrug+~gk^69ikfY+?4e$3ncZoY*u65+)$w@sDDSysM z*#F#Fc>A%cDZ7-FquDFfN$Z{(@``opELxlNpi(|-3ZI9u0GH{PD|h3Co_0B3m~NG0 zEvS00>wUwij37A~#kC>XkJ>!u-LLpdUYl{9<}MBHnU7y{VXVU_sN*)R{{JcGqWKnj2~r+gEeI&2yfc)fXQ+^^W;? zGN0F#oe^)o&D-mD?wrt{E7Q8y@o+B;OOZG^+2Oc*$CZ0i*1XNTbVvRXk5_b}5Zknn zl-YND<5R~$GN{nY6r1` zO8v_=$)DWy{&2nIHjVr2ZL4^;IrOI4R~|56_$%pGT+g3u@`ls&)S88R4qkk~GRsr` z**mMibE|Kt{o1@wEa%~AW8Lgy#h$fql{c`5=)bnrmkwBw!p^mGQe97pSZ9>5wBHn! zfZEw&KQnf&x^>Xe(;;?u;-I9`s`7M z{8^7bx3f57cwp~}slB{B6K2ggCAurO=HQELQU6u!$retwAD1Vu2t6XRRyMZhz5R-v zH6D@1+JRBZSrc8V%pOiN6gK@4t;27!fA99*lT$UK?gf4Qvqr&V|Ec`$Q+InV-D$I5 z-SOs!C%^4$>#!;ReUIqJO9Wig51KUh6lYb9o|Bo#6Q|2r^L$QUa9T6l^kHV~r&|q7 zN8Gl?u1L$zINB5vU3&F<=&az@k`oivSY%#0N1MI%xbyz&c@xW<9fyOPLbe^}k3D`X z^w%Dv_CgQYU4FglYp+~$ewmnD!{zIG^?`n!$KmaznW8&>7A{h&U!AdP$;I!D^V{VKj@HfJVeUkLsME{hFQ?LA&IH3RO zOV*@S6B(p^T3Ra2HqR(-xR$$C;^k)%-Up0Uvd0&(|5BS#Ua0)CE<*SB%d2gRx2^x> zuyC5-Gl&)NsVyxf8kZV8UM8W6H1m`ZnvAx*iL;ZhT|!MCblJ&+flBvu<8s zI8SSm#k>;=AyXHv)Q`M>QK{o++UsNn&xmgIt#g$mUnh7P_pRSqcYgAN)N;+3^B%g5 zTkbZg*a!C69Io-`%J09iI^}pyE}u-m@0A)k#S1q~_HGT(<#viX!wYF=m zh?AX!o*b zGZ&q@vw5xiG!2O_A9N;a=y%_5`FXWEKAzq3Sn57a@k`n)_2$u+C%kH^JCz}8ED#*X zJ#nka28|ryYuBEz&r5Zx;STKYp0%vZNytgk_S_}MlaDv8FL}wS5_8Lck4n~qs%NUd zEj#Xi_#wA^(x1Nt*K-*rYL_jkFWtIb)9~a0R#RF1J?s7+SvmQRu9d&W{|E~augpWI zqD8j&%~}43`&NZYNAL;$lgd{tI!pf+m+gN(QLwxD{-qBr&#nkdd+eSI&C%aQ7kL{QE@X)2VExzqs{d?JoBJCozaNAqk zX5G_&y?gs)xwUG~MLiZRV>Ry9eA7ImTSB<-$h34f{YSS9jC`VO?}z%tU;ClFn;5TXbh*vG;8SGt)wsa{a!wKVNBdPV8&7 zxNq3E@LkW&O5d4kdk@!FvhT0GJok8y&CD;0?<&q;UnFpRS}4b-@@I!nEzmuc_q*m& z`17Sl7I8g$$8XmzuFt(GZt|6BpK`QAmV|Oo`nG`CchkKHnHIy-8eV_&m+n1e8n{(j z)T6EKvFK;5@`93@p0BS(?DxO(n&j|%G6(a$MFKG&wsv=2hM{^2wd4GrvD` zKC&TT;^mBW&S|y6UY+%U@oytu@Ammo^R4AwZ>3Xhtg7$w#a`h&s=DTp#a~a}w6JOIxSi%W;mxOOEOTz&IV7`z zWme$4J+V`s-8S8nkaFTznf%wC2OanCF?0!9d1jYt=$<8}{CA7?Obm0@yS+)aa9f_` zw4KIB1Ll89)sa>!OuYGtPw;epK-LLi!8*_6n~~ElbMb4mZoiSYRpix;&QH#6lP2z& zRP%AC^mGRs>j;e0zzA@Xbr=Q@!s@P@D6tt9-5E zk|_^nAFLF2K6*@I`viZLR%^Aphi$#C{8d=eRR2)2Wr9fT#XC*~)f4{g?X3|BnRbA= z_1jI|rTYyhy?$G2!NhgpbKYXl)E~dh-Z^J4k!d`)enrDiUui9`H(njBD(}|aTDzy& zCWEur-M{&r;k*R>H7p*?8uBJPw_3iPnYZa&QpC~8i;b^3S%#)4di^q+cG9|!{eLK1 zANOQYLR;T_KgWCMgi6VCw`amD?WJ03e^q|iTWju}wb{oR zW!FWu3zuqq`FS&Os_^3c(@payPETAGwXvW5nb_qMDaWVU-{rbkP`JdgCt!kyu=dUO zZGRqRbj1g&{5+DwK2y&jZOIu;&Lp9nkMq_XTeIp(VffMsr|ZAlwduZeP+F|GU(LU~ z{2jLo3Y`~!`|pXk31^}cG2@Dv#$4goj7Tg zs;GA0ylUcC<8Hyy79&ieF-$+~yZw&mLV zce|w=tQRbO#C+4JF+kSxVvhXvt6L4F^Do7IJ@mfUsf{;m`}%dijz$*W);l{<fj?792B*}!qb#M*CaY+=M{gFq{{2qo5uqhY7uud*Ot=5K_rufO&u;s9 zzOU4F7yG;Iu6E7Tc2h42EqMd~LoVljoxbx?l<_pPZ=+k(_cWu5H@o+KDXRM1bww}g za_H=*k3W8J`!#W6RM@21Q9E1iw49yv{p>{hU!jbf{P)W8ZfJdBGHvFRL)OtZ z{;JnI?C|yrs@$Q*SF8E*p>5nNfqBjU{%krVl{wKyU+`|?diIm~trPYZzRld{_%m9d zV#c%&N9Sfv;)oBeP~})Huu7|X@5YGRrZ*NEgyq<=uWw!dmFJg)^S94e-#)2&vG}*G z%kJ3it@7t0jxVq=UvOiw$Pdn&D>S1H-;VujyYj(0FFvKWa|-`+aoS~^?n zo2r*l0ehuScWZk{^VI&027@cT(CE!M)F{Ue_E>khr`5kJ3va*2{JmnmAS6 z7C(C>VU(^`5_zMQ$Ml)C>Z`RR31?=U0kShS(~Z zB`&MKO*;~7T>0hAhPxLo^qU^}tJt>q;k9pdT0E0(-cLg$R|UC;Z@ zw&yP#T*>j|opra-f^LtWKMQW{s?F`%v|IA=20x_(jDKH!+|pT6ynMxjCC+|Fw?z27 z{XKK_vzh%%+Ipuwe7~UTl+oSp__$bqc?+MXhL&$xHlBaEd*4RmkMZ8Rjw_0-{w!)Z z*wP>U{mQm2rX?!30;&uqgxLeifeHN7!OFIBqsO1AQ< zcCJ*?8vjkzVP|`nH!jy^HHrM!80zRW@p=1qKHpl#D@SCEY~{YBeKnS-6AaoG*1mLp z>sOvUjo&ZC-d8%mUAbiipXtnrONI`6#J3&Lehq453gm4Ii~`f75jaTckDQRyLzJ5&Y(RLSPtb#EO>7I>W1X)fUEDi zMAH^#tOzSOE4=^h5jP1#EwSerQ!aiS!vg`xH1+wL&mv z()HA<4^P!g)vRBcG-t+P)dri0#F^W2EHA5aTsdx$WxCeMx?YgWkf)+JK|G03bn&9sIxvqW> zEo?;YPcrp>Rrt*g6ODLcACQh`ZEx9T8f9Q8L^@eki1`}pBmp%!;e)h$p=aE0Vr%m5! zuXk^u9K&A=^OC)_3Uj;n=fAou)?Z?H*3(Qxl4-$V=JQiq6;TFH&36ot>KmH4NdNwuD-=F44%p#SoBgS1bvCQd8R?;(sC!C`ngY*`9&Y! zeCvm`%>Kx{tm#EMzDkSrwQ~1~U2H67Feu5(y*r2TvD(8+%9TGl<=jH=b@E*hja-lz z$fsQ_AtT4LFppc|V)?#Hu8cWmo|86O=e^#leB9W+_M>4&(;?o}8TanVYZ$)gb6P4? zyJlgEar4mzsSjFS&pbcBvbM6YaxuTF$2I$)j$Dm*!W7|q`N|bL_q~03)mqB7?Sib= zJfWiWk0zDtwjU|oYuxtc#LsCmM;o^}F1qx*`{~S8U3q8P1>fHO@BB1e>~{M0);Jn1LrIHQExlP(#QoSt>sYQOxINXacZb5eW$ul1ald~Mp=+@#h=zxTWo zeSSks``J8mrO$KD2fVmxBX?lqo*n9?t6YBMey&l}lPOyk=y~8+gq!;EZ7Y7}B&F=q zQ2La9cWQl7`dZGpI&WvM_#u9+@8R!wq4~>i{hfSkfnLXgKQ6lcQ`prrokbLcA~&2b zURTfgCjQio^wc>QzFU72tvmknW&o$@7CG@a!^G)#{xo;(Kk6lQcd_~xlTNF3yEdhM zPf%0+AN@dardsjAfH(QADve->~pIQIrtM1CP zi(~GtU9P?Jy2i8R_g5UwouByALvX2{ROka{d9AX#SYgKy1q0)>>(}Z-*&hblKAn7i zvy}I1s}H(6wmpixcvY;?^6>M{wRS1O_K_NI&wiEO&XX_Cknd zYJ6Z}UjBi5wT%s%4|$mcuZg-~9<=4zuOI%pZ*Q#q-tn`rw%n;^7LUc{4LRa9B2PTT zzb)<1x|GFvGW}k-(MDh2S=`;$Hf!Jh$`lnUoZ6%D@Dx)}QQ@~~7oNRLk@|N1+=@j% z#h&F~YHYtXLDopDxX3xZxPtY5Y&uP&gr8`*!4Gy$7i(PYEo*CI%>SM=f+hnKr zS;F_?4e^&IeTGF!zc{ZdUs4pE_5EG#vPnOe$gZ0$(f4r2@2I_HXOz^O?tEr9^m*I& zwl!{o+=41+p~ucAtoeURs>d#^-Q>0Ryxjb6#T#M2)Gj+5(?(ev(&lOX*Ybh7g z_O&nXRxuwp&SLIKIh-r?ApG-{UH95AIqnEZUnglYr%i8%ysFaq&vv^FL?h@5hQ9G`&+&wZG|k{xn^%@9@-kHOI5C37oGj4dqUb~ zhP%pImp4vb+5THm=goqf6?He4)m`TPmGSy6QXJ9 zKW#H^Ju-Xp7CwI6f~b23>theh_$kUO{9=0Q(~Lf&V-CAiE&tuV`}g9~jt2;l&H*H)P{I2K4wQIYQe_5RQ95=_>OZ?9IWfOOp z_e`23SQIy{(Ds9_UeLlsma_-9r={Q0`LOLqi_uo+<#{$Z zy36Kmd9gR3qwY%aqT4o!$ER=DccuRFQ?C2kTND}Zc)yEM4Unn|mC!HT{8aXjTgBUe z+;VyK=U%dx9{R4hUH4G=h{e7$91-!?(&nBu|C@LwZ2BFGK-0>ycUMl-?ac4^_WSr% zE$J&)-o1VCHMvQKjsNtN7#s6DAAe;^yl<>>`LZW_c~9zW+0Gq7hs5>-r(B(Q;J}>| zQlAeW|7gTCb=}M5x0?S>xWG2`^UKDCpHhT2KA9vE9IbP#{pc*7H42;a8E!u?F?;;8 zEh6omgiV^+oaIta^w{;46aftk`Mt5yqT6Ke2Pd)l6u`zo`La6~9|%QE>_A8hQm2OOzG=Mu-*vrl9kHgSe1Z{CkJGc{xRB zJNr6CU|I1GUKbvObb&Ki0Omei>;28R^j%VmL6_bu=o+G)?~G<0@_K&**iwH(LldO6 z{w5||`k)|ia>}nzh}JbWFod1%Y-XZhX<`=31zPu;UaSB*WI7|UC^)r5L4%xQogs%h zd+K}Z`{?`X`+-(t!;f?h(~m@2Rh_P%p`WP_*#nTTU!Y$ITNkZgreCgKpS5DT^!G)ZA2o5C+9A0$Z3_Dp(j=C|DSSV$vLZcC(3srGbfpfr5!KXf3~` zfuVw#C1~xmrICWAfq{aBnTY~qnZJdZk%F1ArGf=W)WTE&WEjY37!6`WuqkNSzp(w2j(q*^si{v%)UKFKWd_n5 z9M4`IWqrcd#rWjv)1HPJ1_g6{HQ~v7*pJ*gE%xTm|ivKq#=rwmQ$9wBwYd*UM#|-kTqEU;Tgf zgTFlW!h7alv}dtjV6#6wPUPR2XXXcEbN(wT=*Jv;$KTQ~_lf=A)*bZ@+c>{Ny$c`Tm z+}ZMUxCF$W@cz0ll)Kl~MqyoC{rwXkPCvh&^PXe>Dg}Y~4&7&uWX^=y9MasZxymTw z<5?F`uHV9z?ax$tf4zI@x8_6Z6Lq~*=T-0C+_#gs8}?k_Vcz1L%Xa@=UrOE%20oQLh36N_e>6uCx-XT=Hbei*xCUhbR^-=_Dz zG|H8`aOLTn(04qiEtgM^EX$pK`}(b!O+u5UeM^cOwU$bVCdwSYvF)6YRc*_zCFN%n zAD`7eDjT3J-0MASqIq#hK_aF2359d8cJte}hgAn}YF8#&_1&V$6=Yi`HE| zarDSekE6f0^D5pnnde!$W4GUeOXU~8-Tm<;s%LX_V9bO3Uhek8FT0B#{+;18>B1zH za#rR)@U<)mAn>?fgPXHrhc1i zclzkD4tc)(mgZF=#?n4qo&A@5?$5b+!oV!8ojc?Ivii7X`*!uE#_&o1cysK-(v*p} z`c;<|Ij*0Se`i+AGbzr9Pb;b(D>8{p@eVq3zWP#)$vvsB?*DWwT&LGN9MS%>uR|ce ze{<_p>-d<56YnzWY?#k~czKTL4Tq`qb7x!45cJvjGVVn8*MyY+$?sOX?q}6xeOzLE z>!kFunF6YbyZ7EXX!YlZ!RF1gwr|%{xE*`XqnN#O?~P|Jr^QMuc8LpwVH%C~~2DHX;+KX)_F-8ui*`u*RY2qYcU*I?xR{BYa)_j@>`{|YvretYqW zpNfQ})8Pa1FZLdO<~G^t_SM|(y)ug?zB^doQRuwO^og3_94W^+t*<2&Z4>71_p(}{ z@~vl5@@viOj)f`Nk6sIM?_RlmZQ^aOoOgnPw~lscPY->hKjT}Lki(w$@;{&b;fu_= z=f>BOH6`|;u}P$?yZ13mht}_WUS^hB=M+CBc~)H6JJr4{d1j?Qx5jZ9>jOUnD|Rlq z{Zz1Tx>fdb9pwszWdHMw`x4Dqj?JIELjJXc(4AuHd-0k7kCNWsk0vJNk{>JsP;r^b|?&<`Uf;C{^0)#56@CWJiokte=jZjMU;T&y7q4G)`(Yhm`%7lJ{`%P} z`?ce(rQ%c@);}x6&VCnNFA^>p&1Dp{IQh+ol}qPeGuG(Y_%6lZsjCEUn3SecRc~y5 z(Ua6~pP7DtS~=6X{FM3ok~1;8J6uyZ&)0wAP3Qi+R(f5SuY}AwBmZKSl{YUuPnn$B zJTYe1>5pz5qG!I?yfk%G;=aVOsbsNRAy4?s%4h3hFQrcNy2x&Rd)l=PNy1;t4$V&3 zV-Y%`{MmX7Db0y0hpbp9F6x`UPPwq6u+VVT_F&b0o9#BY{`^w8=lS)Y+ui#N?|hfP z(mFf7<;`6hUgniMFJC*R^HqDn@!GwnMhfh2w9j2P=US$?=FX+4xn5iO-e%Zt zKHQk-*1M;3L4Np>cR@9u7c)YkUzh^m% zneSxp)8`j{Tl`Y}-52+Fi?iP<*5o~#82&`!oT2CB-k;J=mfFh~^gFzgfAM5aPD0~J z{WBXG{r~uQc&(Y&a!K=*A8&cDp7w^l9L39hWdoQ~=5Kj9tv0#B%R(;7;H39@j#i)D zt>uxgIM=CfYT1=>Ys-SpT^tPJ9kHvup2*uzzw&2Oum0P~XHqBBWS%)~6YQK^cB+P@ zF5DpG=mz1hmbv%eT{*jPjR3Ddzu9EDg;$rW^VEjlc*)F~cig1$P0$7V-1J{{OZ8T` znaTuR(SNFIarT*I(w%z^E$?mJv~R06f0Ng{bLgS<^90XReI^G!|CLHGHCs_yxWHoZ z?+1shJ*zqwq`bW+vZ>$m<%d!Mk8nNBuZMq~US<2*ZI;ic37b;FL)FbLn*UeY{9WjX zp@gsRYVCuQWNwHtby*8X?qSUong8*a{g1%K`DRmP_PL7JtP|U4ruJw<`bF2wB^Rf6 zu9D1ZT(fEAnxAXTGaJ9l`c0hD<8@L)@`^&BkmbJfk*mMjx!w1$j7*Qa^Z1AN$Hfag zwyK)l?M$gkeOSl&K;r)D$c(ZVV&_){Y^x7+{v0N&=zLkBoV8Ts*Pg<6f7{Z&*DkD4 zzp^0sUDW*2`Grq8>La^PJe+K!w7cw9^V-_$Om5qQ9$J4}5`JV)=!^CwO|x9@1Jg9R z?|9lY+Boq1Jh|+eeroN(i1oj3%wzs0boue&dliAV4%S&M6?9s3RkBG{@mS9FbugHCt$E+x3CHs? zzIrDu?u|C#zT0yk>i0GFYs;5!d1QBdzoik^jw8O3g}PBc&rI68MF0Dq>(NrBAsU+= zKD2r^U2*H?H7{CIR&BRsj$_spSGxS*LRVXb-231f=Xq^>!kupOJ^e-1T5iZqS@v#i z}cp7poJrv{U(J%-OBc zFFf^M$x1oikmWN3u32Tjd!^(hczjcMm4EHkZx<47JLnp{{bu|5Y(kwPXB5A~F`>+B z7J7Pb*L>J~E^zKvMWeLaH5<1Do@n4$9=@tlZ}t51&(Cu?ncqHKQR{V6pqH=9C*F==_Y|2x13fToBsPvH$P)^#jU!^{BPHEY`35J`dHX_W7w9+KAXfP zoy$}w=}h{WJ?r$0xayBx$AeyUFMYo=U|*obv9+nkt_8i8eC1(z<*(P7X4TUd6*G*i zXM|+SeemTzubXr|^tKv*uFmsE%Em>{85Rn4n7wk__)Ge@!_Ka03_1^|AAZ-#zpm6T z{bS|wn1j{Kc@9A#d|pDG3ATcgdpuay#pLVBE6tvKN$Y>pL%n^fd*?l`y(-`qxa4xo z`(1Z_xbpXze}2!gwO~54lV#iF$$yTEo{Dmf*rIc;r~NF>Wbce*NxaH9Pd$Fk;d51=UWrxzEx#$3`{POLLSs4A z6O4~eKDm)qvuNYw%%6TQ{MF~EHy-j)%Ar-vwyS2HC|NRoVq%s!}1KL z=X-&Jx$n&d_wualRh}aLA?EJ%T8cYmLFp-sTwvE}v>iN!LdvNji9Z#lKk za9^KFV{v9!=u`o(=8m7I;-n55RWZ+bY_amxmC)xM-8%0AjQ*5J{$ck0z0>9M(fRWl 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

j1#w9gd^)i0Hh!6ZWnRVUF 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 diff --git a/lib/hcrypto/libtommath/bn_cutoffs.c b/lib/hcrypto/libtommath/bn_cutoffs.c new file mode 100644 index 000000000..b02ab7161 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_cutoffs.c @@ -0,0 +1,14 @@ +#include "tommath_private.h" +#ifdef BN_CUTOFFS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef MP_FIXED_CUTOFFS +#include "tommath_cutoffs.h" +int KARATSUBA_MUL_CUTOFF = MP_DEFAULT_KARATSUBA_MUL_CUTOFF, + KARATSUBA_SQR_CUTOFF = MP_DEFAULT_KARATSUBA_SQR_CUTOFF, + TOOM_MUL_CUTOFF = MP_DEFAULT_TOOM_MUL_CUTOFF, + TOOM_SQR_CUTOFF = MP_DEFAULT_TOOM_SQR_CUTOFF; +#endif + +#endif diff --git a/lib/hcrypto/libtommath/bn_deprecated.c b/lib/hcrypto/libtommath/bn_deprecated.c new file mode 100644 index 000000000..2056b20e6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_deprecated.c @@ -0,0 +1,321 @@ +#include "tommath_private.h" +#ifdef BN_DEPRECATED_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef BN_MP_GET_BIT_C +int mp_get_bit(const mp_int *a, int b) +{ + if (b < 0) { + return MP_VAL; + } + return (s_mp_get_bit(a, (unsigned int)b) == MP_YES) ? MP_YES : MP_NO; +} +#endif +#ifdef BN_MP_JACOBI_C +mp_err mp_jacobi(const mp_int *a, const mp_int *n, int *c) +{ + if (a->sign == MP_NEG) { + return MP_VAL; + } + if (mp_cmp_d(n, 0uL) != MP_GT) { + return MP_VAL; + } + return mp_kronecker(a, n, c); +} +#endif +#ifdef BN_MP_PRIME_RANDOM_EX_C +mp_err mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat) +{ + return s_mp_prime_random_ex(a, t, size, flags, cb, dat); +} +#endif +#ifdef BN_MP_RAND_DIGIT_C +mp_err mp_rand_digit(mp_digit *r) +{ + mp_err err = s_mp_rand_source(r, sizeof(mp_digit)); + *r &= MP_MASK; + return err; +} +#endif +#ifdef BN_FAST_MP_INVMOD_C +mp_err fast_mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) +{ + return s_mp_invmod_fast(a, b, c); +} +#endif +#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C +mp_err fast_mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho) +{ + return s_mp_montgomery_reduce_fast(x, n, rho); +} +#endif +#ifdef BN_FAST_S_MP_MUL_DIGS_C +mp_err fast_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + return s_mp_mul_digs_fast(a, b, c, digs); +} +#endif +#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C +mp_err fast_s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + return s_mp_mul_high_digs_fast(a, b, c, digs); +} +#endif +#ifdef BN_FAST_S_MP_SQR_C +mp_err fast_s_mp_sqr(const mp_int *a, mp_int *b) +{ + return s_mp_sqr_fast(a, b); +} +#endif +#ifdef BN_MP_BALANCE_MUL_C +mp_err mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + return s_mp_balance_mul(a, b, c); +} +#endif +#ifdef BN_MP_EXPTMOD_FAST_C +mp_err mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) +{ + return s_mp_exptmod_fast(G, X, P, Y, redmode); +} +#endif +#ifdef BN_MP_INVMOD_SLOW_C +mp_err mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) +{ + return s_mp_invmod_slow(a, b, c); +} +#endif +#ifdef BN_MP_KARATSUBA_MUL_C +mp_err mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + return s_mp_karatsuba_mul(a, b, c); +} +#endif +#ifdef BN_MP_KARATSUBA_SQR_C +mp_err mp_karatsuba_sqr(const mp_int *a, mp_int *b) +{ + return s_mp_karatsuba_sqr(a, b); +} +#endif +#ifdef BN_MP_TOOM_MUL_C +mp_err mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + return s_mp_toom_mul(a, b, c); +} +#endif +#ifdef BN_MP_TOOM_SQR_C +mp_err mp_toom_sqr(const mp_int *a, mp_int *b) +{ + return s_mp_toom_sqr(a, b); +} +#endif +#ifdef S_MP_REVERSE_C +void bn_reverse(unsigned char *s, int len) +{ + if (len > 0) { + s_mp_reverse(s, (size_t)len); + } +} +#endif +#ifdef BN_MP_TC_AND_C +mp_err mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) +{ + return mp_and(a, b, c); +} +#endif +#ifdef BN_MP_TC_OR_C +mp_err mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c) +{ + return mp_or(a, b, c); +} +#endif +#ifdef BN_MP_TC_XOR_C +mp_err mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c) +{ + return mp_xor(a, b, c); +} +#endif +#ifdef BN_MP_TC_DIV_2D_C +mp_err mp_tc_div_2d(const mp_int *a, int b, mp_int *c) +{ + return mp_signed_rsh(a, b, c); +} +#endif +#ifdef BN_MP_INIT_SET_INT_C +mp_err mp_init_set_int(mp_int *a, unsigned long b) +{ + return mp_init_u32(a, (uint32_t)b); +} +#endif +#ifdef BN_MP_SET_INT_C +mp_err mp_set_int(mp_int *a, unsigned long b) +{ + mp_set_u32(a, (uint32_t)b); + return MP_OKAY; +} +#endif +#ifdef BN_MP_SET_LONG_C +mp_err mp_set_long(mp_int *a, unsigned long b) +{ + mp_set_u64(a, b); + return MP_OKAY; +} +#endif +#ifdef BN_MP_SET_LONG_LONG_C +mp_err mp_set_long_long(mp_int *a, unsigned long long b) +{ + mp_set_u64(a, b); + return MP_OKAY; +} +#endif +#ifdef BN_MP_GET_INT_C +unsigned long mp_get_int(const mp_int *a) +{ + return (unsigned long)mp_get_mag_u32(a); +} +#endif +#ifdef BN_MP_GET_LONG_C +unsigned long mp_get_long(const mp_int *a) +{ + return (unsigned long)mp_get_mag_ul(a); +} +#endif +#ifdef BN_MP_GET_LONG_LONG_C +unsigned long long mp_get_long_long(const mp_int *a) +{ + return mp_get_mag_ull(a); +} +#endif +#ifdef BN_MP_PRIME_IS_DIVISIBLE_C +mp_err mp_prime_is_divisible(const mp_int *a, mp_bool *result) +{ + return s_mp_prime_is_divisible(a, result); +} +#endif +#ifdef BN_MP_EXPT_D_EX_C +mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) +{ + (void)fast; + if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + return MP_VAL; + } + return mp_expt_u32(a, (uint32_t)b, c); +} +#endif +#ifdef BN_MP_EXPT_D_C +mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c) +{ + if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + return MP_VAL; + } + return mp_expt_u32(a, (uint32_t)b, c); +} +#endif +#ifdef BN_MP_N_ROOT_EX_C +mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) +{ + (void)fast; + if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + return MP_VAL; + } + return mp_root_u32(a, (uint32_t)b, c); +} +#endif +#ifdef BN_MP_N_ROOT_C +mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c) +{ + if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + return MP_VAL; + } + return mp_root_u32(a, (uint32_t)b, c); +} +#endif +#ifdef BN_MP_UNSIGNED_BIN_SIZE_C +int mp_unsigned_bin_size(const mp_int *a) +{ + return (int)mp_ubin_size(a); +} +#endif +#ifdef BN_MP_READ_UNSIGNED_BIN_C +mp_err mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c) +{ + return mp_from_ubin(a, b, (size_t) c); +} +#endif +#ifdef BN_MP_TO_UNSIGNED_BIN_C +mp_err mp_to_unsigned_bin(const mp_int *a, unsigned char *b) +{ + return mp_to_ubin(a, b, SIZE_MAX, NULL); +} +#endif +#ifdef BN_MP_TO_UNSIGNED_BIN_N_C +mp_err mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen) +{ + size_t n = mp_ubin_size(a); + if (*outlen < (unsigned long)n) { + return MP_VAL; + } + *outlen = (unsigned long)n; + return mp_to_ubin(a, b, n, NULL); +} +#endif +#ifdef BN_MP_SIGNED_BIN_SIZE_C +int mp_signed_bin_size(const mp_int *a) +{ + return (int)mp_sbin_size(a); +} +#endif +#ifdef BN_MP_READ_SIGNED_BIN_C +mp_err mp_read_signed_bin(mp_int *a, const unsigned char *b, int c) +{ + return mp_from_sbin(a, b, (size_t) c); +} +#endif +#ifdef BN_MP_TO_SIGNED_BIN_C +mp_err mp_to_signed_bin(const mp_int *a, unsigned char *b) +{ + return mp_to_sbin(a, b, SIZE_MAX, NULL); +} +#endif +#ifdef BN_MP_TO_SIGNED_BIN_N_C +mp_err mp_to_signed_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen) +{ + size_t n = mp_sbin_size(a); + if (*outlen < (unsigned long)n) { + return MP_VAL; + } + *outlen = (unsigned long)n; + return mp_to_sbin(a, b, n, NULL); +} +#endif +#ifdef BN_MP_TORADIX_N_C +mp_err mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) +{ + if (maxlen < 0) { + return MP_VAL; + } + return mp_to_radix(a, str, (size_t)maxlen, NULL, radix); +} +#endif +#ifdef BN_MP_TORADIX_C +mp_err mp_toradix(const mp_int *a, char *str, int radix) +{ + return mp_to_radix(a, str, SIZE_MAX, NULL, radix); +} +#endif +#ifdef BN_MP_IMPORT_C +mp_err mp_import(mp_int *rop, size_t count, int order, size_t size, int endian, size_t nails, + const void *op) +{ + return mp_unpack(rop, count, order, size, endian, nails, op); +} +#endif +#ifdef BN_MP_EXPORT_C +mp_err mp_export(void *rop, size_t *countp, int order, size_t size, + int endian, size_t nails, const mp_int *op) +{ + return mp_pack(rop, SIZE_MAX, countp, order, size, endian, nails, op); +} +#endif +#endif diff --git a/lib/hcrypto/libtommath/bn_error.c b/lib/hcrypto/libtommath/bn_error.c deleted file mode 100644 index fbba7aa1f..000000000 --- a/lib/hcrypto/libtommath/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; - const 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 */ -const char *mp_error_to_string(int code) -{ - int x; - - /* scan the lookup table for the given message */ - for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) { - if (msgs[x].code == code) { - return msgs[x].msg; - } - } - - /* generic reply for invalid code */ - return "Invalid error code"; -} - -#endif - -/* $Source: /cvs/libtom/libtommath/bn_error.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_fast_mp_invmod.c b/lib/hcrypto/libtommath/bn_fast_mp_invmod.c deleted file mode 100644 index f4780d8e8..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_fast_mp_invmod.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c b/lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c deleted file mode 100644 index b6c0694bd..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_fast_mp_montgomery_reduce.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c b/lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c deleted file mode 100644 index 90f161b10..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_fast_s_mp_mul_digs.c,v $ */ -/* $Revision: 1.8 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c b/lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c deleted file mode 100644 index a03b9f132..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_fast_s_mp_mul_high_digs.c,v $ */ -/* $Revision: 1.6 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c b/lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c deleted file mode 100644 index 848eaf046..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_fast_s_mp_sqr.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_2expt.c b/lib/hcrypto/libtommath/bn_mp_2expt.c index 11a508c7f..0ae3df1bf 100644 --- a/lib/hcrypto/libtommath/bn_mp_2expt.c +++ b/lib/hcrypto/libtommath/bn_mp_2expt.c @@ -1,48 +1,31 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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) +mp_err mp_2expt(mp_int *a, int b) { - int res; + mp_err err; - /* zero a as per default */ - mp_zero (a); + /* 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; - } + /* grow a to accomodate the single bit */ + if ((err = mp_grow(a, (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) { + return err; + } - /* set the used count of where the bit will go */ - a->used = b / DIGIT_BIT + 1; + /* set the used count of where the bit will go */ + a->used = (b / MP_DIGIT_BIT) + 1; - /* put the single bit in its place */ - a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT); + /* put the single bit in its place */ + a->dp[b / MP_DIGIT_BIT] = (mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT); - return MP_OKAY; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_2expt.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_abs.c b/lib/hcrypto/libtommath/bn_mp_abs.c index d97e8db05..00900bbdd 100644 --- a/lib/hcrypto/libtommath/bn_mp_abs.c +++ b/lib/hcrypto/libtommath/bn_mp_abs.c @@ -1,43 +1,26 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* b = |a| * * Simple function copies the input and fixes the sign to positive */ -int -mp_abs (mp_int * a, mp_int * b) +mp_err mp_abs(const mp_int *a, mp_int *b) { - int res; + mp_err err; - /* copy a to b */ - if (a != b) { - if ((res = mp_copy (a, b)) != MP_OKAY) { - return res; - } - } + /* copy a to b */ + if (a != b) { + if ((err = mp_copy(a, b)) != MP_OKAY) { + return err; + } + } - /* force the sign of b to positive */ - b->sign = MP_ZPOS; + /* force the sign of b to positive */ + b->sign = MP_ZPOS; - return MP_OKAY; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_abs.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_add.c b/lib/hcrypto/libtommath/bn_mp_add.c index be2064477..dfa78de50 100644 --- a/lib/hcrypto/libtommath/bn_mp_add.c +++ b/lib/hcrypto/libtommath/bn_mp_add.c @@ -1,53 +1,38 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* high level addition (handles signs) */ -int mp_add (mp_int * a, mp_int * b, mp_int * c) +mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c) { - int sa, sb, res; + mp_sign sa, sb; + mp_err err; - /* get sign of both inputs */ - sa = a->sign; - sb = b->sign; + /* 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 { + /* 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_sub (a, b, c); - } - } - return res; + err = 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; + err = s_mp_sub(b, a, c); + } else { + c->sign = sa; + err = s_mp_sub(a, b, c); + } + } + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_add.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_add_d.c b/lib/hcrypto/libtommath/bn_mp_add_d.c index 8ca36c112..f30157561 100644 --- a/lib/hcrypto/libtommath/bn_mp_add_d.c +++ b/lib/hcrypto/libtommath/bn_mp_add_d.c @@ -1,112 +1,89 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* single digit addition */ -int -mp_add_d (mp_int * a, mp_digit b, mp_int * c) +mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c) { - int res, ix, oldused; - mp_digit *tmpa, *tmpc, mu; + mp_err err; + int ix, oldused; + mp_digit *tmpa, *tmpc; - /* grow c as required */ - if (c->alloc < a->used + 1) { - if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { - return res; - } - } + /* grow c as required */ + if (c->alloc < (a->used + 1)) { + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + } - /* 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; + /* if a is negative and |a| >= b, call c = |a| - b */ + if ((a->sign == MP_NEG) && ((a->used > 1) || (a->dp[0] >= b))) { + mp_int a_ = *a; + /* temporarily fix sign of a */ + a_.sign = MP_ZPOS; - /* c = |a| - b */ - res = mp_sub_d(a, b, c); + /* c = |a| - b */ + err = mp_sub_d(&a_, b, c); - /* fix sign */ - a->sign = c->sign = MP_NEG; + /* fix sign */ + c->sign = MP_NEG; - /* clamp */ - mp_clamp(c); + /* clamp */ + mp_clamp(c); - return res; - } + return err; + } - /* old number of used digits in c */ - oldused = c->used; + /* old number of used digits in c */ + oldused = c->used; - /* sign always positive */ - c->sign = MP_ZPOS; + /* source alias */ + tmpa = a->dp; - /* source alias */ - tmpa = a->dp; + /* destination alias */ + tmpc = c->dp; - /* destination alias */ - tmpc = c->dp; + /* if a is positive */ + if (a->sign == MP_ZPOS) { + /* add digits, mu is carry */ + mp_digit mu = b; + for (ix = 0; ix < a->used; ix++) { + *tmpc = *tmpa++ + mu; + mu = *tmpc >> MP_DIGIT_BIT; + *tmpc++ &= MP_MASK; + } + /* set final carry */ + ix++; + *tmpc++ = mu; - /* 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; + /* setup size */ + c->used = a->used + 1; + } else { + /* a was negative and |a| < b */ + c->used = 1; - /* 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; + /* the result is a single digit */ + if (a->used == 1) { + *tmpc++ = b - a->dp[0]; + } else { + *tmpc++ = b; + } - /* setup size */ - c->used = a->used + 1; - } else { - /* a was negative and |a| < b */ - c->used = 1; + /* setup count so the clearing of oldused + * can fall through correctly + */ + ix = 1; + } - /* the result is a single digit */ - if (a->used == 1) { - *tmpc++ = b - a->dp[0]; - } else { - *tmpc++ = b; - } + /* sign always positive */ + c->sign = MP_ZPOS; - /* setup count so the clearing of oldused - * can fall through correctly - */ - ix = 1; - } + /* now zero to oldused */ + MP_ZERO_DIGITS(tmpc, oldused - ix); + mp_clamp(c); - /* now zero to oldused */ - while (ix++ < oldused) { - *tmpc++ = 0; - } - mp_clamp(c); - - return MP_OKAY; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_add_d.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_addmod.c b/lib/hcrypto/libtommath/bn_mp_addmod.c index 6d8afe18c..1dcfb678c 100644 --- a/lib/hcrypto/libtommath/bn_mp_addmod.c +++ b/lib/hcrypto/libtommath/bn_mp_addmod.c @@ -1,41 +1,25 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* d = a + b (mod c) */ -int -mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) { - int res; - mp_int t; + mp_err err; + mp_int t; - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } - 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; + if ((err = mp_add(a, b, &t)) != MP_OKAY) { + goto LBL_ERR; + } + err = mp_mod(&t, c, d); + +LBL_ERR: + mp_clear(&t); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_addmod.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_and.c b/lib/hcrypto/libtommath/bn_mp_and.c index 8ea22878f..c259f8dec 100644 --- a/lib/hcrypto/libtommath/bn_mp_and.c +++ b/lib/hcrypto/libtommath/bn_mp_and.c @@ -1,57 +1,56 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ -/* AND two ints together */ -int -mp_and (mp_int * a, mp_int * b, mp_int * c) +/* two complement and */ +mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c) { - int res, ix, px; - mp_int t, *x; + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + mp_sign csign = ((a->sign == MP_NEG) && (b->sign == MP_NEG)) ? MP_NEG : MP_ZPOS; - 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; - } + if (c->alloc < used) { + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + } - for (ix = 0; ix < px; ix++) { - t.dp[ix] &= x->dp[ix]; - } + for (i = 0; i < used; i++) { + mp_digit x, y; - /* zero digits above the last from the smallest mp_int */ - for (; ix < t.used; ix++) { - t.dp[ix] = 0; - } + /* convert to two complement if negative */ + if (a->sign == MP_NEG) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } - mp_clamp (&t); - mp_exch (c, &t); - mp_clear (&t); - return MP_OKAY; + /* convert to two complement if negative */ + if (b->sign == MP_NEG) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x & y; + + /* convert to to sign-magnitude if negative */ + if (csign == MP_NEG) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = csign; + mp_clamp(c); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_and.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_clamp.c b/lib/hcrypto/libtommath/bn_mp_clamp.c index 2a565e8db..ac23bfd3f 100644 --- a/lib/hcrypto/libtommath/bn_mp_clamp.c +++ b/lib/hcrypto/libtommath/bn_mp_clamp.c @@ -1,19 +1,7 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* trim unused digits * @@ -22,23 +10,18 @@ * Typically very fast. Also fixes the sign if there * are no more leading digits */ -void -mp_clamp (mp_int * a) +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); - } + /* decrease used while the most significant digit is + * zero. + */ + while ((a->used > 0) && (a->dp[a->used - 1] == 0u)) { + --(a->used); + } - /* reset the sign flag if used == 0 */ - if (a->used == 0) { - a->sign = MP_ZPOS; - } + /* reset the sign flag if used == 0 */ + if (a->used == 0) { + a->sign = MP_ZPOS; + } } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_clamp.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_clear.c b/lib/hcrypto/libtommath/bn_mp_clear.c index a65f0a36c..ff78324d9 100644 --- a/lib/hcrypto/libtommath/bn_mp_clear.c +++ b/lib/hcrypto/libtommath/bn_mp_clear.c @@ -1,44 +1,20 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* clear one (frees) */ -void -mp_clear (mp_int * a) +void mp_clear(mp_int *a) { - int i; + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* free ram */ + MP_FREE_DIGITS(a->dp, a->alloc); - /* 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; - } + /* reset members to make debugging easier */ + a->dp = NULL; + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_clear.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_clear_multi.c b/lib/hcrypto/libtommath/bn_mp_clear_multi.c index e5e3da340..794e45fa5 100644 --- a/lib/hcrypto/libtommath/bn_mp_clear_multi.c +++ b/lib/hcrypto/libtommath/bn_mp_clear_multi.c @@ -1,34 +1,19 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + #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); + mp_int *next_mp = mp; + va_list args; + va_start(args, mp); + while (next_mp != NULL) { + mp_clear(next_mp); + next_mp = va_arg(args, mp_int *); + } + va_end(args); } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_clear_multi.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_cmp.c b/lib/hcrypto/libtommath/bn_mp_cmp.c index ccd2c8eb9..ced484096 100644 --- a/lib/hcrypto/libtommath/bn_mp_cmp.c +++ b/lib/hcrypto/libtommath/bn_mp_cmp.c @@ -1,43 +1,26 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* compare two ints (signed)*/ -int -mp_cmp (mp_int * a, mp_int * b) +mp_ord mp_cmp(const mp_int *a, const 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 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); - } + /* compare digits */ + if (a->sign == MP_NEG) { + /* if negative compare opposite direction */ + return mp_cmp_mag(b, a); + } else { + return mp_cmp_mag(a, b); + } } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_cmp.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_cmp_d.c b/lib/hcrypto/libtommath/bn_mp_cmp_d.c index 724c1c363..5a8337b5b 100644 --- a/lib/hcrypto/libtommath/bn_mp_cmp_d.c +++ b/lib/hcrypto/libtommath/bn_mp_cmp_d.c @@ -1,44 +1,28 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* compare a digit */ -int mp_cmp_d(mp_int * a, mp_digit b) +mp_ord mp_cmp_d(const mp_int *a, mp_digit b) { - /* compare based on sign */ - if (a->sign == MP_NEG) { - return MP_LT; - } + /* compare based on sign */ + if (a->sign == MP_NEG) { + return MP_LT; + } - /* compare based on magnitude */ - if (a->used > 1) { - return MP_GT; - } + /* 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; - } + /* compare the only digit of a to b */ + if (a->dp[0] > b) { + return MP_GT; + } else if (a->dp[0] < b) { + return MP_LT; + } else { + return MP_EQ; + } } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_d.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_cmp_mag.c b/lib/hcrypto/libtommath/bn_mp_cmp_mag.c index 4a505238a..f144ea9e6 100644 --- a/lib/hcrypto/libtommath/bn_mp_cmp_mag.c +++ b/lib/hcrypto/libtommath/bn_mp_cmp_mag.c @@ -1,55 +1,39 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* compare maginitude of two ints (unsigned) */ -int mp_cmp_mag (mp_int * a, mp_int * b) +mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b) { - int n; - mp_digit *tmpa, *tmpb; + int n; + const 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) { + /* compare based on # of non-zero digits */ + if (a->used > b->used) { return MP_GT; - } + } - if (*tmpa < *tmpb) { + if (a->used < b->used) { return MP_LT; - } - } - return MP_EQ; + } + + /* alias for a */ + tmpa = a->dp + (a->used - 1); + + /* alias for b */ + tmpb = b->dp + (a->used - 1); + + /* compare based on digits */ + for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { + if (*tmpa > *tmpb) { + return MP_GT; + } + + if (*tmpa < *tmpb) { + return MP_LT; + } + } + return MP_EQ; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_mag.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c b/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c index 2d4a8d4f0..4b2d206eb 100644 --- a/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c +++ b/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c @@ -1,53 +1,37 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ 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 mp_cnt_lsb(const mp_int *a) { int x; mp_digit q, qq; /* easy out */ - if (mp_iszero(a) == 1) { + if (MP_IS_ZERO(a)) { return 0; } /* scan lower digits until non-zero */ - for (x = 0; x < a->used && a->dp[x] == 0; x++); + for (x = 0; (x < a->used) && (a->dp[x] == 0u); x++) {} q = a->dp[x]; - x *= DIGIT_BIT; + x *= MP_DIGIT_BIT; /* now scan this digit until a 1 is found */ - if ((q & 1) == 0) { + if ((q & 1u) == 0u) { do { - qq = q & 15; + qq = q & 15u; x += lnz[qq]; q >>= 4; - } while (qq == 0); + } while (qq == 0u); } return x; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_cnt_lsb.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_complement.c b/lib/hcrypto/libtommath/bn_mp_complement.c new file mode 100644 index 000000000..fef1423c5 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_complement.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef BN_MP_COMPLEMENT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = ~a */ +mp_err mp_complement(const mp_int *a, mp_int *b) +{ + mp_err err = mp_neg(a, b); + return (err == MP_OKAY) ? mp_sub_d(b, 1uL, b) : err; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_copy.c b/lib/hcrypto/libtommath/bn_mp_copy.c index b0de16d8a..e72fcf6d5 100644 --- a/lib/hcrypto/libtommath/bn_mp_copy.c +++ b/lib/hcrypto/libtommath/bn_mp_copy.c @@ -1,68 +1,47 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* copy, b = a */ -int -mp_copy (mp_int * a, mp_int * b) +mp_err mp_copy(const mp_int *a, mp_int *b) { - int res, n; + int n; + mp_digit *tmpa, *tmpb; + mp_err err; - /* if dst == src do nothing */ - if (a == b) { - return MP_OKAY; - } + /* 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; - } - } + /* grow dest */ + if (b->alloc < a->used) { + if ((err = mp_grow(b, a->used)) != MP_OKAY) { + return err; + } + } - /* zero b and copy the parameters over */ - { - register mp_digit *tmpa, *tmpb; + /* zero b and copy the parameters over */ + /* pointer aliases */ - /* pointer aliases */ + /* source */ + tmpa = a->dp; - /* source */ - tmpa = a->dp; + /* destination */ + tmpb = b->dp; - /* destination */ - tmpb = b->dp; - - /* copy all the digits */ - for (n = 0; n < a->used; n++) { + /* copy all the digits */ + for (n = 0; n < a->used; n++) { *tmpb++ = *tmpa++; - } + } - /* clear high digits */ - for (; n < b->used; n++) { - *tmpb++ = 0; - } - } + /* clear high digits */ + MP_ZERO_DIGITS(tmpb, b->used - n); - /* copy used count and sign */ - b->used = a->used; - b->sign = a->sign; - return MP_OKAY; + /* copy used count and sign */ + b->used = a->used; + b->sign = a->sign; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_copy.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_count_bits.c b/lib/hcrypto/libtommath/bn_mp_count_bits.c index 5dfd5f375..b7c2cad10 100644 --- a/lib/hcrypto/libtommath/bn_mp_count_bits.c +++ b/lib/hcrypto/libtommath/bn_mp_count_bits.c @@ -1,45 +1,28 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* returns the number of bits in an int */ -int -mp_count_bits (mp_int * a) +int mp_count_bits(const mp_int *a) { - int r; - mp_digit q; + int r; + mp_digit q; - /* shortcut */ - if (a->used == 0) { - return 0; - } + /* shortcut */ + if (MP_IS_ZERO(a)) { + return 0; + } - /* get number of digits and add that */ - r = (a->used - 1) * DIGIT_BIT; + /* get number of digits and add that */ + r = (a->used - 1) * MP_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; + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > 0u) { + ++r; + q >>= 1u; + } + return r; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_count_bits.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_decr.c b/lib/hcrypto/libtommath/bn_mp_decr.c new file mode 100644 index 000000000..c6a1572c6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_decr.c @@ -0,0 +1,34 @@ +#include "tommath_private.h" +#ifdef BN_MP_DECR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Decrement "a" by one like "a--". Changes input! */ +mp_err mp_decr(mp_int *a) +{ + if (MP_IS_ZERO(a)) { + mp_set(a,1uL); + a->sign = MP_NEG; + return MP_OKAY; + } else if (a->sign == MP_NEG) { + mp_err err; + a->sign = MP_ZPOS; + if ((err = mp_incr(a)) != MP_OKAY) { + return err; + } + /* There is no -0 in LTM */ + if (!MP_IS_ZERO(a)) { + a->sign = MP_NEG; + } + return MP_OKAY; + } else if (a->dp[0] > 1uL) { + a->dp[0]--; + if (a->dp[0] == 0u) { + mp_zero(a); + } + return MP_OKAY; + } else { + return mp_sub_d(a, 1uL,a); + } +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_div.c b/lib/hcrypto/libtommath/bn_mp_div.c index 2c364b396..71de55bea 100644 --- a/lib/hcrypto/libtommath/bn_mp_div.c +++ b/lib/hcrypto/libtommath/bn_mp_div.c @@ -1,88 +1,71 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ #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_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) { mp_int ta, tb, tq, q; - int res, n, n2; + int n, n2; + mp_err err; - /* is divisor zero ? */ - if (mp_iszero (b) == 1) { - return MP_VAL; - } + /* is divisor zero ? */ + if (MP_IS_ZERO(b)) { + 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 a < b then q=0, r = a */ + if (mp_cmp_mag(a, b) == MP_LT) { + if (d != NULL) { + err = mp_copy(a, d); + } else { + err = MP_OKAY; + } + if (c != NULL) { + mp_zero(c); + } + return err; + } - /* init our temps */ - if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) { - return res; - } + /* init our temps */ + if ((err = mp_init_multi(&ta, &tb, &tq, &q, NULL)) != MP_OKAY) { + return err; + } - 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; - } + mp_set(&tq, 1uL); + n = mp_count_bits(a) - mp_count_bits(b); + if ((err = mp_abs(a, &ta)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_abs(b, &tb)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) goto LBL_ERR; + if ((err = 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; - } - } + while (n-- >= 0) { + if (mp_cmp(&tb, &ta) != MP_GT) { + if ((err = mp_sub(&ta, &tb, &ta)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&q, &tq, &q)) != MP_OKAY) goto LBL_ERR; + } + if ((err = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) goto LBL_ERR; + if ((err = 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; - } + /* 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_IS_ZERO(c) ? MP_ZPOS : n2; + } + if (d != NULL) { + mp_exch(d, &ta); + d->sign = MP_IS_ZERO(d) ? MP_ZPOS : n; + } LBL_ERR: mp_clear_multi(&ta, &tb, &tq, &q, NULL); - return res; + return err; } #else @@ -100,193 +83,168 @@ LBL_ERR: * 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_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) { - mp_int q, x, y, t1, t2; - int res, n, t, i, norm, neg; + mp_int q, x, y, t1, t2; + int n, t, i, norm; + mp_sign neg; + mp_err err; - /* is divisor zero ? */ - if (mp_iszero (b) == 1) { - return MP_VAL; - } + /* is divisor zero ? */ + if (MP_IS_ZERO(b)) { + 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 a < b then q=0, r = a */ + if (mp_cmp_mag(a, b) == MP_LT) { + if (d != NULL) { + err = mp_copy(a, d); + } else { + err = MP_OKAY; + } + if (c != NULL) { + mp_zero(c); + } + return err; + } - if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { - return res; - } - q.used = a->used + 2; + if ((err = mp_init_size(&q, a->used + 2)) != MP_OKAY) { + return err; + } + q.used = a->used + 2; - if ((res = mp_init (&t1)) != MP_OKAY) { - goto LBL_Q; - } + if ((err = mp_init(&t1)) != MP_OKAY) goto LBL_Q; - if ((res = mp_init (&t2)) != MP_OKAY) { - goto LBL_T1; - } + if ((err = mp_init(&t2)) != MP_OKAY) goto LBL_T1; - if ((res = mp_init_copy (&x, a)) != MP_OKAY) { - goto LBL_T2; - } + if ((err = mp_init_copy(&x, a)) != MP_OKAY) goto LBL_T2; - if ((res = mp_init_copy (&y, b)) != MP_OKAY) { - goto LBL_X; - } + if ((err = 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; + /* 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; - } + /* normalize both x and y, ensure that y >= b/2, [b == 2**MP_DIGIT_BIT] */ + norm = mp_count_bits(&y) % MP_DIGIT_BIT; + if (norm < (MP_DIGIT_BIT - 1)) { + norm = (MP_DIGIT_BIT - 1) - norm; + if ((err = mp_mul_2d(&x, norm, &x)) != MP_OKAY) goto LBL_Y; + if ((err = 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; + /* 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 (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ + /* y = y*b**{n-t} */ + if ((err = mp_lshd(&y, n - t)) != MP_OKAY) 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; - } - } + while (mp_cmp(&x, &y) != MP_LT) { + ++(q.dp[n - t]); + if ((err = mp_sub(&x, &y, &x)) != MP_OKAY) goto LBL_Y; + } - /* reset y by shifting it back down */ - mp_rshd (&y, n - t); + /* 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. 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)); - } + /* 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 << (mp_digit)MP_DIGIT_BIT) - (mp_digit)1; + } else { + mp_word tmp; + tmp = (mp_word)x.dp[i] << (mp_word)MP_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 + /* while (q{i-t-1} * (yt * b + y{t-1})) > + xi * b**2 + xi-1 * b + xi-2 - do q{i-t-1} -= 1; + do q{i-t-1} -= 1; + */ + q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] + 1uL) & (mp_digit)MP_MASK; + do { + q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & (mp_digit)MP_MASK; + + /* find left hand */ + mp_zero(&t1); + t1.dp[0] = ((t - 1) < 0) ? 0u : y.dp[t - 1]; + t1.dp[1] = y.dp[t]; + t1.used = 2; + if ((err = mp_mul_d(&t1, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y; + + /* find right hand */ + t2.dp[0] = ((i - 2) < 0) ? 0u : x.dp[i - 2]; + t2.dp[1] = x.dp[i - 1]; /* i >= 1 always holds */ + 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 ((err = mp_mul_d(&y, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y; + + if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y; + + if ((err = 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 ((err = mp_copy(&y, &t1)) != MP_OKAY) goto LBL_Y; + if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y; + if ((err = 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] */ - 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; - } + /* get sign before writing to c */ + x.sign = (x.used == 0) ? MP_ZPOS : a->sign; - /* 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); + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + c->sign = neg; + } - /* 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 (d != NULL) { + if ((err = mp_div_2d(&x, norm, &x, NULL)) != MP_OKAY) goto LBL_Y; + mp_exch(&x, d); + } - if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { - goto LBL_Y; - } + err = MP_OKAY; - 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; +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 err; } #endif #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_div.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_div_2.c b/lib/hcrypto/libtommath/bn_mp_div_2.c index 7ee3e5b70..f56ea8199 100644 --- a/lib/hcrypto/libtommath/bn_mp_div_2.c +++ b/lib/hcrypto/libtommath/bn_mp_div_2.c @@ -1,68 +1,49 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* b = a/2 */ -int mp_div_2(mp_int * a, mp_int * b) +mp_err mp_div_2(const mp_int *a, mp_int *b) { - int x, res, oldused; + int x, oldused; + mp_digit r, rr, *tmpa, *tmpb; + mp_err err; - /* copy */ - if (b->alloc < a->used) { - if ((res = mp_grow (b, a->used)) != MP_OKAY) { - return res; - } - } + /* copy */ + if (b->alloc < a->used) { + if ((err = mp_grow(b, a->used)) != MP_OKAY) { + return err; + } + } - oldused = b->used; - b->used = a->used; - { - register mp_digit r, rr, *tmpa, *tmpb; + oldused = b->used; + b->used = a->used; - /* source alias */ - tmpa = a->dp + b->used - 1; + /* source alias */ + tmpa = a->dp + b->used - 1; - /* dest alias */ - tmpb = b->dp + b->used - 1; + /* dest alias */ + tmpb = b->dp + b->used - 1; - /* carry */ - r = 0; - for (x = b->used - 1; x >= 0; x--) { + /* carry */ + r = 0; + for (x = b->used - 1; x >= 0; x--) { /* get the carry for the next iteration */ - rr = *tmpa & 1; + rr = *tmpa & 1u; /* shift the current digit, add in carry and store */ - *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); + *tmpb-- = (*tmpa-- >> 1) | (r << (MP_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; + /* zero excess digits */ + MP_ZERO_DIGITS(b->dp + b->used, oldused - b->used); + + b->sign = a->sign; + mp_clamp(b); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_div_2.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_div_2d.c b/lib/hcrypto/libtommath/bn_mp_div_2d.c index 4f7fa59e3..c47d5ce35 100644 --- a/lib/hcrypto/libtommath/bn_mp_div_2d.c +++ b/lib/hcrypto/libtommath/bn_mp_div_2d.c @@ -1,97 +1,71 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) { - mp_digit D, r, rr; - int x, res; - mp_int t; + mp_digit D, r, rr; + int x; + mp_err err; + /* if the shift count is <= 0 then we do no work */ + if (b <= 0) { + err = mp_copy(a, c); + if (d != NULL) { + mp_zero(d); + } + return err; + } - /* 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; - } + /* copy */ + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + /* 'a' should not be used after here - it might be the same as d */ - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } + /* get the remainder */ + if (d != NULL) { + if ((err = mp_mod_2d(a, b, d)) != MP_OKAY) { + return err; + } + } - /* get the remainder */ - if (d != NULL) { - if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - } + /* shift by as many digits in the bit count */ + if (b >= MP_DIGIT_BIT) { + mp_rshd(c, b / MP_DIGIT_BIT); + } - /* copy */ - if ((res = mp_copy (a, c)) != MP_OKAY) { - mp_clear (&t); - return res; - } + /* shift any bit count < MP_DIGIT_BIT */ + D = (mp_digit)(b % MP_DIGIT_BIT); + if (D != 0u) { + mp_digit *tmpc, mask, shift; - /* shift by as many digits in the bit count */ - if (b >= (int)DIGIT_BIT) { - mp_rshd (c, b / DIGIT_BIT); - } + /* mask */ + mask = ((mp_digit)1 << D) - 1uL; - /* shift any bit count < DIGIT_BIT */ - D = (mp_digit) (b % DIGIT_BIT); - if (D != 0) { - register mp_digit *tmpc, mask, shift; + /* shift for lsb */ + shift = (mp_digit)MP_DIGIT_BIT - D; - /* mask */ - mask = (((mp_digit)1) << D) - 1; + /* alias */ + tmpc = c->dp + (c->used - 1); - /* shift for lsb */ - shift = DIGIT_BIT - D; + /* carry */ + r = 0; + for (x = c->used - 1; x >= 0; x--) { + /* get the lower bits of this word in a temp */ + rr = *tmpc & mask; - /* alias */ - tmpc = c->dp + (c->used - 1); + /* shift the current word and mix in the carry bits from the previous word */ + *tmpc = (*tmpc >> D) | (r << shift); + --tmpc; - /* 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; + /* set the carry to the carry bits of the current word found above */ + r = rr; + } + } + mp_clamp(c); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_div_2d.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_div_3.c b/lib/hcrypto/libtommath/bn_mp_div_3.c index 78e2381b6..3a23fdff2 100644 --- a/lib/hcrypto/libtommath/bn_mp_div_3.c +++ b/lib/hcrypto/libtommath/bn_mp_div_3.c @@ -1,79 +1,63 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) { - mp_int q; - mp_word w, t; - mp_digit b; - int res, ix; + mp_int q; + mp_word w, t; + mp_digit b; + mp_err err; + int ix; - /* b = 2**DIGIT_BIT / 3 */ - b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3); + /* b = 2**MP_DIGIT_BIT / 3 */ + b = ((mp_word)1 << (mp_word)MP_DIGIT_BIT) / (mp_word)3; - if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { - return res; - } + if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { + return err; + } - 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]); + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix]; - if (w >= 3) { - /* multiply w by [1/3] */ - t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); + if (w >= 3u) { + /* multiply w by [1/3] */ + t = (w * (mp_word)b) >> (mp_word)MP_DIGIT_BIT; - /* now subtract 3 * [w/3] from w, to get the remainder */ - w -= t+t+t; + /* 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; - } + /* fixup the remainder as required since + * the optimization is not exact. + */ + while (w >= 3u) { + t += 1u; + w -= 3u; + } } else { - t = 0; + t = 0; } q.dp[ix] = (mp_digit)t; - } + } - /* [optional] store the remainder */ - if (d != NULL) { - *d = (mp_digit)w; - } + /* [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); + /* [optional] store the quotient */ + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); - return res; + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_div_3.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_div_d.c b/lib/hcrypto/libtommath/bn_mp_div_d.c index 7bd372c20..b9d718bb0 100644 --- a/lib/hcrypto/libtommath/bn_mp_div_d.c +++ b/lib/hcrypto/libtommath/bn_mp_div_d.c @@ -1,115 +1,84 @@ -#include +#include "tommath_private.h" #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; + /* quick outs */ + if ((b == 1u) || MP_IS_ZERO(a)) { + if (d != NULL) { + *d = 0; } - q.dp[ix] = (mp_digit)t; - } + if (c != NULL) { + return mp_copy(a, c); + } + return MP_OKAY; + } - if (d != NULL) { - *d = (mp_digit)w; - } + /* power of two ? */ + if ((b & (b - 1u)) == 0u) { + ix = 1; + while ((ix < MP_DIGIT_BIT) && (b != (((mp_digit)1)<dp[0] & (((mp_digit)1<<(mp_digit)ix) - 1uL); + } + if (c != NULL) { + return mp_div_2d(a, ix, c, NULL); + } + return MP_OKAY; + } - if (c != NULL) { - mp_clamp(&q); - mp_exch(&q, c); - } - mp_clear(&q); + /* three? */ + if (MP_HAS(MP_DIV_3) && (b == 3u)) { + return mp_div_3(a, c, d); + } - return res; + /* no easy answer [c'est la vie]. Just division */ + if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { + return err; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << (mp_word)MP_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] = t; + } + + if (d != NULL) { + *d = (mp_digit)w; + } + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_div_d.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2007/01/09 04:44:32 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c b/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c index 52373440d..83760eacc 100644 --- a/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c +++ b/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c @@ -1,43 +1,27 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* determines if a number is a valid DR modulus */ -int mp_dr_is_modulus(mp_int *a) +mp_bool mp_dr_is_modulus(const mp_int *a) { int ix; /* must be at least two digits */ if (a->used < 2) { - return 0; + return MP_NO; } /* 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; - } + if (a->dp[ix] != MP_MASK) { + return MP_NO; + } } - return 1; + return MP_YES; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_dr_is_modulus.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_dr_reduce.c b/lib/hcrypto/libtommath/bn_mp_dr_reduce.c index e60b5784f..ffc33a6b5 100644 --- a/lib/hcrypto/libtommath/bn_mp_dr_reduce.c +++ b/lib/hcrypto/libtommath/bn_mp_dr_reduce.c @@ -1,19 +1,7 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* reduce "x" in place modulo "n" using the Diminished Radix algorithm. * @@ -29,66 +17,62 @@ * * 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) +mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k) { - int err, i, m; - mp_word r; - mp_digit mu, *tmpx1, *tmpx2; + mp_err err; + int i, m; + mp_word r; + mp_digit mu, *tmpx1, *tmpx2; - /* m = digits in modulus */ - m = n->used; + /* 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; - } - } + /* 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 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; + /* 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; + /* alias for upper half of x, or x/B**m */ + tmpx2 = x->dp + m; - /* set carry to zero */ - mu = 0; + /* 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; + /* 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)); - } + mu = (mp_digit)(r >> ((mp_word)MP_DIGIT_BIT)); + } - /* set final carry */ - *tmpx1++ = mu; + /* set final carry */ + *tmpx1++ = mu; - /* zero words above m */ - for (i = m + 1; i < x->used; i++) { - *tmpx1++ = 0; - } + /* zero words above m */ + MP_ZERO_DIGITS(tmpx1, (x->used - m) - 1); - /* clamp, sub and return */ - mp_clamp (x); + /* 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; + /* 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) { + if ((err = s_mp_sub(x, n, x)) != MP_OKAY) { + return err; + } + goto top; + } + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_dr_reduce.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_dr_setup.c b/lib/hcrypto/libtommath/bn_mp_dr_setup.c index b7d5ed7c0..32d5f3890 100644 --- a/lib/hcrypto/libtommath/bn_mp_dr_setup.c +++ b/lib/hcrypto/libtommath/bn_mp_dr_setup.c @@ -1,32 +1,15 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* determines the setup value */ -void mp_dr_setup(mp_int *a, mp_digit *d) +void mp_dr_setup(const 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] + /* the casts are required if MP_DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. MP_DIGIT_BIT==31] */ - *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - - ((mp_word)a->dp[0])); + *d = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - (mp_word)a->dp[0]); } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_dr_setup.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_error_to_string.c b/lib/hcrypto/libtommath/bn_mp_error_to_string.c new file mode 100644 index 000000000..2e2adb0f2 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_error_to_string.c @@ -0,0 +1,27 @@ +#include "tommath_private.h" +#ifdef BN_MP_ERROR_TO_STRING_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* return a char * string for a given code */ +const char *mp_error_to_string(mp_err code) +{ + switch (code) { + case MP_OKAY: + return "Successful"; + case MP_ERR: + return "Unknown error"; + case MP_MEM: + return "Out of heap"; + case MP_VAL: + return "Value out of range"; + case MP_ITER: + return "Max. iterations reached"; + case MP_BUF: + return "Buffer overflow"; + default: + return "Invalid error code"; + } +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_exch.c b/lib/hcrypto/libtommath/bn_mp_exch.c index ee551bc3e..552094c6b 100644 --- a/lib/hcrypto/libtommath/bn_mp_exch.c +++ b/lib/hcrypto/libtommath/bn_mp_exch.c @@ -1,34 +1,17 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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) +void mp_exch(mp_int *a, mp_int *b) { - mp_int t; + mp_int t; - t = *a; - *a = *b; - *b = t; + t = *a; + *a = *b; + *b = t; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_exch.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_expt_d.c b/lib/hcrypto/libtommath/bn_mp_expt_d.c deleted file mode 100644 index 4bdc2d13a..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_expt_d.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_expt_u32.c b/lib/hcrypto/libtommath/bn_mp_expt_u32.c new file mode 100644 index 000000000..2ab67ba53 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_expt_u32.c @@ -0,0 +1,46 @@ +#include "tommath_private.h" +#ifdef BN_MP_EXPT_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* calculate c = a**b using a square-multiply algorithm */ +mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) +{ + mp_err err; + + mp_int g; + + if ((err = mp_init_copy(&g, a)) != MP_OKAY) { + return err; + } + + /* set initial result */ + mp_set(c, 1uL); + + while (b > 0u) { + /* if the bit is set multiply */ + if ((b & 1u) != 0u) { + if ((err = mp_mul(c, &g, c)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* square */ + if (b > 1u) { + if ((err = mp_sqr(&g, &g)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* shift to next bit */ + b >>= 1; + } + + err = MP_OKAY; + +LBL_ERR: + mp_clear(&g); + return err; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_exptmod.c b/lib/hcrypto/libtommath/bn_mp_exptmod.c index 56d7c11d2..5f811ebd8 100644 --- a/lib/hcrypto/libtommath/bn_mp_exptmod.c +++ b/lib/hcrypto/libtommath/bn_mp_exptmod.c @@ -1,112 +1,76 @@ -#include +#include "tommath_private.h" #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 - */ - +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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) +mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) { - int dr; + int dr; - /* modulus P must be positive */ - if (P->sign == MP_NEG) { - return MP_VAL; - } + /* 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; + /* if exponent X is negative we have to recurse */ + if (X->sign == MP_NEG) { + mp_int tmpG, tmpX; + mp_err 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; - } + if (!MP_HAS(MP_INVMOD)) { + return MP_VAL; + } - /* 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; - } + if ((err = mp_init_multi(&tmpG, &tmpX, NULL)) != MP_OKAY) { + 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 - } + /* first compute 1/G mod P */ + if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { + goto LBL_ERR; + } -/* 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 + /* now get |X| */ + if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { + goto LBL_ERR; + } -#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 + /* and now compute (1/G)**|X| instead of G**X [X < 0] */ + err = mp_exptmod(&tmpG, &tmpX, P, Y); +LBL_ERR: + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; + } -#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 + /* modified diminished radix reduction */ + if (MP_HAS(MP_REDUCE_IS_2K_L) && MP_HAS(MP_REDUCE_2K_L) && MP_HAS(S_MP_EXPTMOD) && + (mp_reduce_is_2k_l(P) == MP_YES)) { + return s_mp_exptmod(G, X, P, Y, 1); + } - /* 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 + /* is it a DR modulus? default to no */ + dr = (MP_HAS(MP_DR_IS_MODULUS) && (mp_dr_is_modulus(P) == MP_YES)) ? 1 : 0; + + /* if not, is it a unrestricted DR modulus? */ + if (MP_HAS(MP_REDUCE_IS_2K) && (dr == 0)) { + dr = (mp_reduce_is_2k(P) == MP_YES) ? 2 : 0; + } + + /* if the modulus is odd or dr != 0 use the montgomery method */ + if (MP_HAS(S_MP_EXPTMOD_FAST) && (MP_IS_ODD(P) || (dr != 0))) { + return s_mp_exptmod_fast(G, X, P, Y, dr); + } else if (MP_HAS(S_MP_EXPTMOD)) { + /* 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 - -/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_exptmod_fast.c b/lib/hcrypto/libtommath/bn_mp_exptmod_fast.c deleted file mode 100644 index 64fbe7fe2..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_exptmod_fast.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_exteuclid.c b/lib/hcrypto/libtommath/bn_mp_exteuclid.c index daf0c95ea..faf47ba6a 100644 --- a/lib/hcrypto/libtommath/bn_mp_exteuclid.c +++ b/lib/hcrypto/libtommath/bn_mp_exteuclid.c @@ -1,82 +1,73 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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_err mp_exteuclid(const mp_int *a, const 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; + mp_int u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp; + mp_err 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; } + mp_set(&u1, 1uL); + if ((err = mp_copy(a, &u3)) != MP_OKAY) goto LBL_ERR; /* initialize, (v1,v2,v3) = (0,1,b) */ - mp_set(&v2, 1); - if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; } + mp_set(&v2, 1uL); + if ((err = mp_copy(b, &v3)) != MP_OKAY) goto LBL_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; } + while (!MP_IS_ZERO(&v3)) { + /* q = u3/v3 */ + if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) goto LBL_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; } + /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ + if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) goto LBL_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; } + /* (u1,u2,u3) = (v1,v2,v3) */ + if ((err = mp_copy(&v1, &u1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&v2, &u2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&v3, &u3)) != MP_OKAY) goto LBL_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; } + /* (v1,v2,v3) = (t1,t2,t3) */ + if ((err = mp_copy(&t1, &v1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&t2, &v2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&t3, &v3)) != MP_OKAY) goto LBL_ERR; } /* make sure U3 >= 0 */ if (u3.sign == MP_NEG) { - mp_neg(&u1, &u1); - mp_neg(&u2, &u2); - mp_neg(&u3, &u3); + if ((err = mp_neg(&u1, &u1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_neg(&u2, &u2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_neg(&u3, &u3)) != MP_OKAY) goto LBL_ERR; } /* copy result out */ - if (U1 != NULL) { mp_exch(U1, &u1); } - if (U2 != NULL) { mp_exch(U2, &u2); } - if (U3 != NULL) { mp_exch(U3, &u3); } + 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); +LBL_ERR: + mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_exteuclid.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_find_prime.c b/lib/hcrypto/libtommath/bn_mp_find_prime.c deleted file mode 100644 index 29ef8747d..000000000 --- a/lib/hcrypto/libtommath/bn_mp_find_prime.c +++ /dev/null @@ -1,36 +0,0 @@ -/* TomsFastMath, a fast ISO C bignum library. - * - * This project is public domain and free for all purposes. - * - * Love Hornquist Astrand - */ -#include -#ifdef BN_MP_FIND_PRIME_C -int mp_find_prime(mp_int *a, int t) -{ - int res = MP_NO; - - /* valid value of t? */ - if (t <= 0 || t > PRIME_SIZE) { - return MP_VAL; - } - - if (mp_iseven(a)) - mp_add_d(a, 1, a); - - do { - if (mp_prime_is_prime(a, t, &res) != 0) { - res = MP_VAL; - break; - } - - if (res == MP_NO) { - mp_add_d(a, 2, a); - continue; - } - - } while (res != MP_YES); - - return res; -} -#endif diff --git a/lib/hcrypto/libtommath/bn_mp_fread.c b/lib/hcrypto/libtommath/bn_mp_fread.c index 52f7f32f0..52ea773e4 100644 --- a/lib/hcrypto/libtommath/bn_mp_fread.c +++ b/lib/hcrypto/libtommath/bn_mp_fread.c @@ -1,67 +1,60 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#ifndef MP_NO_FILE /* read a bigint from a file stream in ASCII */ -int mp_fread(mp_int *a, int radix, FILE *stream) +mp_err mp_fread(mp_int *a, int radix, FILE *stream) { - int err, ch, neg, y; - - /* clear a */ - mp_zero(a); + mp_err err; + mp_sign neg; /* if first digit is - then set negative */ - ch = fgetc(stream); - if (ch == '-') { + int ch = fgetc(stream); + if (ch == (int)'-') { 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; - } + /* no digits, return error */ + if (ch == EOF) { + return MP_ERR; + } + + /* clear a */ + mp_zero(a); + + do { + int y; + unsigned pos = (unsigned)(ch - (int)'('); + if (mp_s_rmap_reverse_sz < pos) { + break; } - if (y == radix) { + + y = (int)mp_s_rmap_reverse[pos]; + + if ((y == 0xff) || (y >= radix)) { break; } /* shift up and add */ - if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) { + if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) { return err; } - if ((err = mp_add_d(a, y, a)) != MP_OKAY) { + if ((err = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) { return err; } + } while ((ch = fgetc(stream)) != EOF); - ch = fgetc(stream); - } - if (mp_cmp_d(a, 0) != MP_EQ) { + if (a->used != 0) { a->sign = neg; } return MP_OKAY; } - #endif -/* $Source: /cvs/libtom/libtommath/bn_mp_fread.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_from_sbin.c b/lib/hcrypto/libtommath/bn_mp_from_sbin.c new file mode 100644 index 000000000..20e45971e --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_from_sbin.c @@ -0,0 +1,25 @@ +#include "tommath_private.h" +#ifdef BN_MP_FROM_SBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* read signed bin, big endian, first byte is 0==positive or 1==negative */ +mp_err mp_from_sbin(mp_int *a, const unsigned char *buf, size_t size) +{ + mp_err err; + + /* read magnitude */ + if ((err = mp_from_ubin(a, buf + 1, size - 1u)) != MP_OKAY) { + return err; + } + + /* first byte is 0 for positive, non-zero for negative */ + if (buf[0] == (unsigned char)0) { + a->sign = MP_ZPOS; + } else { + a->sign = MP_NEG; + } + + return MP_OKAY; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_from_ubin.c b/lib/hcrypto/libtommath/bn_mp_from_ubin.c new file mode 100644 index 000000000..7f73cbccd --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_from_ubin.c @@ -0,0 +1,39 @@ +#include "tommath_private.h" +#ifdef BN_MP_FROM_UBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reads a unsigned char array, assumes the msb is stored first [big endian] */ +mp_err mp_from_ubin(mp_int *a, const unsigned char *buf, size_t size) +{ + mp_err err; + + /* make sure there are at least two digits */ + if (a->alloc < 2) { + if ((err = mp_grow(a, 2)) != MP_OKAY) { + return err; + } + } + + /* zero the int */ + mp_zero(a); + + /* read the bytes in */ + while (size-- > 0u) { + if ((err = mp_mul_2d(a, 8, a)) != MP_OKAY) { + return err; + } + +#ifndef MP_8BIT + a->dp[0] |= *buf++; + a->used += 1; +#else + a->dp[0] = (*buf & MP_MASK); + a->dp[1] |= ((*buf++ >> 7) & 1u); + a->used += 2; +#endif + } + mp_clamp(a); + return MP_OKAY; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_fwrite.c b/lib/hcrypto/libtommath/bn_mp_fwrite.c index dc4529ba2..abe2e6717 100644 --- a/lib/hcrypto/libtommath/bn_mp_fwrite.c +++ b/lib/hcrypto/libtommath/bn_mp_fwrite.c @@ -1,52 +1,45 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ -int mp_fwrite(mp_int *a, int radix, FILE *stream) +#ifndef MP_NO_FILE +mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) { char *buf; - int err, len, x; + mp_err err; + int len; + size_t written; - if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) { - return err; + /* TODO: this function is not in this PR */ + if (MP_HAS(MP_RADIX_SIZE_OVERESTIMATE)) { + /* if ((err = mp_radix_size_overestimate(&t, base, &len)) != MP_OKAY) goto LBL_ERR; */ + } else { + if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) { + return err; + } } - buf = OPT_CAST(char) XMALLOC (len); + buf = (char *) MP_MALLOC((size_t)len); if (buf == NULL) { return MP_MEM; } - if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) { - XFREE (buf); - return err; + if ((err = mp_to_radix(a, buf, (size_t)len, &written, radix)) != MP_OKAY) { + goto LBL_ERR; } - for (x = 0; x < len; x++) { - if (fputc(buf[x], stream) == EOF) { - XFREE (buf); - return MP_VAL; - } + if (fwrite(buf, written, 1uL, stream) != 1uL) { + err = MP_ERR; + goto LBL_ERR; } + err = MP_OKAY; - XFREE (buf); - return MP_OKAY; + +LBL_ERR: + MP_FREE_BUFFER(buf, (size_t)len); + return err; } - #endif -/* $Source: /cvs/libtom/libtommath/bn_mp_fwrite.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_gcd.c b/lib/hcrypto/libtommath/bn_mp_gcd.c index 89795d564..53029baf3 100644 --- a/lib/hcrypto/libtommath/bn_mp_gcd.c +++ b/lib/hcrypto/libtommath/bn_mp_gcd.c @@ -1,105 +1,92 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* Greatest Common Divisor using the binary method */ -int mp_gcd (mp_int * a, mp_int * b, mp_int * c) +mp_err mp_gcd(const mp_int *a, const mp_int *b, mp_int *c) { - mp_int u, v; - int k, u_lsb, v_lsb, res; + mp_int u, v; + int k, u_lsb, v_lsb; + mp_err err; - /* 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); - } + /* either zero than gcd is the largest */ + if (MP_IS_ZERO(a)) { + return mp_abs(b, c); + } + if (MP_IS_ZERO(b)) { + 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; - } + /* get copies of a and b we can modify */ + if ((err = mp_init_copy(&u, a)) != MP_OKAY) { + return err; + } - if ((res = mp_init_copy (&v, b)) != MP_OKAY) { - goto LBL_U; - } + if ((err = 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; + /* 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); + /* B1. Find the common power of two for u and v */ + u_lsb = mp_cnt_lsb(&u); + v_lsb = mp_cnt_lsb(&v); + k = MP_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 (k > 0) { + /* divide the power of two out */ + if ((err = 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; - } - } + if ((err = 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; - } - } + /* divide any remaining factors of two out */ + if (u_lsb != k) { + if ((err = 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; - } - } + if (v_lsb != k) { + if ((err = 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); - } + while (!MP_IS_ZERO(&v)) { + /* 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; - } + /* subtract smallest from largest */ + if ((err = 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; - } - } + /* Divide out all factors of two */ + if ((err = 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; + /* multiply by 2**k which we divided out at the beginning */ + if ((err = mp_mul_2d(&u, k, c)) != MP_OKAY) { + goto LBL_V; + } + c->sign = MP_ZPOS; + err = MP_OKAY; +LBL_V: + mp_clear(&u); +LBL_U: + mp_clear(&v); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_gcd.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_get_double.c b/lib/hcrypto/libtommath/bn_mp_get_double.c new file mode 100644 index 000000000..c9b1b19f4 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_get_double.c @@ -0,0 +1,18 @@ +#include "tommath_private.h" +#ifdef BN_MP_GET_DOUBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +double mp_get_double(const mp_int *a) +{ + int i; + double d = 0.0, fac = 1.0; + for (i = 0; i < MP_DIGIT_BIT; ++i) { + fac *= 2.0; + } + for (i = a->used; i --> 0;) { + d = (d * fac) + (double)a->dp[i]; + } + return (a->sign == MP_NEG) ? -d : d; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_get_i32.c b/lib/hcrypto/libtommath/bn_mp_get_i32.c new file mode 100644 index 000000000..030b657a3 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_get_i32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_GET_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_i32, mp_get_mag_u32, int32_t, uint32_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_get_i64.c b/lib/hcrypto/libtommath/bn_mp_get_i64.c new file mode 100644 index 000000000..969c8d23c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_get_i64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_GET_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_i64, mp_get_mag_u64, int64_t, uint64_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_get_int.c b/lib/hcrypto/libtommath/bn_mp_get_int.c deleted file mode 100644 index e8e9b1d44..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_get_int.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_get_l.c b/lib/hcrypto/libtommath/bn_mp_get_l.c new file mode 100644 index 000000000..55d78ec03 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_get_l.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_GET_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_l, mp_get_mag_ul, long, unsigned long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_get_ll.c b/lib/hcrypto/libtommath/bn_mp_get_ll.c new file mode 100644 index 000000000..268753490 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_get_ll.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_GET_LL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_ll, mp_get_mag_ull, long long, unsigned long long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_get_mag_u32.c b/lib/hcrypto/libtommath/bn_mp_get_mag_u32.c new file mode 100644 index 000000000..d77189be6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_get_mag_u32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_GET_MAG_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_u32, uint32_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_get_mag_u64.c b/lib/hcrypto/libtommath/bn_mp_get_mag_u64.c new file mode 100644 index 000000000..36dd73f62 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_get_mag_u64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_GET_MAG_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_u64, uint64_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_get_mag_ul.c b/lib/hcrypto/libtommath/bn_mp_get_mag_ul.c new file mode 100644 index 000000000..e8819aef6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_get_mag_ul.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_GET_MAG_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_ul, unsigned long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_get_mag_ull.c b/lib/hcrypto/libtommath/bn_mp_get_mag_ull.c new file mode 100644 index 000000000..63a27412c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_get_mag_ull.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_GET_MAG_ULL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_ull, unsigned long long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_grow.c b/lib/hcrypto/libtommath/bn_mp_grow.c index cf2b949b2..9e904c547 100644 --- a/lib/hcrypto/libtommath/bn_mp_grow.c +++ b/lib/hcrypto/libtommath/bn_mp_grow.c @@ -1,57 +1,38 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* grow as required */ -int mp_grow (mp_int * a, int size) +mp_err mp_grow(mp_int *a, int size) { - int i; - mp_digit *tmp; + 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); + /* if the alloc size is smaller alloc more ram */ + if (a->alloc < size) { + /* 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 = (mp_digit *) MP_REALLOC(a->dp, + (size_t)a->alloc * sizeof(mp_digit), + (size_t)size * sizeof(mp_digit)); + if (tmp == NULL) { + /* reallocation failed but "a" is still valid [can be freed] */ + return MP_MEM; + } - /* 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; - /* 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; + /* zero excess digits */ + i = a->alloc; + a->alloc = size; + MP_ZERO_DIGITS(a->dp + i, a->alloc - i); + } + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_grow.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_incr.c b/lib/hcrypto/libtommath/bn_mp_incr.c new file mode 100644 index 000000000..7695ac73c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_incr.c @@ -0,0 +1,30 @@ +#include "tommath_private.h" +#ifdef BN_MP_INCR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Increment "a" by one like "a++". Changes input! */ +mp_err mp_incr(mp_int *a) +{ + if (MP_IS_ZERO(a)) { + mp_set(a,1uL); + return MP_OKAY; + } else if (a->sign == MP_NEG) { + mp_err err; + a->sign = MP_ZPOS; + if ((err = mp_decr(a)) != MP_OKAY) { + return err; + } + /* There is no -0 in LTM */ + if (!MP_IS_ZERO(a)) { + a->sign = MP_NEG; + } + return MP_OKAY; + } else if (a->dp[0] < MP_DIGIT_MAX) { + a->dp[0]++; + return MP_OKAY; + } else { + return mp_add_d(a, 1uL,a); + } +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_init.c b/lib/hcrypto/libtommath/bn_mp_init.c index 8be27f569..2eb792409 100644 --- a/lib/hcrypto/libtommath/bn_mp_init.c +++ b/lib/hcrypto/libtommath/bn_mp_init.c @@ -1,46 +1,23 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* init a new mp_int */ -int mp_init (mp_int * a) +mp_err mp_init(mp_int *a) { - int i; + /* allocate memory required and clear it */ + a->dp = (mp_digit *) MP_CALLOC((size_t)MP_PREC, sizeof(mp_digit)); + if (a->dp == NULL) { + return MP_MEM; + } - /* 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 used to zero, allocated digits to the default precision + * and sign to positive */ + a->used = 0; + a->alloc = MP_PREC; + a->sign = MP_ZPOS; - /* 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; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_init.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_copy.c b/lib/hcrypto/libtommath/bn_mp_init_copy.c index 0160811af..1888203d2 100644 --- a/lib/hcrypto/libtommath/bn_mp_init_copy.c +++ b/lib/hcrypto/libtommath/bn_mp_init_copy.c @@ -1,32 +1,21 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* creates "a" then copies b into it */ -int mp_init_copy (mp_int * a, mp_int * b) +mp_err mp_init_copy(mp_int *a, const mp_int *b) { - int res; + mp_err err; - if ((res = mp_init (a)) != MP_OKAY) { - return res; - } - return mp_copy (b, a); + if ((err = mp_init_size(a, b->used)) != MP_OKAY) { + return err; + } + + if ((err = mp_copy(b, a)) != MP_OKAY) { + mp_clear(a); + } + + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_init_copy.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_i32.c b/lib/hcrypto/libtommath/bn_mp_init_i32.c new file mode 100644 index 000000000..bc4de8d50 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_i32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_INIT_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_i32, mp_set_i32, int32_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_init_i64.c b/lib/hcrypto/libtommath/bn_mp_init_i64.c new file mode 100644 index 000000000..2fa1516eb --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_i64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_INIT_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_i64, mp_set_i64, int64_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_init_l.c b/lib/hcrypto/libtommath/bn_mp_init_l.c new file mode 100644 index 000000000..bc380b539 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_l.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_INIT_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_l, mp_set_l, long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_init_ll.c b/lib/hcrypto/libtommath/bn_mp_init_ll.c new file mode 100644 index 000000000..dc7c4a44e --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_ll.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_INIT_LL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_ll, mp_set_ll, long long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_init_multi.c b/lib/hcrypto/libtommath/bn_mp_init_multi.c index 56e860276..d8390b5a0 100644 --- a/lib/hcrypto/libtommath/bn_mp_init_multi.c +++ b/lib/hcrypto/libtommath/bn_mp_init_multi.c @@ -1,59 +1,41 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + #include -int mp_init_multi(mp_int *mp, ...) +mp_err 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; + mp_err err = 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; + 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. */ + /* now start cleaning up */ + cur_arg = mp; + va_start(clean_args, mp); + while (n-- != 0) { + mp_clear(cur_arg); + cur_arg = va_arg(clean_args, mp_int *); + } + va_end(clean_args); + err = MP_MEM; + break; + } + n++; + cur_arg = va_arg(args, mp_int *); + } + va_end(args); + return err; /* Assumed ok, if error flagged above. */ } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_init_multi.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_set.c b/lib/hcrypto/libtommath/bn_mp_init_set.c index 34edad92f..5068f2bf6 100644 --- a/lib/hcrypto/libtommath/bn_mp_init_set.c +++ b/lib/hcrypto/libtommath/bn_mp_init_set.c @@ -1,32 +1,16 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* initialize and set a digit */ -int mp_init_set (mp_int * a, mp_digit b) +mp_err 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; + mp_err err; + if ((err = mp_init(a)) != MP_OKAY) { + return err; + } + mp_set(a, b); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_init_set.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_set_int.c b/lib/hcrypto/libtommath/bn_mp_init_set_int.c deleted file mode 100644 index 5c5599315..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_init_set_int.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_size.c b/lib/hcrypto/libtommath/bn_mp_init_size.c index 9578ac754..d62268721 100644 --- a/lib/hcrypto/libtommath/bn_mp_init_size.c +++ b/lib/hcrypto/libtommath/bn_mp_init_size.c @@ -1,48 +1,24 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* init an mp_init for a given size */ -int mp_init_size (mp_int * a, int size) +mp_err mp_init_size(mp_int *a, int size) { - int x; + size = MP_MAX(MP_MIN_PREC, size); - /* pad size so there are always extra digits */ - size += (MP_PREC * 2) - (size % MP_PREC); + /* alloc mem */ + a->dp = (mp_digit *) MP_CALLOC((size_t)size, sizeof(mp_digit)); + if (a->dp == NULL) { + return MP_MEM; + } - /* 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; - /* 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; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_init_size.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_init_u32.c b/lib/hcrypto/libtommath/bn_mp_init_u32.c new file mode 100644 index 000000000..015d89b90 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_u32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_INIT_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_u32, mp_set_u32, uint32_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_init_u64.c b/lib/hcrypto/libtommath/bn_mp_init_u64.c new file mode 100644 index 000000000..2b35f7ef8 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_u64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_INIT_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_u64, mp_set_u64, uint64_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_init_ul.c b/lib/hcrypto/libtommath/bn_mp_init_ul.c new file mode 100644 index 000000000..5164f7287 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_ul.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_INIT_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_ul, mp_set_ul, unsigned long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_init_ull.c b/lib/hcrypto/libtommath/bn_mp_init_ull.c new file mode 100644 index 000000000..84110c002 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_init_ull.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_INIT_ULL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_ull, mp_set_ull, unsigned long long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_invmod.c b/lib/hcrypto/libtommath/bn_mp_invmod.c index ac1a95231..7b35a2431 100644 --- a/lib/hcrypto/libtommath/bn_mp_invmod.c +++ b/lib/hcrypto/libtommath/bn_mp_invmod.c @@ -1,43 +1,23 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* hac 14.61, pp608 */ -int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) { - /* b cannot be negative */ - if (b->sign == MP_NEG || mp_iszero(b) == 1) { - return MP_VAL; - } + /* b cannot be negative and has to be >1 */ + if ((b->sign == MP_NEG) || (mp_cmp_d(b, 1uL) != MP_GT)) { + 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 + /* if the modulus is odd we can use a faster routine instead */ + if (MP_HAS(S_MP_INVMOD_FAST) && MP_IS_ODD(b)) { + return s_mp_invmod_fast(a, b, c); + } -#ifdef BN_MP_INVMOD_SLOW_C - return mp_invmod_slow(a, b, c); -#else - return MP_VAL; -#endif + return MP_HAS(S_MP_INVMOD_SLOW) + ? s_mp_invmod_slow(a, b, c) + : MP_VAL; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_invmod.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_invmod_slow.c b/lib/hcrypto/libtommath/bn_mp_invmod_slow.c deleted file mode 100644 index 4ec487efa..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_invmod_slow.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_is_square.c b/lib/hcrypto/libtommath/bn_mp_is_square.c index 027fcd2f5..69e77a21a 100644 --- a/lib/hcrypto/libtommath/bn_mp_is_square.c +++ b/lib/hcrypto/libtommath/bn_mp_is_square.c @@ -1,109 +1,93 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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 + 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 + 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) +mp_err mp_is_square(const mp_int *arg, mp_bool *ret) { - int res; - mp_digit c; - mp_int t; - unsigned long r; + mp_err err; + mp_digit c; + mp_int t; + unsigned long r; - /* Default to Non-square :) */ - *ret = MP_NO; + /* Default to Non-square :) */ + *ret = MP_NO; - if (arg->sign == MP_NEG) { - return MP_VAL; - } + if (arg->sign == MP_NEG) { + return MP_VAL; + } - /* digits used? (TSD) */ - if (arg->used == 0) { - return MP_OKAY; - } + if (MP_IS_ZERO(arg)) { + 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; - } + /* First check mod 128 (suppose that MP_DIGIT_BIT is at least 7) */ + if (rem_128[127u & arg->dp[0]] == (char)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; - } + /* Next check mod 105 (3*5*7) */ + if ((err = mp_mod_d(arg, 105uL, &c)) != MP_OKAY) { + return err; + } + if (rem_105[c] == (char)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; + if ((err = mp_init_u32(&t, 11u*13u*17u*19u*23u*29u*31u)) != MP_OKAY) { + return err; + } + if ((err = mp_mod(arg, &t, &t)) != MP_OKAY) { + goto LBL_ERR; + } + r = mp_get_u32(&t); + /* Check for other prime modules, note it's not an ERROR but we must + * free "t" so the easiest way is to goto LBL_ERR. We know that err + * is already equal to MP_OKAY from the mp_mod call + */ + if (((1uL<<(r%11uL)) & 0x5C4uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%13uL)) & 0x9E4uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%17uL)) & 0x5CE8uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%19uL)) & 0x4F50CuL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%23uL)) & 0x7ACCA0uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%29uL)) & 0xC2EDD0CuL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%31uL)) & 0x6DE2B848uL) != 0uL) goto LBL_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; - } + /* Final check - is sqr(sqrt(arg)) == arg ? */ + if ((err = mp_sqrt(arg, &t)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_sqr(&t, &t)) != MP_OKAY) { + goto LBL_ERR; + } - *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO; -ERR:mp_clear(&t); - return res; + *ret = (mp_cmp_mag(&t, arg) == MP_EQ) ? MP_YES : MP_NO; +LBL_ERR: + mp_clear(&t); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_is_square.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_iseven.c b/lib/hcrypto/libtommath/bn_mp_iseven.c new file mode 100644 index 000000000..5cb962284 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_iseven.c @@ -0,0 +1,10 @@ +#include "tommath_private.h" +#ifdef BN_MP_ISEVEN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_bool mp_iseven(const mp_int *a) +{ + return MP_IS_EVEN(a) ? MP_YES : MP_NO; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_isodd.c b/lib/hcrypto/libtommath/bn_mp_isodd.c new file mode 100644 index 000000000..bf17646d7 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_isodd.c @@ -0,0 +1,10 @@ +#include "tommath_private.h" +#ifdef BN_MP_ISODD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_bool mp_isodd(const mp_int *a) +{ + return MP_IS_ODD(a) ? MP_YES : MP_NO; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_jacobi.c b/lib/hcrypto/libtommath/bn_mp_jacobi.c deleted file mode 100644 index 91cfeeade..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_jacobi.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c b/lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c deleted file mode 100644 index 72a2319c0..000000000 --- a/lib/hcrypto/libtommath/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))<used == 1) && (a->dp[0] == 1u)) { + *c = 1; + } else { + *c = 0; + } + return MP_OKAY; + } + + if (MP_IS_EVEN(a) && MP_IS_EVEN(p)) { + *c = 0; + return MP_OKAY; + } + + if ((err = mp_init_copy(&a1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_init_copy(&p1, p)) != MP_OKAY) { + goto LBL_KRON_0; + } + + v = mp_cnt_lsb(&p1); + if ((err = mp_div_2d(&p1, v, &p1, NULL)) != MP_OKAY) { + goto LBL_KRON_1; + } + + if ((v & 1) == 0) { + k = 1; + } else { + k = table[a->dp[0] & 7u]; + } + + if (p1.sign == MP_NEG) { + p1.sign = MP_ZPOS; + if (a1.sign == MP_NEG) { + k = -k; + } + } + + if ((err = mp_init(&r)) != MP_OKAY) { + goto LBL_KRON_1; + } + + for (;;) { + if (MP_IS_ZERO(&a1)) { + if (mp_cmp_d(&p1, 1uL) == MP_EQ) { + *c = k; + goto LBL_KRON; + } else { + *c = 0; + goto LBL_KRON; + } + } + + v = mp_cnt_lsb(&a1); + if ((err = mp_div_2d(&a1, v, &a1, NULL)) != MP_OKAY) { + goto LBL_KRON; + } + + if ((v & 1) == 1) { + k = k * table[p1.dp[0] & 7u]; + } + + if (a1.sign == MP_NEG) { + /* + * Compute k = (-1)^((a1)*(p1-1)/4) * k + * a1.dp[0] + 1 cannot overflow because the MSB + * of the type mp_digit is not set by definition + */ + if (((a1.dp[0] + 1u) & p1.dp[0] & 2u) != 0u) { + k = -k; + } + } else { + /* compute k = (-1)^((a1-1)*(p1-1)/4) * k */ + if ((a1.dp[0] & p1.dp[0] & 2u) != 0u) { + k = -k; + } + } + + if ((err = mp_copy(&a1, &r)) != MP_OKAY) { + goto LBL_KRON; + } + r.sign = MP_ZPOS; + if ((err = mp_mod(&p1, &r, &a1)) != MP_OKAY) { + goto LBL_KRON; + } + if ((err = mp_copy(&r, &p1)) != MP_OKAY) { + goto LBL_KRON; + } + } + +LBL_KRON: + mp_clear(&r); +LBL_KRON_1: + mp_clear(&p1); +LBL_KRON_0: + mp_clear(&a1); + + return err; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_lcm.c b/lib/hcrypto/libtommath/bn_mp_lcm.c index 781eef565..c32b269e6 100644 --- a/lib/hcrypto/libtommath/bn_mp_lcm.c +++ b/lib/hcrypto/libtommath/bn_mp_lcm.c @@ -1,60 +1,44 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* computes least common multiple as |a*b|/(a, b) */ -int mp_lcm (mp_int * a, mp_int * b, mp_int * c) +mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) { - int res; - mp_int t1, t2; + mp_err err; + mp_int t1, t2; - if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) { - return res; - } + if ((err = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) { + return err; + } - /* t1 = get the GCD of the two inputs */ - if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) { - goto LBL_T; - } + /* t1 = get the GCD of the two inputs */ + if ((err = 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); - } + /* 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 ((err = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + err = mp_mul(b, &t2, c); + } else { + /* store quotient in t2 such that t2 * a is the LCM */ + if ((err = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + err = mp_mul(a, &t2, c); + } - /* fix the sign to positive */ - c->sign = MP_ZPOS; + /* fix the sign to positive */ + c->sign = MP_ZPOS; LBL_T: - mp_clear_multi (&t1, &t2, NULL); - return res; + mp_clear_multi(&t1, &t2, NULL); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_lcm.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_log_u32.c b/lib/hcrypto/libtommath/bn_mp_log_u32.c new file mode 100644 index 000000000..f7bca01de --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_log_u32.c @@ -0,0 +1,180 @@ +#include "tommath_private.h" +#ifdef BN_MP_LOG_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Compute log_{base}(a) */ +static mp_word s_pow(mp_word base, mp_word exponent) +{ + mp_word result = 1uLL; + while (exponent != 0u) { + if ((exponent & 1u) == 1u) { + result *= base; + } + exponent >>= 1; + base *= base; + } + + return result; +} + +static mp_digit s_digit_ilogb(mp_digit base, mp_digit n) +{ + mp_word bracket_low = 1uLL, bracket_mid, bracket_high, N; + mp_digit ret, high = 1uL, low = 0uL, mid; + + if (n < base) { + return 0uL; + } + if (n == base) { + return 1uL; + } + + bracket_high = (mp_word) base ; + N = (mp_word) n; + + while (bracket_high < N) { + low = high; + bracket_low = bracket_high; + high <<= 1; + bracket_high *= bracket_high; + } + + while (((mp_digit)(high - low)) > 1uL) { + mid = (low + high) >> 1; + bracket_mid = bracket_low * s_pow(base, (mp_word)(mid - low)); + + if (N < bracket_mid) { + high = mid ; + bracket_high = bracket_mid ; + } + if (N > bracket_mid) { + low = mid ; + bracket_low = bracket_mid ; + } + if (N == bracket_mid) { + return (mp_digit) mid; + } + } + + if (bracket_high == N) { + ret = high; + } else { + ret = low; + } + + return ret; +} + +/* TODO: output could be "int" because the output of mp_radix_size is int, too, + as is the output of mp_bitcount. + With the same problem: max size is INT_MAX * MP_DIGIT not INT_MAX only! +*/ +mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c) +{ + mp_err err; + mp_ord cmp; + uint32_t high, low, mid; + mp_int bracket_low, bracket_high, bracket_mid, t, bi_base; + + err = MP_OKAY; + + if (a->sign == MP_NEG) { + return MP_VAL; + } + + if (MP_IS_ZERO(a)) { + return MP_VAL; + } + + if (base < 2u) { + return MP_VAL; + } + + /* A small shortcut for bases that are powers of two. */ + if ((base & (base - 1u)) == 0u) { + int y, bit_count; + for (y=0; (y < 7) && ((base & 1u) == 0u); y++) { + base >>= 1; + } + bit_count = mp_count_bits(a) - 1; + *c = (uint32_t)(bit_count/y); + return MP_OKAY; + } + + if (a->used == 1) { + *c = (uint32_t)s_digit_ilogb(base, a->dp[0]); + return err; + } + + cmp = mp_cmp_d(a, base); + if ((cmp == MP_LT) || (cmp == MP_EQ)) { + *c = cmp == MP_EQ; + return err; + } + + if ((err = + mp_init_multi(&bracket_low, &bracket_high, + &bracket_mid, &t, &bi_base, NULL)) != MP_OKAY) { + return err; + } + + low = 0u; + mp_set(&bracket_low, 1uL); + high = 1u; + + mp_set(&bracket_high, base); + + /* + A kind of Giant-step/baby-step algorithm. + Idea shamelessly stolen from https://programmingpraxis.com/2010/05/07/integer-logarithms/2/ + The effect is asymptotic, hence needs benchmarks to test if the Giant-step should be skipped + for small n. + */ + while (mp_cmp(&bracket_high, a) == MP_LT) { + low = high; + if ((err = mp_copy(&bracket_high, &bracket_low)) != MP_OKAY) { + goto LBL_ERR; + } + high <<= 1; + if ((err = mp_sqr(&bracket_high, &bracket_high)) != MP_OKAY) { + goto LBL_ERR; + } + } + mp_set(&bi_base, base); + + while ((high - low) > 1u) { + mid = (high + low) >> 1; + + if ((err = mp_expt_u32(&bi_base, (uint32_t)(mid - low), &t)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_mul(&bracket_low, &t, &bracket_mid)) != MP_OKAY) { + goto LBL_ERR; + } + cmp = mp_cmp(a, &bracket_mid); + if (cmp == MP_LT) { + high = mid; + mp_exch(&bracket_mid, &bracket_high); + } + if (cmp == MP_GT) { + low = mid; + mp_exch(&bracket_mid, &bracket_low); + } + if (cmp == MP_EQ) { + *c = mid; + goto LBL_END; + } + } + + *c = (mp_cmp(&bracket_high, a) == MP_EQ) ? high : low; + +LBL_END: +LBL_ERR: + mp_clear_multi(&bracket_low, &bracket_high, &bracket_mid, + &t, &bi_base, NULL); + return err; +} + + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_lshd.c b/lib/hcrypto/libtommath/bn_mp_lshd.c index f118cf1ae..82345809c 100644 --- a/lib/hcrypto/libtommath/bn_mp_lshd.c +++ b/lib/hcrypto/libtommath/bn_mp_lshd.c @@ -1,67 +1,51 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* shift left a certain amount of digits */ -int mp_lshd (mp_int * a, int b) +mp_err mp_lshd(mp_int *a, int b) { - int x, res; + int x; + mp_err err; + mp_digit *top, *bottom; - /* if its less than zero return */ - if (b <= 0) { - return MP_OKAY; - } + /* if its less than zero return */ + if (b <= 0) { + return MP_OKAY; + } + /* no need to shift 0 around */ + if (MP_IS_ZERO(a)) { + 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; - } - } + /* grow to fit the new digits */ + if (a->alloc < (a->used + b)) { + if ((err = mp_grow(a, a->used + b)) != MP_OKAY) { + return err; + } + } - { - register mp_digit *top, *bottom; + /* increment the used by the shift amount then copy upwards */ + a->used += b; - /* increment the used by the shift amount then copy upwards */ - a->used += b; + /* top */ + top = a->dp + a->used - 1; - /* top */ - top = a->dp + a->used - 1; + /* base */ + bottom = (a->dp + a->used - 1) - b; - /* 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--) { + /* 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; + /* zero the lower digits */ + MP_ZERO_DIGITS(a->dp, b); + + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_lshd.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mod.c b/lib/hcrypto/libtommath/bn_mp_mod.c index 757335aeb..8fbfe08dc 100644 --- a/lib/hcrypto/libtommath/bn_mp_mod.c +++ b/lib/hcrypto/libtommath/bn_mp_mod.c @@ -1,48 +1,31 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* c = a mod b, 0 <= c < b if b > 0, b < c <= 0 if b < 0 */ -int -mp_mod (mp_int * a, mp_int * b, mp_int * c) +mp_err mp_mod(const mp_int *a, const mp_int *b, mp_int *c) { - mp_int t; - int res; + mp_int t; + mp_err err; - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } + if ((err = mp_init_size(&t, b->used)) != MP_OKAY) { + return err; + } - if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } + if ((err = mp_div(a, b, NULL, &t)) != MP_OKAY) { + goto LBL_ERR; + } - if (mp_iszero(&t) || t.sign == b->sign) { - res = MP_OKAY; - mp_exch (&t, c); - } else { - res = mp_add (b, &t, c); - } + if (MP_IS_ZERO(&t) || (t.sign == b->sign)) { + err = MP_OKAY; + mp_exch(&t, c); + } else { + err = mp_add(b, &t, c); + } - mp_clear (&t); - return res; +LBL_ERR: + mp_clear(&t); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_mod.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mod_2d.c b/lib/hcrypto/libtommath/bn_mp_mod_2d.c index e194a0687..5bf57a1a3 100644 --- a/lib/hcrypto/libtommath/bn_mp_mod_2d.c +++ b/lib/hcrypto/libtommath/bn_mp_mod_2d.c @@ -1,55 +1,38 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* calc a value mod 2**b */ -int -mp_mod_2d (mp_int * a, int b, mp_int * c) +mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c) { - int x, res; + int x; + mp_err err; - /* if b is <= 0 then zero the int */ - if (b <= 0) { - mp_zero (c); - return MP_OKAY; - } + /* 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; - } + /* if the modulus is larger than the value than return */ + if (b >= (a->used * MP_DIGIT_BIT)) { + return mp_copy(a, c); + } - /* copy */ - if ((res = mp_copy (a, c)) != MP_OKAY) { - return res; - } + /* copy */ + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } - /* 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; + /* zero digits above the last digit of the modulus */ + x = (b / MP_DIGIT_BIT) + (((b % MP_DIGIT_BIT) == 0) ? 0 : 1); + MP_ZERO_DIGITS(c->dp + x, c->used - x); + + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / MP_DIGIT_BIT] &= + ((mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT)) - (mp_digit)1; + mp_clamp(c); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_mod_2d.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mod_d.c b/lib/hcrypto/libtommath/bn_mp_mod_d.c index 9ca37e673..0b6c12a9e 100644 --- a/lib/hcrypto/libtommath/bn_mp_mod_d.c +++ b/lib/hcrypto/libtommath/bn_mp_mod_d.c @@ -1,27 +1,10 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ -int -mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) +mp_err mp_mod_d(const mp_int *a, mp_digit b, mp_digit *c) { - return mp_div_d(a, b, NULL, c); + return mp_div_d(a, b, NULL, c); } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_mod_d.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c b/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c index c669fe0ec..837978925 100644 --- a/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c +++ b/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c @@ -1,19 +1,7 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* * shifts with subtractions when the result is greater than b. @@ -21,39 +9,36 @@ * 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) +mp_err mp_montgomery_calc_normalization(mp_int *a, const mp_int *b) { - int x, bits, res; + int x, bits; + mp_err err; - /* how many bits of last digit does b use */ - bits = mp_count_bits (b) % DIGIT_BIT; + /* how many bits of last digit does b use */ + bits = mp_count_bits(b) % MP_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; + if (b->used > 1) { + if ((err = mp_2expt(a, ((b->used - 1) * MP_DIGIT_BIT) + bits - 1)) != MP_OKAY) { + return err; } - } - } + } else { + mp_set(a, 1uL); + bits = 1; + } - return MP_OKAY; + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int)MP_DIGIT_BIT; x++) { + if ((err = mp_mul_2(a, a)) != MP_OKAY) { + return err; + } + if (mp_cmp_mag(a, b) != MP_LT) { + if ((err = s_mp_sub(a, b, a)) != MP_OKAY) { + return err; + } + } + } + + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_calc_normalization.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c b/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c index b76509051..ffe8341ee 100644 --- a/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c +++ b/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c @@ -1,118 +1,102 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* computes xR**-1 == x (mod N) via Montgomery Reduction */ -int -mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +mp_err mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho) { - int ix, res, digs; - mp_digit mu; + int ix, digs; + mp_err err; + 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); - } + /* 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) && + (x->used <= MP_WARRAY) && + (n->used < MP_MAXFAST)) { + return s_mp_montgomery_reduce_fast(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)); + /* grow the input as required */ + if (x->alloc < digs) { + if ((err = mp_grow(x, digs)) != MP_OKAY) { + return err; } - /* At this point the ix'th digit of x should be zero */ + } + 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 */ + { + int iy; + mp_digit *tmpn, *tmpx, u; + 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)MP_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; + /* propagate carries upwards as required*/ + while (u != 0u) { + *tmpx += u; + u = *tmpx >> MP_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. - */ + /* 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); + /* 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); - } + /* 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; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_reduce.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c b/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c index f08274936..39f6e9d24 100644 --- a/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c +++ b/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c @@ -1,59 +1,42 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* setups the montgomery reduction stuff */ -int -mp_montgomery_setup (mp_int * n, mp_digit * rho) +mp_err mp_montgomery_setup(const mp_int *n, mp_digit *rho) { - mp_digit x, b; + 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]; + /* 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; - } + if ((b & 1u) == 0u) { + 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 */ + x = (((b + 2u) & 4u) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2u - (b * x); /* here x*a==1 mod 2**8 */ #if !defined(MP_8BIT) - x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2u - (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 */ + x *= 2u - (b * x); /* here x*a==1 mod 2**32 */ #endif #ifdef MP_64BIT - x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + x *= 2u - (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; + /* rho = -1/m mod b */ + *rho = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - x) & MP_MASK; - return MP_OKAY; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_setup.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mul.c b/lib/hcrypto/libtommath/bn_mp_mul.c index 816e7b2f0..561913a5e 100644 --- a/lib/hcrypto/libtommath/bn_mp_mul.c +++ b/lib/hcrypto/libtommath/bn_mp_mul.c @@ -1,66 +1,52 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* high level multiplication (handles sign) */ -int mp_mul (mp_int * a, mp_int * b, mp_int * c) +mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c) { - int res, neg; - neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + mp_err err; + int min_len = MP_MIN(a->used, b->used), + max_len = MP_MAX(a->used, b->used), + digs = a->used + b->used + 1; + mp_sign 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; + if (MP_HAS(S_MP_BALANCE_MUL) && + /* Check sizes. The smaller one needs to be larger than the Karatsuba cut-off. + * The bigger one needs to be at least about one MP_KARATSUBA_MUL_CUTOFF bigger + * to make some sense, but it depends on architecture, OS, position of the + * stars... so YMMV. + * Using it to cut the input into slices small enough for fast_s_mp_mul_digs + * was actually slower on the author's machine, but YMMV. + */ + (min_len >= MP_KARATSUBA_MUL_CUTOFF) && + ((max_len / 2) >= MP_KARATSUBA_MUL_CUTOFF) && + /* Not much effect was observed below a ratio of 1:2, but again: YMMV. */ + (max_len >= (2 * min_len))) { + err = s_mp_balance_mul(a,b,c); + } else if (MP_HAS(S_MP_TOOM_MUL) && + (min_len >= MP_TOOM_MUL_CUTOFF)) { + err = s_mp_toom_mul(a, b, c); + } else if (MP_HAS(S_MP_KARATSUBA_MUL) && + (min_len >= MP_KARATSUBA_MUL_CUTOFF)) { + err = s_mp_karatsuba_mul(a, b, c); + } else if (MP_HAS(S_MP_MUL_DIGS_FAST) && + /* 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 + */ + (digs < MP_WARRAY) && + (min_len <= MP_MAXFAST)) { + err = s_mp_mul_digs_fast(a, b, c, digs); + } else if (MP_HAS(S_MP_MUL_DIGS)) { + err = s_mp_mul_digs(a, b, c, digs); + } else { + err = MP_VAL; + } + c->sign = (c->used > 0) ? neg : MP_ZPOS; + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_mul.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mul_2.c b/lib/hcrypto/libtommath/bn_mp_mul_2.c index f90654832..bc0691a0d 100644 --- a/lib/hcrypto/libtommath/bn_mp_mul_2.c +++ b/lib/hcrypto/libtommath/bn_mp_mul_2.c @@ -1,82 +1,64 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* b = a*2 */ -int mp_mul_2(mp_int * a, mp_int * b) +mp_err mp_mul_2(const mp_int *a, mp_int *b) { - int x, res, oldused; + int x, oldused; + mp_err err; - /* grow to accomodate result */ - if (b->alloc < a->used + 1) { - if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { - return res; - } - } + /* grow to accomodate result */ + if (b->alloc < (a->used + 1)) { + if ((err = mp_grow(b, a->used + 1)) != MP_OKAY) { + return err; + } + } - oldused = b->used; - b->used = a->used; + oldused = b->used; + b->used = a->used; - { - register mp_digit r, rr, *tmpa, *tmpb; + { + mp_digit r, rr, *tmpa, *tmpb; - /* alias for source */ - tmpa = a->dp; + /* alias for source */ + tmpa = a->dp; - /* alias for dest */ - tmpb = b->dp; + /* alias for dest */ + tmpb = b->dp; - /* carry */ - r = 0; - for (x = 0; x < a->used; x++) { + /* 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 + /* get what will be the *next* carry bit from the + * MSB of the current digit + */ + rr = *tmpa >> (mp_digit)(MP_DIGIT_BIT - 1); + + /* now shift up this digit, add in the carry [from the previous] */ + *tmpb++ = ((*tmpa++ << 1uL) | r) & MP_MASK; + + /* copy the carry that would be from the source + * digit into the next iteration + */ + r = rr; + } + + /* new leading digit? */ + if (r != 0u) { + /* 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 */ - 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; + MP_ZERO_DIGITS(b->dp + b->used, oldused - b->used); + } + b->sign = a->sign; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mul_2d.c b/lib/hcrypto/libtommath/bn_mp_mul_2d.c index d023b382c..87354de20 100644 --- a/lib/hcrypto/libtommath/bn_mp_mul_2d.c +++ b/lib/hcrypto/libtommath/bn_mp_mul_2d.c @@ -1,85 +1,69 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* shift left by a certain bit count */ -int mp_mul_2d (mp_int * a, int b, mp_int * c) +mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) { - mp_digit d; - int res; + mp_digit d; + mp_err err; - /* copy */ - if (a != c) { - if ((res = mp_copy (a, c)) != MP_OKAY) { - return res; - } - } + /* copy */ + if (a != c) { + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + } - 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; - } - } + if (c->alloc < (c->used + (b / MP_DIGIT_BIT) + 1)) { + if ((err = mp_grow(c, c->used + (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) { + return err; + } + } - /* 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 by as many digits in the bit count */ + if (b >= MP_DIGIT_BIT) { + if ((err = mp_lshd(c, b / MP_DIGIT_BIT)) != MP_OKAY) { + return err; + } + } - /* 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; + /* shift any bit count < MP_DIGIT_BIT */ + d = (mp_digit)(b % MP_DIGIT_BIT); + if (d != 0u) { + mp_digit *tmpc, shift, mask, r, rr; + int x; - /* bitmask for carries */ - mask = (((mp_digit)1) << d) - 1; + /* bitmask for carries */ + mask = ((mp_digit)1 << d) - (mp_digit)1; - /* shift for msbs */ - shift = DIGIT_BIT - d; + /* shift for msbs */ + shift = (mp_digit)MP_DIGIT_BIT - d; - /* alias */ - tmpc = c->dp; + /* 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; + /* 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; + /* 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 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; + /* set final carry */ + if (r != 0u) { + c->dp[(c->used)++] = r; + } + } + mp_clamp(c); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2d.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mul_d.c b/lib/hcrypto/libtommath/bn_mp_mul_d.c index 00f9a899e..b56dfa3c9 100644 --- a/lib/hcrypto/libtommath/bn_mp_mul_d.c +++ b/lib/hcrypto/libtommath/bn_mp_mul_d.c @@ -1,79 +1,61 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* multiply by a digit */ -int -mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c) { - mp_digit u, *tmpa, *tmpc; - mp_word r; - int ix, res, olduse; + mp_digit u, *tmpa, *tmpc; + mp_word r; + mp_err err; + int ix, 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; - } - } + /* make sure c is big enough to hold a*b */ + if (c->alloc < (a->used + 1)) { + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + } - /* get the original destinations used count */ - olduse = c->used; + /* get the original destinations used count */ + olduse = c->used; - /* set the sign */ - c->sign = a->sign; + /* set the sign */ + c->sign = a->sign; - /* alias for a->dp [source] */ - tmpa = a->dp; + /* alias for a->dp [source] */ + tmpa = a->dp; - /* alias for c->dp [dest] */ - tmpc = c->dp; + /* alias for c->dp [dest] */ + tmpc = c->dp; - /* zero carry */ - u = 0; + /* 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); + /* 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)); + /* 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)); - } + /* send carry into next iteration */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } - /* store final carry [if any] and increment ix offset */ - *tmpc++ = u; - ++ix; + /* store final carry [if any] and increment ix offset */ + *tmpc++ = u; + ++ix; - /* now zero digits above the top */ - while (ix++ < olduse) { - *tmpc++ = 0; - } + /* now zero digits above the top */ + MP_ZERO_DIGITS(tmpc, olduse - ix); - /* set used count */ - c->used = a->used + 1; - mp_clamp(c); + /* set used count */ + c->used = a->used + 1; + mp_clamp(c); - return MP_OKAY; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_mul_d.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_mulmod.c b/lib/hcrypto/libtommath/bn_mp_mulmod.c index 003ceb9b9..160d1626a 100644 --- a/lib/hcrypto/libtommath/bn_mp_mulmod.c +++ b/lib/hcrypto/libtommath/bn_mp_mulmod.c @@ -1,40 +1,25 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* d = a * b (mod c) */ -int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) { - int res; - mp_int t; + mp_err err; + mp_int t; - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } + if ((err = mp_init_size(&t, c->used)) != MP_OKAY) { + return err; + } - 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; + if ((err = mp_mul(a, b, &t)) != MP_OKAY) { + goto LBL_ERR; + } + err = mp_mod(&t, c, d); + +LBL_ERR: + mp_clear(&t); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_mulmod.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_n_root.c b/lib/hcrypto/libtommath/bn_mp_n_root.c deleted file mode 100644 index 85d335cb9..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_n_root.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_neg.c b/lib/hcrypto/libtommath/bn_mp_neg.c index a7d035ab6..264d90097 100644 --- a/lib/hcrypto/libtommath/bn_mp_neg.c +++ b/lib/hcrypto/libtommath/bn_mp_neg.c @@ -1,40 +1,24 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* b = -a */ -int mp_neg (mp_int * a, mp_int * b) +mp_err mp_neg(const mp_int *a, mp_int *b) { - int res; - if (a != b) { - if ((res = mp_copy (a, b)) != MP_OKAY) { - return res; - } - } + mp_err err; + if (a != b) { + if ((err = mp_copy(a, b)) != MP_OKAY) { + return err; + } + } - if (mp_iszero(b) != MP_YES) { - b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; - } else { - b->sign = MP_ZPOS; - } + if (!MP_IS_ZERO(b)) { + b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; + } else { + b->sign = MP_ZPOS; + } - return MP_OKAY; + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_neg.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_or.c b/lib/hcrypto/libtommath/bn_mp_or.c index bff499548..cdacbfbe5 100644 --- a/lib/hcrypto/libtommath/bn_mp_or.c +++ b/lib/hcrypto/libtommath/bn_mp_or.c @@ -1,50 +1,56 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ -/* OR two ints together */ -int mp_or (mp_int * a, mp_int * b, mp_int * c) +/* two complement or */ +mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c) { - int res, ix, px; - mp_int t, *x; + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + mp_sign csign = ((a->sign == MP_NEG) || (b->sign == MP_NEG)) ? MP_NEG : MP_ZPOS; - 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; - } + if (c->alloc < used) { + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + } - 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; + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (a->sign == MP_NEG) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (b->sign == MP_NEG) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x | y; + + /* convert to to sign-magnitude if negative */ + if (csign == MP_NEG) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = csign; + mp_clamp(c); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_or.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_pack.c b/lib/hcrypto/libtommath/bn_mp_pack.c new file mode 100644 index 000000000..6e00b6fc6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_pack.c @@ -0,0 +1,69 @@ +#include "tommath_private.h" +#ifdef BN_MP_PACK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on gmp's mpz_export. + * see http://gmplib.org/manual/Integer-Import-and-Export.html + */ +mp_err mp_pack(void *rop, size_t maxcount, size_t *written, mp_order order, size_t size, + mp_endian endian, size_t nails, const mp_int *op) +{ + mp_err err; + size_t odd_nails, nail_bytes, i, j, count; + unsigned char odd_nail_mask; + + mp_int t; + + count = mp_pack_count(op, nails, size); + + if (count > maxcount) { + return MP_BUF; + } + + if ((err = mp_init_copy(&t, op)) != MP_OKAY) { + return err; + } + + if (endian == MP_NATIVE_ENDIAN) { + MP_GET_ENDIANNESS(endian); + } + + odd_nails = (nails % 8u); + odd_nail_mask = 0xff; + for (i = 0u; i < odd_nails; ++i) { + odd_nail_mask ^= (unsigned char)(1u << (7u - i)); + } + nail_bytes = nails / 8u; + + for (i = 0u; i < count; ++i) { + for (j = 0u; j < size; ++j) { + unsigned char *byte = (unsigned char *)rop + + (((order == MP_LSB_FIRST) ? i : ((count - 1u) - i)) * size) + + ((endian == MP_LITTLE_ENDIAN) ? j : ((size - 1u) - j)); + + if (j >= (size - nail_bytes)) { + *byte = 0; + continue; + } + + *byte = (unsigned char)((j == ((size - nail_bytes) - 1u)) ? (t.dp[0] & odd_nail_mask) : (t.dp[0] & 0xFFuL)); + + if ((err = mp_div_2d(&t, (j == ((size - nail_bytes) - 1u)) ? (int)(8u - odd_nails) : 8, &t, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + } + } + + if (written != NULL) { + *written = count; + } + err = MP_OKAY; + +LBL_ERR: + mp_clear(&t); + return err; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_pack_count.c b/lib/hcrypto/libtommath/bn_mp_pack_count.c new file mode 100644 index 000000000..dfecdf98f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_pack_count.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef BN_MP_PACK_COUNT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +size_t mp_pack_count(const mp_int *a, size_t nails, size_t size) +{ + size_t bits = (size_t)mp_count_bits(a); + return ((bits / ((size * 8u) - nails)) + (((bits % ((size * 8u) - nails)) != 0u) ? 1u : 0u)); +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_prime_fermat.c b/lib/hcrypto/libtommath/bn_mp_prime_fermat.c index 8e74a337c..af3e884bb 100644 --- a/lib/hcrypto/libtommath/bn_mp_prime_fermat.c +++ b/lib/hcrypto/libtommath/bn_mp_prime_fermat.c @@ -1,19 +1,7 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* performs one Fermat test. * @@ -23,40 +11,37 @@ * * Sets result to 1 if the congruence holds, or zero otherwise. */ -int mp_prime_fermat (mp_int * a, mp_int * b, int *result) +mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, mp_bool *result) { - mp_int t; - int err; + mp_int t; + mp_err err; - /* default to composite */ - *result = MP_NO; + /* default to composite */ + *result = MP_NO; - /* ensure b > 1 */ - if (mp_cmp_d(b, 1) != MP_GT) { - return MP_VAL; - } + /* ensure b > 1 */ + if (mp_cmp_d(b, 1uL) != MP_GT) { + return MP_VAL; + } - /* init t */ - if ((err = mp_init (&t)) != MP_OKAY) { - return err; - } + /* 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; - } + /* 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; - } + /* 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; + err = MP_OKAY; +LBL_T: + mp_clear(&t); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_prime_fermat.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_frobenius_underwood.c b/lib/hcrypto/libtommath/bn_mp_prime_frobenius_underwood.c new file mode 100644 index 000000000..253e8d53b --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_prime_frobenius_underwood.c @@ -0,0 +1,132 @@ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_FROBENIUS_UNDERWOOD_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * See file bn_mp_prime_is_prime.c or the documentation in doc/bn.tex for the details + */ +#ifndef LTM_USE_ONLY_MR + +#ifdef MP_8BIT +/* + * floor of positive solution of + * (2^16)-1 = (a+4)*(2*a+5) + * TODO: Both values are smaller than N^(1/4), would have to use a bigint + * for a instead but any a biger than about 120 are already so rare that + * it is possible to ignore them and still get enough pseudoprimes. + * But it is still a restriction of the set of available pseudoprimes + * which makes this implementation less secure if used stand-alone. + */ +#define LTM_FROBENIUS_UNDERWOOD_A 177 +#else +#define LTM_FROBENIUS_UNDERWOOD_A 32764 +#endif +mp_err mp_prime_frobenius_underwood(const mp_int *N, mp_bool *result) +{ + mp_int T1z, T2z, Np1z, sz, tz; + + int a, ap2, length, i, j; + mp_err err; + + *result = MP_NO; + + if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, NULL)) != MP_OKAY) { + return err; + } + + for (a = 0; a < LTM_FROBENIUS_UNDERWOOD_A; a++) { + /* TODO: That's ugly! No, really, it is! */ + if ((a==2) || (a==4) || (a==7) || (a==8) || (a==10) || + (a==14) || (a==18) || (a==23) || (a==26) || (a==28)) { + continue; + } + /* (32764^2 - 4) < 2^31, no bigint for >MP_8BIT needed) */ + mp_set_u32(&T1z, (uint32_t)a); + + if ((err = mp_sqr(&T1z, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + + if ((err = mp_sub_d(&T1z, 4uL, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + + if ((err = mp_kronecker(&T1z, N, &j)) != MP_OKAY) goto LBL_FU_ERR; + + if (j == -1) { + break; + } + + if (j == 0) { + /* composite */ + goto LBL_FU_ERR; + } + } + /* Tell it a composite and set return value accordingly */ + if (a >= LTM_FROBENIUS_UNDERWOOD_A) { + err = MP_ITER; + goto LBL_FU_ERR; + } + /* Composite if N and (a+4)*(2*a+5) are not coprime */ + mp_set_u32(&T1z, (uint32_t)((a+4)*((2*a)+5))); + + if ((err = mp_gcd(N, &T1z, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + + if (!((T1z.used == 1) && (T1z.dp[0] == 1u))) goto LBL_FU_ERR; + + ap2 = a + 2; + if ((err = mp_add_d(N, 1uL, &Np1z)) != MP_OKAY) goto LBL_FU_ERR; + + mp_set(&sz, 1uL); + mp_set(&tz, 2uL); + length = mp_count_bits(&Np1z); + + for (i = length - 2; i >= 0; i--) { + /* + * temp = (sz*(a*sz+2*tz))%N; + * tz = ((tz-sz)*(tz+sz))%N; + * sz = temp; + */ + if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_FU_ERR; + + /* a = 0 at about 50% of the cases (non-square and odd input) */ + if (a != 0) { + if ((err = mp_mul_d(&sz, (mp_digit)a, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_add(&T1z, &T2z, &T2z)) != MP_OKAY) goto LBL_FU_ERR; + } + + if ((err = mp_mul(&T2z, &sz, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_sub(&tz, &sz, &T2z)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_add(&sz, &tz, &sz)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_mul(&sz, &T2z, &tz)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_mod(&tz, N, &tz)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_mod(&T1z, N, &sz)) != MP_OKAY) goto LBL_FU_ERR; + if (s_mp_get_bit(&Np1z, (unsigned int)i) == MP_YES) { + /* + * temp = (a+2) * sz + tz + * tz = 2 * tz - sz + * sz = temp + */ + if (a == 0) { + if ((err = mp_mul_2(&sz, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + } else { + if ((err = mp_mul_d(&sz, (mp_digit)ap2, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + } + if ((err = mp_add(&T1z, &tz, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_sub(&T2z, &sz, &tz)) != MP_OKAY) goto LBL_FU_ERR; + mp_exch(&sz, &T1z); + } + } + + mp_set_u32(&T1z, (uint32_t)((2 * a) + 5)); + if ((err = mp_mod(&T1z, N, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + if (MP_IS_ZERO(&sz) && (mp_cmp(&tz, &T1z) == MP_EQ)) { + *result = MP_YES; + } + +LBL_FU_ERR: + mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, NULL); + return err; +} + +#endif +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c b/lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c deleted file mode 100644 index 766cde95a..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_prime_is_divisible.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c b/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c index c316d6210..7f9fc0b45 100644 --- a/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c +++ b/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c @@ -1,83 +1,314 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ -/* 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) +/* portable integer log of two with small footprint */ +static unsigned int s_floor_ilog2(int value) { - mp_int b; - int ix, err, res; + unsigned int r = 0; + while ((value >>= 1) != 0) { + r++; + } + return r; +} - /* default to no */ - *result = MP_NO; - /* valid value of t? */ - if (t <= 0 || t > PRIME_SIZE) { - return MP_VAL; - } +mp_err mp_prime_is_prime(const mp_int *a, int t, mp_bool *result) +{ + mp_int b; + int ix, p_max = 0, size_a, len; + mp_bool res; + mp_err err; + unsigned int fips_rand, mask; - /* 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; + /* default to no */ + *result = MP_NO; + + /* Some shortcuts */ + /* N > 3 */ + if (a->used == 1) { + if ((a->dp[0] == 0u) || (a->dp[0] == 1u)) { + *result = MP_NO; return MP_OKAY; } - } + if (a->dp[0] == 2u) { + *result = MP_YES; + return MP_OKAY; + } + } - /* first perform trial division */ - if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { - return err; - } + /* N must be odd */ + if (MP_IS_EVEN(a)) { + return MP_OKAY; + } + /* N is not a perfect square: floor(sqrt(N))^2 != N */ + if ((err = mp_is_square(a, &res)) != MP_OKAY) { + return err; + } + if (res != MP_NO) { + return MP_OKAY; + } - /* 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; -} + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < PRIVATE_MP_PRIME_TAB_SIZE; ix++) { + if (mp_cmp_d(a, s_mp_prime_tab[ix]) == MP_EQ) { + *result = MP_YES; + return MP_OKAY; + } + } +#ifdef MP_8BIT + /* The search in the loop above was exhaustive in this case */ + if ((a->used == 1) && (PRIVATE_MP_PRIME_TAB_SIZE >= 31)) { + return MP_OKAY; + } #endif -/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_prime.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ + /* first perform trial division */ + if ((err = s_mp_prime_is_divisible(a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res == MP_YES) { + return MP_OKAY; + } + + /* + Run the Miller-Rabin test with base 2 for the BPSW test. + */ + if ((err = mp_init_set(&b, 2uL)) != MP_OKAY) { + return err; + } + + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (res == MP_NO) { + goto LBL_B; + } + /* + Rumours have it that Mathematica does a second M-R test with base 3. + Other rumours have it that their strong L-S test is slightly different. + It does not hurt, though, beside a bit of extra runtime. + */ + b.dp[0]++; + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (res == MP_NO) { + goto LBL_B; + } + + /* + * Both, the Frobenius-Underwood test and the the Lucas-Selfridge test are quite + * slow so if speed is an issue, define LTM_USE_ONLY_MR to use M-R tests with + * bases 2, 3 and t random bases. + */ +#ifndef LTM_USE_ONLY_MR + if (t >= 0) { + /* + * Use a Frobenius-Underwood test instead of the Lucas-Selfridge test for + * MP_8BIT (It is unknown if the Lucas-Selfridge test works with 16-bit + * integers but the necesssary analysis is on the todo-list). + */ +#if defined (MP_8BIT) || defined (LTM_USE_FROBENIUS_TEST) + err = mp_prime_frobenius_underwood(a, &res); + if ((err != MP_OKAY) && (err != MP_ITER)) { + goto LBL_B; + } + if (res == MP_NO) { + goto LBL_B; + } +#else + if ((err = mp_prime_strong_lucas_selfridge(a, &res)) != MP_OKAY) { + goto LBL_B; + } + if (res == MP_NO) { + goto LBL_B; + } +#endif + } +#endif + + /* run at least one Miller-Rabin test with a random base */ + if (t == 0) { + t = 1; + } + + /* + Only recommended if the input range is known to be < 3317044064679887385961981 + + It uses the bases necessary for a deterministic M-R test if the input is + smaller than 3317044064679887385961981 + The caller has to check the size. + TODO: can be made a bit finer grained but comparing is not free. + */ + if (t < 0) { + /* + Sorenson, Jonathan; Webster, Jonathan (2015). + "Strong Pseudoprimes to Twelve Prime Bases". + */ + /* 0x437ae92817f9fc85b7e5 = 318665857834031151167461 */ + if ((err = mp_read_radix(&b, "437ae92817f9fc85b7e5", 16)) != MP_OKAY) { + goto LBL_B; + } + + if (mp_cmp(a, &b) == MP_LT) { + p_max = 12; + } else { + /* 0x2be6951adc5b22410a5fd = 3317044064679887385961981 */ + if ((err = mp_read_radix(&b, "2be6951adc5b22410a5fd", 16)) != MP_OKAY) { + goto LBL_B; + } + + if (mp_cmp(a, &b) == MP_LT) { + p_max = 13; + } else { + err = MP_VAL; + goto LBL_B; + } + } + + /* we did bases 2 and 3 already, skip them */ + for (ix = 2; ix < p_max; ix++) { + mp_set(&b, s_mp_prime_tab[ix]); + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (res == MP_NO) { + goto LBL_B; + } + } + } + /* + Do "t" M-R tests with random bases between 3 and "a". + See Fips 186.4 p. 126ff + */ + else if (t > 0) { + /* + * The mp_digit's have a defined bit-size but the size of the + * array a.dp is a simple 'int' and this library can not assume full + * compliance to the current C-standard (ISO/IEC 9899:2011) because + * it gets used for small embeded processors, too. Some of those MCUs + * have compilers that one cannot call standard compliant by any means. + * Hence the ugly type-fiddling in the following code. + */ + size_a = mp_count_bits(a); + mask = (1u << s_floor_ilog2(size_a)) - 1u; + /* + Assuming the General Rieman hypothesis (never thought to write that in a + comment) the upper bound can be lowered to 2*(log a)^2. + E. Bach, "Explicit bounds for primality testing and related problems," + Math. Comp. 55 (1990), 355-380. + + size_a = (size_a/10) * 7; + len = 2 * (size_a * size_a); + + E.g.: a number of size 2^2048 would be reduced to the upper limit + + floor(2048/10)*7 = 1428 + 2 * 1428^2 = 4078368 + + (would have been ~4030331.9962 with floats and natural log instead) + That number is smaller than 2^28, the default bit-size of mp_digit. + */ + + /* + How many tests, you might ask? Dana Jacobsen of Math::Prime::Util fame + does exactly 1. In words: one. Look at the end of _GMP_is_prime() in + Math-Prime-Util-GMP-0.50/primality.c if you do not believe it. + + The function mp_rand() goes to some length to use a cryptographically + good PRNG. That also means that the chance to always get the same base + in the loop is non-zero, although very low. + If the BPSW test and/or the addtional Frobenious test have been + performed instead of just the Miller-Rabin test with the bases 2 and 3, + a single extra test should suffice, so such a very unlikely event + will not do much harm. + + To preemptivly answer the dangling question: no, a witness does not + need to be prime. + */ + for (ix = 0; ix < t; ix++) { + /* mp_rand() guarantees the first digit to be non-zero */ + if ((err = mp_rand(&b, 1)) != MP_OKAY) { + goto LBL_B; + } + /* + * Reduce digit before casting because mp_digit might be bigger than + * an unsigned int and "mask" on the other side is most probably not. + */ + fips_rand = (unsigned int)(b.dp[0] & (mp_digit) mask); +#ifdef MP_8BIT + /* + * One 8-bit digit is too small, so concatenate two if the size of + * unsigned int allows for it. + */ + if ((MP_SIZEOF_BITS(unsigned int)/2) >= MP_SIZEOF_BITS(mp_digit)) { + if ((err = mp_rand(&b, 1)) != MP_OKAY) { + goto LBL_B; + } + fips_rand <<= MP_SIZEOF_BITS(mp_digit); + fips_rand |= (unsigned int) b.dp[0]; + fips_rand &= mask; + } +#endif + if (fips_rand > (unsigned int)(INT_MAX - MP_DIGIT_BIT)) { + len = INT_MAX / MP_DIGIT_BIT; + } else { + len = (((int)fips_rand + MP_DIGIT_BIT) / MP_DIGIT_BIT); + } + /* Unlikely. */ + if (len < 0) { + ix--; + continue; + } + /* + * As mentioned above, one 8-bit digit is too small and + * although it can only happen in the unlikely case that + * an "unsigned int" is smaller than 16 bit a simple test + * is cheap and the correction even cheaper. + */ +#ifdef MP_8BIT + /* All "a" < 2^8 have been caught before */ + if (len == 1) { + len++; + } +#endif + if ((err = mp_rand(&b, len)) != MP_OKAY) { + goto LBL_B; + } + /* + * That number might got too big and the witness has to be + * smaller than "a" + */ + len = mp_count_bits(&b); + if (len >= size_a) { + len = (len - size_a) + 1; + if ((err = mp_div_2d(&b, len, &b, NULL)) != MP_OKAY) { + goto LBL_B; + } + } + /* Although the chance for b <= 3 is miniscule, try again. */ + if (mp_cmp_d(&b, 3uL) != MP_GT) { + ix--; + continue; + } + 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 diff --git a/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c b/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c index 60a8c48ea..96470dba7 100644 --- a/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c +++ b/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c @@ -1,19 +1,7 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* Miller-Rabin test of "a" to the base of "b" as described in * HAC pp. 139 Algorithm 4.24 @@ -22,82 +10,82 @@ * 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_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, mp_bool *result) { - mp_int n1, y, r; - int s, j, err; + mp_int n1, y, r; + mp_err err; + int s, j; - /* default */ - *result = MP_NO; + /* default */ + *result = MP_NO; - /* ensure b > 1 */ - if (mp_cmp_d(b, 1) != MP_GT) { - return MP_VAL; - } + /* ensure b > 1 */ + if (mp_cmp_d(b, 1uL) != 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; - } + /* get n1 = a - 1 */ + if ((err = mp_init_copy(&n1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_sub_d(&n1, 1uL, &n1)) != MP_OKAY) { + goto LBL_N1; + } - /* set 2**s * r = n1 */ - if ((err = mp_init_copy (&r, &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); + /* 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; - } + /* 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) { + /* 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; - } - } + } - /* probably prime now */ - *result = MP_YES; -LBL_Y:mp_clear (&y); -LBL_R:mp_clear (&r); -LBL_N1:mp_clear (&n1); - return err; + /* if y != 1 and y != n1 do */ + if ((mp_cmp_d(&y, 1uL) != 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, 1uL) == MP_EQ) { + goto LBL_Y; + } + + ++j; + } + + /* if y != n1 then composite */ + if (mp_cmp(&y, &n1) != MP_EQ) { + goto LBL_Y; + } + } + + /* probably prime now */ + *result = MP_YES; +LBL_Y: + mp_clear(&y); +LBL_R: + mp_clear(&r); +LBL_N1: + mp_clear(&n1); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_prime_miller_rabin.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c b/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c index 8cd3ec2a5..d65656578 100644 --- a/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c +++ b/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c @@ -1,70 +1,42 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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) +mp_err mp_prime_next_prime(mp_int *a, int t, int bbs_style) { - int err, res = MP_NO, x, y; - mp_digit res_tab[PRIME_SIZE], step, kstep; + int x, y; + mp_ord cmp; + mp_err err; + mp_bool res = MP_NO; + mp_digit res_tab[PRIVATE_MP_PRIME_TAB_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; + if (mp_cmp_d(a, s_mp_prime_tab[PRIVATE_MP_PRIME_TAB_SIZE-1]) == MP_LT) { + /* find which prime it is bigger than "a" */ + for (x = 0; x < PRIVATE_MP_PRIME_TAB_SIZE; x++) { + cmp = mp_cmp_d(a, s_mp_prime_tab[x]); + if (cmp == MP_EQ) { + continue; + } + if (cmp != MP_GT) { + if ((bbs_style == 1) && ((s_mp_prime_tab[x] & 3u) != 3u)) { + /* try again until we get a prime congruent to 3 mod 4 */ + continue; + } else { + mp_set(a, s_mp_prime_tab[x]); + return MP_OKAY; + } + } } /* fall through to the sieve */ } @@ -80,21 +52,23 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style) 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; }; + if ((a->dp[0] & 3u) != 3u) { + if ((err = mp_sub_d(a, (a->dp[0] & 3u) + 1u, a)) != MP_OKAY) { + return err; + } } } else { - if (mp_iseven(a) == 1) { + if (MP_IS_EVEN(a)) { /* force odd */ - if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) { + if ((err = mp_sub_d(a, 1uL, 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) { + for (x = 1; x < PRIVATE_MP_PRIME_TAB_SIZE; x++) { + if ((err = mp_mod_d(a, s_mp_prime_tab[x], res_tab + x)) != MP_OKAY) { return err; } } @@ -115,43 +89,35 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style) 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; + for (x = 1; x < PRIVATE_MP_PRIME_TAB_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]; - } + /* subtract the modulus [instead of using division] */ + if (res_tab[x] >= s_mp_prime_tab[x]) { + res_tab[x] -= s_mp_prime_tab[x]; + } - /* set flag if zero */ - if (res_tab[x] == 0) { - y = 1; - } + /* set flag if zero */ + if (res_tab[x] == 0u) { + y = 1; + } } - } while (y == 1 && step < ((((mp_digit)1)<= ((((mp_digit)1)<= (((mp_digit)1 << MP_DIGIT_BIT) - kstep))) { continue; } - /* is this prime? */ - for (x = 0; x < t; x++) { - mp_set(&b, ltm_prime_tab[x]); - if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { - goto LBL_ERR; - } - if (res == MP_NO) { - break; - } + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { + goto LBL_ERR; } - if (res == MP_YES) { break; } @@ -164,7 +130,3 @@ LBL_ERR: } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_prime_next_prime.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c b/lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c index 248c2fd2e..8bbaf6cf9 100644 --- a/lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c +++ b/lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c @@ -1,32 +1,31 @@ -#include +#include "tommath_private.h" #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 - */ - +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ static const struct { int k, t; } sizes[] = { -{ 128, 28 }, -{ 256, 16 }, -{ 384, 10 }, -{ 512, 7 }, -{ 640, 6 }, -{ 768, 5 }, -{ 896, 4 }, -{ 1024, 4 } + { 80, -1 }, /* Use deterministic algorithm for size <= 80 bits */ + { 81, 37 }, /* max. error = 2^(-96)*/ + { 96, 32 }, /* max. error = 2^(-96)*/ + { 128, 40 }, /* max. error = 2^(-112)*/ + { 160, 35 }, /* max. error = 2^(-112)*/ + { 256, 27 }, /* max. error = 2^(-128)*/ + { 384, 16 }, /* max. error = 2^(-128)*/ + { 512, 18 }, /* max. error = 2^(-160)*/ + { 768, 11 }, /* max. error = 2^(-160)*/ + { 896, 10 }, /* max. error = 2^(-160)*/ + { 1024, 12 }, /* max. error = 2^(-192)*/ + { 1536, 8 }, /* max. error = 2^(-192)*/ + { 2048, 6 }, /* max. error = 2^(-192)*/ + { 3072, 4 }, /* max. error = 2^(-192)*/ + { 4096, 5 }, /* max. error = 2^(-256)*/ + { 5120, 4 }, /* max. error = 2^(-256)*/ + { 6144, 4 }, /* max. error = 2^(-256)*/ + { 8192, 3 }, /* max. error = 2^(-256)*/ + { 9216, 3 }, /* max. error = 2^(-256)*/ + { 10240, 2 } /* For bigger keysizes use always at least 2 Rounds */ }; /* returns # of RM trials required for a given bit size */ @@ -35,18 +34,14 @@ 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; - } + 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; + return sizes[x-1].t; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_prime_rabin_miller_trials.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_rand.c b/lib/hcrypto/libtommath/bn_mp_prime_rand.c new file mode 100644 index 000000000..4530e9a5e --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_prime_rand.c @@ -0,0 +1,141 @@ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * MP_PRIME_BBS - make prime congruent to 3 mod 4 + * MP_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS) + * MP_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! */ +mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat) +{ + unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb; + int bsize, maskOR_msb_offset; + mp_bool res; + mp_err err; + + /* sanity check the input */ + if ((size <= 1) || (t <= 0)) { + return MP_VAL; + } + + /* MP_PRIME_SAFE implies MP_PRIME_BBS */ + if ((flags & MP_PRIME_SAFE) != 0) { + flags |= MP_PRIME_BBS; + } + + /* calc the byte size */ + bsize = (size>>3) + ((size&7)?1:0); + + /* we need a buffer of bsize bytes */ + tmp = (unsigned char *) MP_MALLOC((size_t)bsize); + if (tmp == NULL) { + return MP_MEM; + } + + /* calc the maskAND value for the MSbyte*/ + maskAND = ((size&7) == 0) ? 0xFFu : (unsigned char)(0xFFu >> (8 - (size & 7))); + + /* calc the maskOR_msb */ + maskOR_msb = 0; + maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0; + if ((flags & MP_PRIME_2MSB_ON) != 0) { + maskOR_msb |= (unsigned char)(0x80 >> ((9 - size) & 7)); + } + + /* get the maskOR_lsb */ + maskOR_lsb = 1u; + if ((flags & MP_PRIME_BBS) != 0) { + maskOR_lsb |= 3u; + } + + do { + /* read the bytes */ + if (cb(tmp, bsize, dat) != bsize) { + err = MP_VAL; + goto error; + } + + /* work over the MSbyte */ + tmp[0] &= maskAND; + tmp[0] |= (unsigned char)(1 << ((size - 1) & 7)); + + /* mix in the maskORs */ + tmp[maskOR_msb_offset] |= maskOR_msb; + tmp[bsize-1] |= maskOR_lsb; + + /* read it in */ + /* TODO: casting only for now until all lengths have been changed to the type "size_t"*/ + if ((err = mp_from_ubin(a, tmp, (size_t)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 & MP_PRIME_SAFE) != 0) { + /* see if (a-1)/2 is prime */ + if ((err = mp_sub_d(a, 1uL, 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 & MP_PRIME_SAFE) != 0) { + /* restore a to the original value */ + if ((err = mp_mul_2(a, a)) != MP_OKAY) { + goto error; + } + if ((err = mp_add_d(a, 1uL, a)) != MP_OKAY) { + goto error; + } + } + + err = MP_OKAY; +error: + MP_FREE_BUFFER(tmp, (size_t)bsize); + return err; +} + +static int s_mp_rand_cb(unsigned char *dst, int len, void *dat) +{ + (void)dat; + if (len <= 0) { + return len; + } + if (s_mp_rand_source(dst, (size_t)len) != MP_OKAY) { + return 0; + } + return len; +} + +mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) +{ + return s_mp_prime_random_ex(a, t, size, flags, s_mp_rand_cb, NULL); +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_prime_random_ex.c b/lib/hcrypto/libtommath/bn_mp_prime_random_ex.c deleted file mode 100644 index 7b0d15c94..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_prime_random_ex.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_prime_strong_lucas_selfridge.c b/lib/hcrypto/libtommath/bn_mp_prime_strong_lucas_selfridge.c new file mode 100644 index 000000000..b50bbcd2f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_prime_strong_lucas_selfridge.c @@ -0,0 +1,289 @@ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * See file bn_mp_prime_is_prime.c or the documentation in doc/bn.tex for the details + */ +#ifndef LTM_USE_ONLY_MR + +/* + * 8-bit is just too small. You can try the Frobenius test + * but that frobenius test can fail, too, for the same reason. + */ +#ifndef MP_8BIT + +/* + * multiply bigint a with int d and put the result in c + * Like mp_mul_d() but with a signed long as the small input + */ +static mp_err s_mp_mul_si(const mp_int *a, int32_t d, mp_int *c) +{ + mp_int t; + mp_err err; + + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } + + /* + * mp_digit might be smaller than a long, which excludes + * the use of mp_mul_d() here. + */ + mp_set_i32(&t, d); + err = mp_mul(a, &t, c); + mp_clear(&t); + return err; +} +/* + Strong Lucas-Selfridge test. + returns MP_YES if it is a strong L-S prime, MP_NO if it is composite + + Code ported from Thomas Ray Nicely's implementation of the BPSW test + at http://www.trnicely.net/misc/bpsw.html + + Freeware copyright (C) 2016 Thomas R. Nicely . + Released into the public domain by the author, who disclaims any legal + liability arising from its use + + The multi-line comments are made by Thomas R. Nicely and are copied verbatim. + Additional comments marked "CZ" (without the quotes) are by the code-portist. + + (If that name sounds familiar, he is the guy who found the fdiv bug in the + Pentium (P5x, I think) Intel processor) +*/ +mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, mp_bool *result) +{ + /* CZ TODO: choose better variable names! */ + mp_int Dz, gcd, Np1, Uz, Vz, U2mz, V2mz, Qmz, Q2mz, Qkdz, T1z, T2z, T3z, T4z, Q2kdz; + /* CZ TODO: Some of them need the full 32 bit, hence the (temporary) exclusion of MP_8BIT */ + int32_t D, Ds, J, sign, P, Q, r, s, u, Nbits; + mp_err err; + mp_bool oddness; + + *result = MP_NO; + /* + Find the first element D in the sequence {5, -7, 9, -11, 13, ...} + such that Jacobi(D,N) = -1 (Selfridge's algorithm). Theory + indicates that, if N is not a perfect square, D will "nearly + always" be "small." Just in case, an overflow trap for D is + included. + */ + + if ((err = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz, + NULL)) != MP_OKAY) { + return err; + } + + D = 5; + sign = 1; + + for (;;) { + Ds = sign * D; + sign = -sign; + mp_set_u32(&Dz, (uint32_t)D); + if ((err = mp_gcd(a, &Dz, &gcd)) != MP_OKAY) goto LBL_LS_ERR; + + /* if 1 < GCD < N then N is composite with factor "D", and + Jacobi(D,N) is technically undefined (but often returned + as zero). */ + if ((mp_cmp_d(&gcd, 1uL) == MP_GT) && (mp_cmp(&gcd, a) == MP_LT)) { + goto LBL_LS_ERR; + } + if (Ds < 0) { + Dz.sign = MP_NEG; + } + if ((err = mp_kronecker(&Dz, a, &J)) != MP_OKAY) goto LBL_LS_ERR; + + if (J == -1) { + break; + } + D += 2; + + if (D > (INT_MAX - 2)) { + err = MP_VAL; + goto LBL_LS_ERR; + } + } + + + + P = 1; /* Selfridge's choice */ + Q = (1 - Ds) / 4; /* Required so D = P*P - 4*Q */ + + /* NOTE: The conditions (a) N does not divide Q, and + (b) D is square-free or not a perfect square, are included by + some authors; e.g., "Prime numbers and computer methods for + factorization," Hans Riesel (2nd ed., 1994, Birkhauser, Boston), + p. 130. For this particular application of Lucas sequences, + these conditions were found to be immaterial. */ + + /* Now calculate N - Jacobi(D,N) = N + 1 (even), and calculate the + odd positive integer d and positive integer s for which + N + 1 = 2^s*d (similar to the step for N - 1 in Miller's test). + The strong Lucas-Selfridge test then returns N as a strong + Lucas probable prime (slprp) if any of the following + conditions is met: U_d=0, V_d=0, V_2d=0, V_4d=0, V_8d=0, + V_16d=0, ..., etc., ending with V_{2^(s-1)*d}=V_{(N+1)/2}=0 + (all equalities mod N). Thus d is the highest index of U that + must be computed (since V_2m is independent of U), compared + to U_{N+1} for the standard Lucas-Selfridge test; and no + index of V beyond (N+1)/2 is required, just as in the + standard Lucas-Selfridge test. However, the quantity Q^d must + be computed for use (if necessary) in the latter stages of + the test. The result is that the strong Lucas-Selfridge test + has a running time only slightly greater (order of 10 %) than + that of the standard Lucas-Selfridge test, while producing + only (roughly) 30 % as many pseudoprimes (and every strong + Lucas pseudoprime is also a standard Lucas pseudoprime). Thus + the evidence indicates that the strong Lucas-Selfridge test is + more effective than the standard Lucas-Selfridge test, and a + Baillie-PSW test based on the strong Lucas-Selfridge test + should be more reliable. */ + + if ((err = mp_add_d(a, 1uL, &Np1)) != MP_OKAY) goto LBL_LS_ERR; + s = mp_cnt_lsb(&Np1); + + /* CZ + * This should round towards zero because + * Thomas R. Nicely used GMP's mpz_tdiv_q_2exp() + * and mp_div_2d() is equivalent. Additionally: + * dividing an even number by two does not produce + * any leftovers. + */ + if ((err = mp_div_2d(&Np1, s, &Dz, NULL)) != MP_OKAY) goto LBL_LS_ERR; + /* We must now compute U_d and V_d. Since d is odd, the accumulated + values U and V are initialized to U_1 and V_1 (if the target + index were even, U and V would be initialized instead to U_0=0 + and V_0=2). The values of U_2m and V_2m are also initialized to + U_1 and V_1; the FOR loop calculates in succession U_2 and V_2, + U_4 and V_4, U_8 and V_8, etc. If the corresponding bits + (1, 2, 3, ...) of t are on (the zero bit having been accounted + for in the initialization of U and V), these values are then + combined with the previous totals for U and V, using the + composition formulas for addition of indices. */ + + mp_set(&Uz, 1uL); /* U=U_1 */ + mp_set(&Vz, (mp_digit)P); /* V=V_1 */ + mp_set(&U2mz, 1uL); /* U_1 */ + mp_set(&V2mz, (mp_digit)P); /* V_1 */ + + mp_set_i32(&Qmz, Q); + if ((err = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) goto LBL_LS_ERR; + /* Initializes calculation of Q^d */ + mp_set_i32(&Qkdz, Q); + + Nbits = mp_count_bits(&Dz); + + for (u = 1; u < Nbits; u++) { /* zero bit off, already accounted for */ + /* Formulas for doubling of indices (carried out mod N). Note that + * the indices denoted as "2m" are actually powers of 2, specifically + * 2^(ul-1) beginning each loop and 2^ul ending each loop. + * + * U_2m = U_m*V_m + * V_2m = V_m*V_m - 2*Q^m + */ + + if ((err = mp_mul(&U2mz, &V2mz, &U2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&U2mz, a, &U2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sqr(&V2mz, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sub(&V2mz, &Q2mz, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&V2mz, a, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + + /* Must calculate powers of Q for use in V_2m, also for Q^d later */ + if ((err = mp_sqr(&Qmz, &Qmz)) != MP_OKAY) goto LBL_LS_ERR; + + /* prevents overflow */ /* CZ still necessary without a fixed prealloc'd mem.? */ + if ((err = mp_mod(&Qmz, a, &Qmz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) goto LBL_LS_ERR; + + if (s_mp_get_bit(&Dz, (unsigned int)u) == MP_YES) { + /* Formulas for addition of indices (carried out mod N); + * + * U_(m+n) = (U_m*V_n + U_n*V_m)/2 + * V_(m+n) = (V_m*V_n + D*U_m*U_n)/2 + * + * Be careful with division by 2 (mod N)! + */ + if ((err = mp_mul(&U2mz, &Vz, &T1z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&Uz, &V2mz, &T2z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&V2mz, &Vz, &T3z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&U2mz, &Uz, &T4z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = s_mp_mul_si(&T4z, Ds, &T4z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_add(&T1z, &T2z, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if (MP_IS_ODD(&Uz)) { + if ((err = mp_add(&Uz, a, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + } + /* CZ + * This should round towards negative infinity because + * Thomas R. Nicely used GMP's mpz_fdiv_q_2exp(). + * But mp_div_2() does not do so, it is truncating instead. + */ + oddness = MP_IS_ODD(&Uz) ? MP_YES : MP_NO; + if ((err = mp_div_2(&Uz, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if ((Uz.sign == MP_NEG) && (oddness != MP_NO)) { + if ((err = mp_sub_d(&Uz, 1uL, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + } + if ((err = mp_add(&T3z, &T4z, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if (MP_IS_ODD(&Vz)) { + if ((err = mp_add(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + } + oddness = MP_IS_ODD(&Vz) ? MP_YES : MP_NO; + if ((err = mp_div_2(&Vz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if ((Vz.sign == MP_NEG) && (oddness != MP_NO)) { + if ((err = mp_sub_d(&Vz, 1uL, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + } + if ((err = mp_mod(&Uz, a, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + + /* Calculating Q^d for later use */ + if ((err = mp_mul(&Qkdz, &Qmz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + } + } + + /* If U_d or V_d is congruent to 0 mod N, then N is a prime or a + strong Lucas pseudoprime. */ + if (MP_IS_ZERO(&Uz) || MP_IS_ZERO(&Vz)) { + *result = MP_YES; + goto LBL_LS_ERR; + } + + /* NOTE: Ribenboim ("The new book of prime number records," 3rd ed., + 1995/6) omits the condition V0 on p.142, but includes it on + p. 130. The condition is NECESSARY; otherwise the test will + return false negatives---e.g., the primes 29 and 2000029 will be + returned as composite. */ + + /* Otherwise, we must compute V_2d, V_4d, V_8d, ..., V_{2^(s-1)*d} + by repeated use of the formula V_2m = V_m*V_m - 2*Q^m. If any of + these are congruent to 0 mod N, then N is a prime or a strong + Lucas pseudoprime. */ + + /* Initialize 2*Q^(d*2^r) for V_2m */ + if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR; + + for (r = 1; r < s; r++) { + if ((err = mp_sqr(&Vz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sub(&Vz, &Q2kdz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if (MP_IS_ZERO(&Vz)) { + *result = MP_YES; + goto LBL_LS_ERR; + } + /* Calculate Q^{d*2^r} for next r (final iteration irrelevant). */ + if (r < (s - 1)) { + if ((err = mp_sqr(&Qkdz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR; + } + } +LBL_LS_ERR: + mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, NULL); + return err; +} +#endif +#endif +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_radix_size.c b/lib/hcrypto/libtommath/bn_mp_radix_size.c index af94be867..b96f4874c 100644 --- a/lib/hcrypto/libtommath/bn_mp_radix_size.c +++ b/lib/hcrypto/libtommath/bn_mp_radix_size.c @@ -1,78 +1,65 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ -/* returns size of ASCII reprensentation */ -int mp_radix_size (mp_int * a, int radix, int *size) +/* returns size of ASCII representation */ +mp_err mp_radix_size(const mp_int *a, int radix, int *size) { - int res, digs; - mp_int t; - mp_digit d; + mp_err err; + int digs; + mp_int t; + mp_digit d; - *size = 0; + *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; + } - /* make sure the radix is in range */ - if (radix < 2 || radix > 64) { - return MP_VAL; - } + if (MP_IS_ZERO(a)) { + *size = 2; + return MP_OKAY; + } - if (mp_iszero(a) == MP_YES) { - *size = 2; - return MP_OKAY; - } + /* special case for binary */ + if (radix == 2) { + *size = (mp_count_bits(a) + ((a->sign == MP_NEG) ? 1 : 0) + 1); + return MP_OKAY; + } - /* digs is the digit count */ - digs = 0; + /* digs is the digit count */ + digs = 0; - /* if it's negative add one for the sign */ - if (a->sign == MP_NEG) { - ++digs; - } + /* 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; - } + /* init a copy of the input */ + if ((err = mp_init_copy(&t, a)) != MP_OKAY) { + return err; + } - /* force temp to positive */ - t.sign = MP_ZPOS; + /* 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); + /* fetch out all of the digits */ + while (!MP_IS_ZERO(&t)) { + if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) { + goto LBL_ERR; + } + ++digs; + } - /* return digs + 1, the 1 is for the NULL byte that would be required. */ - *size = digs + 1; - return MP_OKAY; + /* return digs + 1, the 1 is for the NULL byte that would be required. */ + *size = digs + 1; + err = MP_OKAY; + +LBL_ERR: + mp_clear(&t); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_radix_size.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_radix_smap.c b/lib/hcrypto/libtommath/bn_mp_radix_smap.c index 7d72feb84..a16128d79 100644 --- a/lib/hcrypto/libtommath/bn_mp_radix_smap.c +++ b/lib/hcrypto/libtommath/bn_mp_radix_smap.c @@ -1,24 +1,22 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* chars used in radix conversions */ -const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +const char *const mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +const uint8_t mp_s_rmap_reverse[] = { + 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, /* ()*+,-./ */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ + 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */ + 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* @ABCDEFG */ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* HIJKLMNO */ + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, /* PQRSTUVW */ + 0x21, 0x22, 0x23, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */ + 0xff, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, /* `abcdefg */ + 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, /* hijklmno */ + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, /* pqrstuvw */ + 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, /* xyz{|}~. */ +}; +const size_t mp_s_rmap_reverse_sz = sizeof(mp_s_rmap_reverse); #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_radix_smap.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_rand.c b/lib/hcrypto/libtommath/bn_mp_rand.c index 14f5b7503..7e9052c2b 100644 --- a/lib/hcrypto/libtommath/bn_mp_rand.c +++ b/lib/hcrypto/libtommath/bn_mp_rand.c @@ -1,55 +1,46 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ -/* makes a pseudo-random int of a given size */ -int -mp_rand (mp_int * a, int digits) +mp_err(*s_mp_rand_source)(void *out, size_t size) = s_mp_rand_platform; + +void mp_rand_source(mp_err(*source)(void *out, size_t size)) { - int res; - mp_digit d; + s_mp_rand_source = (source == NULL) ? s_mp_rand_platform : source; +} - mp_zero (a); - if (digits <= 0) { - return MP_OKAY; - } +mp_err mp_rand(mp_int *a, int digits) +{ + int i; + mp_err err; - /* first place a random non-zero digit */ - do { - d = ((mp_digit) labs (rand ())) & MP_MASK; - } while (d == 0); + mp_zero(a); - if ((res = mp_add_d (a, d, a)) != MP_OKAY) { - return res; - } + if (digits <= 0) { + return MP_OKAY; + } - while (--digits > 0) { - if ((res = mp_lshd (a, 1)) != MP_OKAY) { - return res; - } + if ((err = mp_grow(a, digits)) != MP_OKAY) { + return err; + } - if ((res = mp_add_d (a, ((mp_digit) labs (rand ())), a)) != MP_OKAY) { - return res; - } - } + if ((err = s_mp_rand_source(a->dp, (size_t)digits * sizeof(mp_digit))) != MP_OKAY) { + return err; + } - return MP_OKAY; + /* TODO: We ensure that the highest digit is nonzero. Should this be removed? */ + while ((a->dp[digits - 1] & MP_MASK) == 0u) { + if ((err = s_mp_rand_source(a->dp + digits - 1, sizeof(mp_digit))) != MP_OKAY) { + return err; + } + } + + a->used = digits; + for (i = 0; i < digits; ++i) { + a->dp[i] &= MP_MASK; + } + + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_rand.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_read_radix.c b/lib/hcrypto/libtommath/bn_mp_read_radix.c index 35ca88673..de18e06fc 100644 --- a/lib/hcrypto/libtommath/bn_mp_read_radix.c +++ b/lib/hcrypto/libtommath/bn_mp_read_radix.c @@ -1,85 +1,79 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define MP_TOUPPER(c) ((((c) >= 'a') && ((c) <= 'z')) ? (((c) + 'A') - 'a') : (c)) /* read a string [ASCII] in a given radix */ -int mp_read_radix (mp_int * a, const char *str, int radix) +mp_err mp_read_radix(mp_int *a, const char *str, int radix) { - int y, res, neg; - char ch; + mp_err err; + int y; + mp_sign neg; + unsigned pos; + char ch; - /* zero the digit bignum */ - mp_zero(a); + /* zero the digit bignum */ + mp_zero(a); - /* make sure the radix is ok */ - if (radix < 2 || radix > 64) { - return MP_VAL; - } + /* 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; - } + /* 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); + /* 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]) { + /* process each digit of the string */ + while (*str != '\0') { + /* 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 = (radix <= 36) ? (char)MP_TOUPPER((int)*str) : *str; + pos = (unsigned)(ch - '('); + if (mp_s_rmap_reverse_sz < pos) { break; } - } + y = (int)mp_s_rmap_reverse[pos]; - /* 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 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 == 0xff) || (y >= radix)) { + break; } - if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { - return res; + if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) { + return err; } - } else { - break; - } - ++str; - } + if ((err = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) { + return err; + } + ++str; + } - /* set the sign only if a != 0 */ - if (mp_iszero(a) != 1) { - a->sign = neg; - } - return MP_OKAY; + /* if an illegal character was found, fail. */ + if (!((*str == '\0') || (*str == '\r') || (*str == '\n'))) { + mp_zero(a); + return MP_VAL; + } + + /* set the sign only if a != 0 */ + if (!MP_IS_ZERO(a)) { + a->sign = neg; + } + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_read_radix.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_read_signed_bin.c b/lib/hcrypto/libtommath/bn_mp_read_signed_bin.c deleted file mode 100644 index 8da651ce3..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_read_signed_bin.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c b/lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c deleted file mode 100644 index 1ebba13a0..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_read_unsigned_bin.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce.c b/lib/hcrypto/libtommath/bn_mp_reduce.c index ae57a6a00..3c669d491 100644 --- a/lib/hcrypto/libtommath/bn_mp_reduce.c +++ b/lib/hcrypto/libtommath/bn_mp_reduce.c @@ -1,100 +1,83 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu) { - mp_int q; - int res, um = m->used; + mp_int q; + mp_err err; + int um = m->used; - /* q = x */ - if ((res = mp_init_copy (&q, x)) != MP_OKAY) { - return res; - } + /* q = x */ + if ((err = mp_init_copy(&q, x)) != MP_OKAY) { + return err; + } - /* q1 = x / b**(k-1) */ - mp_rshd (&q, um - 1); + /* 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) { + /* according to HAC this optimization is ok */ + if ((mp_digit)um > ((mp_digit)1 << (MP_DIGIT_BIT - 1))) { + if ((err = mp_mul(&q, mu, &q)) != MP_OKAY) { + goto CLEANUP; + } + } else if (MP_HAS(S_MP_MUL_HIGH_DIGS)) { + if ((err = s_mp_mul_high_digs(&q, mu, &q, um)) != MP_OKAY) { + goto CLEANUP; + } + } else if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST)) { + if ((err = s_mp_mul_high_digs_fast(&q, mu, &q, um)) != MP_OKAY) { + goto CLEANUP; + } + } else { + err = MP_VAL; 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); + /* 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) + /* x = x mod b**(k+1), quick (no division) */ + if ((err = mp_mod_2d(x, MP_DIGIT_BIT * (um + 1), x)) != 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) { + /* q = q * m mod b**(k+1), quick (no division) */ + if ((err = s_mp_mul_digs(&q, m, &q, um + 1)) != MP_OKAY) { goto CLEANUP; - } - } + } + + /* x = x - q */ + if ((err = mp_sub(x, &q, x)) != MP_OKAY) { + goto CLEANUP; + } + + /* If x < 0, add b**(k+1) to it */ + if (mp_cmp_d(x, 0uL) == MP_LT) { + mp_set(&q, 1uL); + if ((err = mp_lshd(&q, um + 1)) != MP_OKAY) { + goto CLEANUP; + } + if ((err = mp_add(x, &q, x)) != MP_OKAY) { + goto CLEANUP; + } + } + + /* Back off if it's too big */ + while (mp_cmp(x, m) != MP_LT) { + if ((err = s_mp_sub(x, m, x)) != MP_OKAY) { + goto CLEANUP; + } + } CLEANUP: - mp_clear (&q); + mp_clear(&q); - return res; + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_reduce.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_2k.c b/lib/hcrypto/libtommath/bn_mp_reduce_2k.c index 1c4a751dd..1cea6cb21 100644 --- a/lib/hcrypto/libtommath/bn_mp_reduce_2k.c +++ b/lib/hcrypto/libtommath/bn_mp_reduce_2k.c @@ -1,61 +1,48 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d) { mp_int q; - int p, res; + mp_err err; + int p; - if ((res = mp_init(&q)) != MP_OKAY) { - return res; + if ((err = mp_init(&q)) != MP_OKAY) { + return err; } 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 ((err = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto LBL_ERR; } - if (d != 1) { + if (d != 1u) { /* q = q * d */ - if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { - goto ERR; + if ((err = mp_mul_d(&q, d, &q)) != MP_OKAY) { + goto LBL_ERR; } } /* a = a + q */ - if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { - goto ERR; + if ((err = s_mp_add(a, &q, a)) != MP_OKAY) { + goto LBL_ERR; } if (mp_cmp_mag(a, n) != MP_LT) { - s_mp_sub(a, n, a); + if ((err = s_mp_sub(a, n, a)) != MP_OKAY) { + goto LBL_ERR; + } goto top; } -ERR: +LBL_ERR: mp_clear(&q); - return res; + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c b/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c index 71abeaebb..6a9f3d31b 100644 --- a/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c +++ b/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c @@ -1,62 +1,49 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d) { mp_int q; - int p, res; + mp_err err; + int p; - if ((res = mp_init(&q)) != MP_OKAY) { - return res; + if ((err = mp_init(&q)) != MP_OKAY) { + return err; } 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 ((err = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto LBL_ERR; } /* q = q * d */ - if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { - goto ERR; + if ((err = mp_mul(&q, d, &q)) != MP_OKAY) { + goto LBL_ERR; } /* a = a + q */ - if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { - goto ERR; + if ((err = s_mp_add(a, &q, a)) != MP_OKAY) { + goto LBL_ERR; } if (mp_cmp_mag(a, n) != MP_LT) { - s_mp_sub(a, n, a); + if ((err = s_mp_sub(a, n, a)) != MP_OKAY) { + goto LBL_ERR; + } goto top; } -ERR: +LBL_ERR: mp_clear(&q); - return res; + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_l.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c b/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c index dca723c81..2eaf7addf 100644 --- a/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c +++ b/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c @@ -1,39 +1,28 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* determines the setup value */ -int mp_reduce_2k_setup(mp_int *a, mp_digit *d) +mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d) { - int res, p; + mp_err err; mp_int tmp; + int p; - if ((res = mp_init(&tmp)) != MP_OKAY) { - return res; + if ((err = mp_init(&tmp)) != MP_OKAY) { + return err; } p = mp_count_bits(a); - if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { + if ((err = mp_2expt(&tmp, p)) != MP_OKAY) { mp_clear(&tmp); - return res; + return err; } - if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + if ((err = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { mp_clear(&tmp); - return res; + return err; } *d = tmp.dp[0]; @@ -41,7 +30,3 @@ int mp_reduce_2k_setup(mp_int *a, mp_digit *d) return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c b/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c index cc59a6e71..4f9aa14d1 100644 --- a/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c +++ b/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c @@ -1,44 +1,28 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* determines the setup value */ -int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) +mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d) { - int res; + mp_err err; mp_int tmp; - if ((res = mp_init(&tmp)) != MP_OKAY) { - return res; + if ((err = mp_init(&tmp)) != MP_OKAY) { + return err; } - if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { - goto ERR; + if ((err = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { + goto LBL_ERR; } - if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) { - goto ERR; + if ((err = s_mp_sub(&tmp, a, d)) != MP_OKAY) { + goto LBL_ERR; } -ERR: +LBL_ERR: mp_clear(&tmp); - return res; + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup_l.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c b/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c index c8d25d83e..a9f4f9f2b 100644 --- a/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c +++ b/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c @@ -1,22 +1,10 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* determines if mp_reduce_2k can be used */ -int mp_reduce_is_2k(mp_int *a) +mp_bool mp_reduce_is_2k(const mp_int *a) { int ix, iy, iw; mp_digit iz; @@ -31,22 +19,20 @@ int mp_reduce_is_2k(mp_int *a) 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; - } + for (ix = MP_DIGIT_BIT; ix < iy; ix++) { + if ((a->dp[iw] & iz) == 0u) { + return MP_NO; + } + iz <<= 1; + if (iz > MP_DIGIT_MAX) { + ++iw; + iz = 1; + } } + return MP_YES; + } else { + return MP_YES; } - return MP_YES; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c b/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c index ad006f39c..4bc69bef8 100644 --- a/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c +++ b/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c @@ -1,22 +1,10 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* determines if reduce_2k_l can be used */ -int mp_reduce_is_2k_l(mp_int *a) +mp_bool mp_reduce_is_2k_l(const mp_int *a) { int ix, iy; @@ -27,18 +15,14 @@ int mp_reduce_is_2k_l(mp_int *a) } 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; - } + if (a->dp[ix] == MP_DIGIT_MAX) { + ++iy; + } } return (iy >= (a->used/2)) ? MP_YES : MP_NO; - + } else { + return MP_NO; } - return MP_NO; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k_l.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_reduce_setup.c b/lib/hcrypto/libtommath/bn_mp_reduce_setup.c index 035419bf3..f02160fa5 100644 --- a/lib/hcrypto/libtommath/bn_mp_reduce_setup.c +++ b/lib/hcrypto/libtommath/bn_mp_reduce_setup.c @@ -1,34 +1,17 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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) +mp_err mp_reduce_setup(mp_int *a, const 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); + mp_err err; + if ((err = mp_2expt(a, b->used * 2 * MP_DIGIT_BIT)) != MP_OKAY) { + return err; + } + return mp_div(a, b, a, NULL); } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_setup.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_root_u32.c b/lib/hcrypto/libtommath/bn_mp_root_u32.c new file mode 100644 index 000000000..ba65549c6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_root_u32.c @@ -0,0 +1,139 @@ +#include "tommath_private.h" +#ifdef BN_MP_ROOT_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. + */ +mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c) +{ + mp_int t1, t2, t3, a_; + mp_ord cmp; + int ilog2; + mp_err err; + + /* input must be positive if b is even */ + if (((b & 1u) == 0u) && (a->sign == MP_NEG)) { + return MP_VAL; + } + + if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) { + return err; + } + + /* if a is negative fudge the sign but keep track */ + a_ = *a; + a_.sign = MP_ZPOS; + + /* Compute seed: 2^(log_2(n)/b + 2)*/ + ilog2 = mp_count_bits(a); + + /* + If "b" is larger than INT_MAX it is also larger than + log_2(n) because the bit-length of the "n" is measured + with an int and hence the root is always < 2 (two). + */ + if (b > (uint32_t)(INT_MAX/2)) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + + /* "b" is smaller than INT_MAX, we can cast safely */ + if (ilog2 < (int)b) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + ilog2 = ilog2 / ((int)b); + if (ilog2 == 0) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + /* Start value must be larger than root */ + ilog2 += 2; + if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY) goto LBL_ERR; + do { + /* t1 = t2 */ + if ((err = mp_copy(&t2, &t1)) != MP_OKAY) goto LBL_ERR; + + /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ + + /* t3 = t1**(b-1) */ + if ((err = mp_expt_u32(&t1, b - 1u, &t3)) != MP_OKAY) goto LBL_ERR; + + /* numerator */ + /* t2 = t1**b */ + if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY) goto LBL_ERR; + + /* t2 = t1**b - a */ + if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY) goto LBL_ERR; + + /* denominator */ + /* t3 = t1**(b-1) * b */ + if ((err = mp_mul_d(&t3, b, &t3)) != MP_OKAY) goto LBL_ERR; + + /* t3 = (t1**b - a)/(b * t1**(b-1)) */ + if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY) goto LBL_ERR; + + /* + Number of rounds is at most log_2(root). If it is more it + got stuck, so break out of the loop and do the rest manually. + */ + if (ilog2-- == 0) { + break; + } + } while (mp_cmp(&t1, &t2) != MP_EQ); + + /* result can be off by a few so check */ + /* Loop beneath can overshoot by one if found root is smaller than actual root */ + for (;;) { + if ((err = mp_expt_u32(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; + cmp = mp_cmp(&t2, &a_); + if (cmp == MP_EQ) { + err = MP_OKAY; + goto LBL_ERR; + } + if (cmp == MP_LT) { + if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; + } else { + break; + } + } + /* correct overshoot from above or from recurrence */ + for (;;) { + if ((err = mp_expt_u32(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; + if (mp_cmp(&t2, &a_) == MP_GT) { + if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; + } else { + break; + } + } + + /* set the result */ + mp_exch(&t1, c); + + /* set the sign of the result */ + c->sign = a->sign; + + err = MP_OKAY; + +LBL_ERR: + mp_clear_multi(&t1, &t2, &t3, NULL); + return err; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_rshd.c b/lib/hcrypto/libtommath/bn_mp_rshd.c index ed13ce59a..bb8743e3b 100644 --- a/lib/hcrypto/libtommath/bn_mp_rshd.c +++ b/lib/hcrypto/libtommath/bn_mp_rshd.c @@ -1,72 +1,51 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* shift right a certain amount of digits */ -void mp_rshd (mp_int * a, int b) +void mp_rshd(mp_int *a, int b) { - int x; + int x; + mp_digit *bottom, *top; - /* if b <= 0 then ignore it */ - if (b <= 0) { - return; - } + /* 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; - } + /* 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 */ - /* shift the digits down */ + /* bottom */ + bottom = a->dp; - /* bottom */ - bottom = a->dp; + /* top [offset into digits] */ + top = a->dp + b; - /* 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. - /* 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++) { + 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; - } - } + /* zero the top digits */ + MP_ZERO_DIGITS(bottom, a->used - x); - /* remove excess digits */ - a->used -= b; + /* remove excess digits */ + a->used -= b; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_rshd.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_sbin_size.c b/lib/hcrypto/libtommath/bn_mp_sbin_size.c new file mode 100644 index 000000000..e0993d690 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_sbin_size.c @@ -0,0 +1,11 @@ +#include "tommath_private.h" +#ifdef BN_MP_SBIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* get the size for an signed equivalent */ +size_t mp_sbin_size(const mp_int *a) +{ + return 1u + mp_ubin_size(a); +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_set.c b/lib/hcrypto/libtommath/bn_mp_set.c index 174adcbc6..44ac6df57 100644 --- a/lib/hcrypto/libtommath/bn_mp_set.c +++ b/lib/hcrypto/libtommath/bn_mp_set.c @@ -1,29 +1,14 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* set to a digit */ -void mp_set (mp_int * a, mp_digit b) +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; + a->dp[0] = b & MP_MASK; + a->sign = MP_ZPOS; + a->used = (a->dp[0] != 0u) ? 1 : 0; + MP_ZERO_DIGITS(a->dp + a->used, a->alloc - a->used); } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_set.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_set_double.c b/lib/hcrypto/libtommath/bn_mp_set_double.c new file mode 100644 index 000000000..a42fc70d9 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set_double.c @@ -0,0 +1,47 @@ +#include "tommath_private.h" +#ifdef BN_MP_SET_DOUBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) +mp_err mp_set_double(mp_int *a, double b) +{ + uint64_t frac; + int exp; + mp_err err; + union { + double dbl; + uint64_t bits; + } cast; + cast.dbl = b; + + exp = (int)((unsigned)(cast.bits >> 52) & 0x7FFu); + frac = (cast.bits & ((1uLL << 52) - 1uLL)) | (1uLL << 52); + + if (exp == 0x7FF) { /* +-inf, NaN */ + return MP_VAL; + } + exp -= 1023 + 52; + + mp_set_u64(a, frac); + + err = (exp < 0) ? mp_div_2d(a, -exp, a, NULL) : mp_mul_2d(a, exp, a); + if (err != MP_OKAY) { + return err; + } + + if (((cast.bits >> 63) != 0uLL) && !MP_IS_ZERO(a)) { + a->sign = MP_NEG; + } + + return MP_OKAY; +} +#else +/* pragma message() not supported by several compilers (in mostly older but still used versions) */ +# ifdef _MSC_VER +# pragma message("mp_set_double implementation is only available on platforms with IEEE754 floating point format") +# else +# warning "mp_set_double implementation is only available on platforms with IEEE754 floating point format" +# endif +#endif +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_set_i32.c b/lib/hcrypto/libtommath/bn_mp_set_i32.c new file mode 100644 index 000000000..df4513d37 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set_i32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_SET_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_i32, mp_set_u32, int32_t, uint32_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_set_i64.c b/lib/hcrypto/libtommath/bn_mp_set_i64.c new file mode 100644 index 000000000..395103bf5 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set_i64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_SET_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_i64, mp_set_u64, int64_t, uint64_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_set_int.c b/lib/hcrypto/libtommath/bn_mp_set_int.c deleted file mode 100644 index 3072e76e1..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_set_int.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_set_l.c b/lib/hcrypto/libtommath/bn_mp_set_l.c new file mode 100644 index 000000000..1e445fb62 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set_l.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_SET_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_l, mp_set_ul, long, unsigned long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_set_ll.c b/lib/hcrypto/libtommath/bn_mp_set_ll.c new file mode 100644 index 000000000..3e2324f32 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set_ll.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_SET_LL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_ll, mp_set_ull, long long, unsigned long long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_set_u32.c b/lib/hcrypto/libtommath/bn_mp_set_u32.c new file mode 100644 index 000000000..18ba5e14c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set_u32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_SET_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_u32, uint32_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_set_u64.c b/lib/hcrypto/libtommath/bn_mp_set_u64.c new file mode 100644 index 000000000..88fab6c54 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set_u64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_SET_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_u64, uint64_t) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_set_ul.c b/lib/hcrypto/libtommath/bn_mp_set_ul.c new file mode 100644 index 000000000..adfd85c7f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set_ul.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_SET_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_ul, unsigned long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_set_ull.c b/lib/hcrypto/libtommath/bn_mp_set_ull.c new file mode 100644 index 000000000..8fbc1bd2c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_set_ull.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef BN_MP_SET_ULL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_ull, unsigned long long) +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_shrink.c b/lib/hcrypto/libtommath/bn_mp_shrink.c index c600efc58..cf27ed9ec 100644 --- a/lib/hcrypto/libtommath/bn_mp_shrink.c +++ b/lib/hcrypto/libtommath/bn_mp_shrink.c @@ -1,40 +1,22 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* shrink a bignum */ -int mp_shrink (mp_int * a) +mp_err 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; + mp_digit *tmp; + int alloc = MP_MAX(MP_MIN_PREC, a->used); + if (a->alloc != alloc) { + if ((tmp = (mp_digit *) MP_REALLOC(a->dp, + (size_t)a->alloc * sizeof(mp_digit), + (size_t)alloc * sizeof(mp_digit))) == NULL) { + return MP_MEM; + } + a->dp = tmp; + a->alloc = alloc; + } + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_shrink.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_signed_bin_size.c b/lib/hcrypto/libtommath/bn_mp_signed_bin_size.c deleted file mode 100644 index 6739d19e2..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_signed_bin_size.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_signed_rsh.c b/lib/hcrypto/libtommath/bn_mp_signed_rsh.c new file mode 100644 index 000000000..8d8d8414d --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_signed_rsh.c @@ -0,0 +1,22 @@ +#include "tommath_private.h" +#ifdef BN_MP_SIGNED_RSH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift right by a certain bit count with sign extension */ +mp_err mp_signed_rsh(const mp_int *a, int b, mp_int *c) +{ + mp_err res; + if (a->sign == MP_ZPOS) { + return mp_div_2d(a, b, c, NULL); + } + + res = mp_add_d(a, 1uL, c); + if (res != MP_OKAY) { + return res; + } + + res = mp_div_2d(c, b, c, NULL); + return (res == MP_OKAY) ? mp_sub_d(c, 1uL, c) : res; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_sqr.c b/lib/hcrypto/libtommath/bn_mp_sqr.c index 90f4dd6d7..e0d0a73e4 100644 --- a/lib/hcrypto/libtommath/bn_mp_sqr.c +++ b/lib/hcrypto/libtommath/bn_mp_sqr.c @@ -1,58 +1,28 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* computes b = a*a */ -int -mp_sqr (mp_int * a, mp_int * b) +mp_err mp_sqr(const 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; + mp_err err; + if (MP_HAS(S_MP_TOOM_SQR) && /* use Toom-Cook? */ + (a->used >= MP_TOOM_SQR_CUTOFF)) { + err = s_mp_toom_sqr(a, b); + } else if (MP_HAS(S_MP_KARATSUBA_SQR) && /* Karatsuba? */ + (a->used >= MP_KARATSUBA_SQR_CUTOFF)) { + err = s_mp_karatsuba_sqr(a, b); + } else if (MP_HAS(S_MP_SQR_FAST) && /* can we use the fast comba multiplier? */ + (((a->used * 2) + 1) < MP_WARRAY) && + (a->used < (MP_MAXFAST / 2))) { + err = s_mp_sqr_fast(a, b); + } else if (MP_HAS(S_MP_SQR)) { + err = s_mp_sqr(a, b); + } else { + err = MP_VAL; + } + b->sign = MP_ZPOS; + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_sqr.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_sqrmod.c b/lib/hcrypto/libtommath/bn_mp_sqrmod.c index 161cbbb30..626ea2c29 100644 --- a/lib/hcrypto/libtommath/bn_mp_sqrmod.c +++ b/lib/hcrypto/libtommath/bn_mp_sqrmod.c @@ -1,41 +1,25 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* c = a * a (mod b) */ -int -mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) +mp_err mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c) { - int res; - mp_int t; + mp_err err; + mp_int t; - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } - if ((res = mp_sqr (a, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - res = mp_mod (&t, b, c); - mp_clear (&t); - return res; + if ((err = mp_sqr(a, &t)) != MP_OKAY) { + goto LBL_ERR; + } + err = mp_mod(&t, b, c); + +LBL_ERR: + mp_clear(&t); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_sqrmod.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_sqrt.c b/lib/hcrypto/libtommath/bn_mp_sqrt.c index 8391297f7..82d682467 100644 --- a/lib/hcrypto/libtommath/bn_mp_sqrt.c +++ b/lib/hcrypto/libtommath/bn_mp_sqrt.c @@ -1,81 +1,67 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* this function is less generic than mp_n_root, simpler and faster */ -int mp_sqrt(mp_int *arg, mp_int *ret) +mp_err mp_sqrt(const mp_int *arg, mp_int *ret) { - int res; - mp_int t1,t2; + mp_err err; + mp_int t1, t2; - /* must be positive */ - if (arg->sign == MP_NEG) { - return MP_VAL; - } + /* 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; - } + /* easy out */ + if (MP_IS_ZERO(arg)) { + mp_zero(ret); + return MP_OKAY; + } - if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) { - return res; - } + if ((err = mp_init_copy(&t1, arg)) != MP_OKAY) { + return err; + } - if ((res = mp_init(&t2)) != MP_OKAY) { - goto E2; - } + if ((err = mp_init(&t2)) != MP_OKAY) { + goto E2; + } - /* First approx. (not very bad for large arg) */ - mp_rshd (&t1,t1.used/2); + /* 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) { + /* t1 > 0 */ + if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { goto E1; - } - if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) { + } + if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { goto E1; - } - if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) { + } + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) { goto E1; - } - /* t1 >= sqrt(arg) >= t2 at this point */ - } while (mp_cmp_mag(&t1,&t2) == MP_GT); + } + /* And now t1 > sqrt(arg) */ + do { + if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { + goto E1; + } + if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { + goto E1; + } + if ((err = 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); + mp_exch(&t1, ret); -E1: mp_clear(&t2); -E2: mp_clear(&t1); - return res; +E1: + mp_clear(&t2); +E2: + mp_clear(&t1); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_sqrt.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_sqrtmod_prime.c b/lib/hcrypto/libtommath/bn_mp_sqrtmod_prime.c new file mode 100644 index 000000000..a833ed7c1 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_sqrtmod_prime.c @@ -0,0 +1,118 @@ +#include "tommath_private.h" +#ifdef BN_MP_SQRTMOD_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Tonelli-Shanks algorithm + * https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm + * https://gmplib.org/list-archives/gmp-discuss/2013-April/005300.html + * + */ + +mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) +{ + mp_err err; + int legendre; + mp_int t1, C, Q, S, Z, M, T, R, two; + mp_digit i; + + /* first handle the simple cases */ + if (mp_cmp_d(n, 0uL) == MP_EQ) { + mp_zero(ret); + return MP_OKAY; + } + if (mp_cmp_d(prime, 2uL) == MP_EQ) return MP_VAL; /* prime must be odd */ + if ((err = mp_kronecker(n, prime, &legendre)) != MP_OKAY) return err; + if (legendre == -1) return MP_VAL; /* quadratic non-residue mod prime */ + + if ((err = mp_init_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL)) != MP_OKAY) { + return err; + } + + /* SPECIAL CASE: if prime mod 4 == 3 + * compute directly: err = n^(prime+1)/4 mod prime + * Handbook of Applied Cryptography algorithm 3.36 + */ + if ((err = mp_mod_d(prime, 4uL, &i)) != MP_OKAY) goto cleanup; + if (i == 3u) { + if ((err = mp_add_d(prime, 1uL, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_exptmod(n, &t1, prime, ret)) != MP_OKAY) goto cleanup; + err = MP_OKAY; + goto cleanup; + } + + /* NOW: Tonelli-Shanks algorithm */ + + /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */ + if ((err = mp_copy(prime, &Q)) != MP_OKAY) goto cleanup; + if ((err = mp_sub_d(&Q, 1uL, &Q)) != MP_OKAY) goto cleanup; + /* Q = prime - 1 */ + mp_zero(&S); + /* S = 0 */ + while (MP_IS_EVEN(&Q)) { + if ((err = mp_div_2(&Q, &Q)) != MP_OKAY) goto cleanup; + /* Q = Q / 2 */ + if ((err = mp_add_d(&S, 1uL, &S)) != MP_OKAY) goto cleanup; + /* S = S + 1 */ + } + + /* find a Z such that the Legendre symbol (Z|prime) == -1 */ + mp_set_u32(&Z, 2u); + /* Z = 2 */ + for (;;) { + if ((err = mp_kronecker(&Z, prime, &legendre)) != MP_OKAY) goto cleanup; + if (legendre == -1) break; + if ((err = mp_add_d(&Z, 1uL, &Z)) != MP_OKAY) goto cleanup; + /* Z = Z + 1 */ + } + + if ((err = mp_exptmod(&Z, &Q, prime, &C)) != MP_OKAY) goto cleanup; + /* C = Z ^ Q mod prime */ + if ((err = mp_add_d(&Q, 1uL, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup; + /* t1 = (Q + 1) / 2 */ + if ((err = mp_exptmod(n, &t1, prime, &R)) != MP_OKAY) goto cleanup; + /* R = n ^ ((Q + 1) / 2) mod prime */ + if ((err = mp_exptmod(n, &Q, prime, &T)) != MP_OKAY) goto cleanup; + /* T = n ^ Q mod prime */ + if ((err = mp_copy(&S, &M)) != MP_OKAY) goto cleanup; + /* M = S */ + mp_set_u32(&two, 2u); + + for (;;) { + if ((err = mp_copy(&T, &t1)) != MP_OKAY) goto cleanup; + i = 0; + for (;;) { + if (mp_cmp_d(&t1, 1uL) == MP_EQ) break; + if ((err = mp_exptmod(&t1, &two, prime, &t1)) != MP_OKAY) goto cleanup; + i++; + } + if (i == 0u) { + if ((err = mp_copy(&R, ret)) != MP_OKAY) goto cleanup; + err = MP_OKAY; + goto cleanup; + } + if ((err = mp_sub_d(&M, i, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_exptmod(&two, &t1, prime, &t1)) != MP_OKAY) goto cleanup; + /* t1 = 2 ^ (M - i - 1) */ + if ((err = mp_exptmod(&C, &t1, prime, &t1)) != MP_OKAY) goto cleanup; + /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ + if ((err = mp_sqrmod(&t1, prime, &C)) != MP_OKAY) goto cleanup; + /* C = (t1 * t1) mod prime */ + if ((err = mp_mulmod(&R, &t1, prime, &R)) != MP_OKAY) goto cleanup; + /* R = (R * t1) mod prime */ + if ((err = mp_mulmod(&T, &C, prime, &T)) != MP_OKAY) goto cleanup; + /* T = (T * C) mod prime */ + mp_set(&M, i); + /* M = i */ + } + +cleanup: + mp_clear_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL); + return err; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_sub.c b/lib/hcrypto/libtommath/bn_mp_sub.c index f5015cce4..c1ea39e11 100644 --- a/lib/hcrypto/libtommath/bn_mp_sub.c +++ b/lib/hcrypto/libtommath/bn_mp_sub.c @@ -1,59 +1,40 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* high level subtraction (handles signs) */ -int -mp_sub (mp_int * a, mp_int * b, mp_int * c) +mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c) { - int sa, sb, res; + mp_sign sa = a->sign, sb = b->sign; + mp_err err; - 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 */ + 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; - /* 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; + err = 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 */ + err = 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 */ + err = s_mp_sub(b, a, c); + } + } + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_sub.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_sub_d.c b/lib/hcrypto/libtommath/bn_mp_sub_d.c index 06cdca636..3ebf9b485 100644 --- a/lib/hcrypto/libtommath/bn_mp_sub_d.c +++ b/lib/hcrypto/libtommath/bn_mp_sub_d.c @@ -1,93 +1,74 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* single digit subtraction */ -int -mp_sub_d (mp_int * a, mp_digit b, mp_int * c) +mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c) { - mp_digit *tmpa, *tmpc, mu; - int res, ix, oldused; + mp_digit *tmpa, *tmpc; + mp_err err; + int ix, oldused; - /* grow c as required */ - if (c->alloc < a->used + 1) { - if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { - return res; - } - } + /* grow c as required */ + if (c->alloc < (a->used + 1)) { + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + } - /* 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; + /* if a is negative just do an unsigned + * addition [with fudged signs] + */ + if (a->sign == MP_NEG) { + mp_int a_ = *a; + a_.sign = MP_ZPOS; + err = mp_add_d(&a_, b, c); + c->sign = MP_NEG; - /* clamp */ - mp_clamp(c); + /* clamp */ + mp_clamp(c); - return res; - } + return err; + } - /* setup regs */ - oldused = c->used; - tmpa = a->dp; - tmpc = c->dp; + /* 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; + /* 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; + /* negative/1digit */ + c->sign = MP_NEG; + c->used = 1; + } else { + mp_digit mu = b; - /* subtract first digit */ - *tmpc = *tmpa++ - b; - mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); - *tmpc++ &= MP_MASK; + /* positive/size */ + c->sign = MP_ZPOS; + c->used = a->used; - /* 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; - } - } + /* subtract digits, mu is carry */ + for (ix = 0; ix < a->used; ix++) { + *tmpc = *tmpa++ - mu; + mu = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u); + *tmpc++ &= MP_MASK; + } + } - /* zero excess digits */ - while (ix++ < oldused) { - *tmpc++ = 0; - } - mp_clamp(c); - return MP_OKAY; + /* zero excess digits */ + MP_ZERO_DIGITS(tmpc, oldused - ix); + + mp_clamp(c); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_sub_d.c,v $ */ -/* $Revision: 1.6 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_submod.c b/lib/hcrypto/libtommath/bn_mp_submod.c index 869e23cde..5ebd37498 100644 --- a/lib/hcrypto/libtommath/bn_mp_submod.c +++ b/lib/hcrypto/libtommath/bn_mp_submod.c @@ -1,42 +1,25 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* d = a - b (mod c) */ -int -mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) { - int res; - mp_int t; + mp_err err; + mp_int t; + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } + if ((err = mp_sub(a, b, &t)) != MP_OKAY) { + goto LBL_ERR; + } + err = mp_mod(&t, c, d); - 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; +LBL_ERR: + mp_clear(&t); + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_submod.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_to_radix.c b/lib/hcrypto/libtommath/bn_mp_to_radix.c new file mode 100644 index 000000000..7fa86cae1 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_to_radix.c @@ -0,0 +1,84 @@ +#include "tommath_private.h" +#ifdef BN_MP_TO_RADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* stores a bignum as a ASCII string in a given radix (2..64) + * + * Stores upto "size - 1" chars and always a NULL byte, puts the number of characters + * written, including the '\0', in "written". + */ +mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) +{ + size_t digs; + mp_err err; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of radix and size*/ + if (maxlen < 2u) { + return MP_BUF; + } + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + /* quick out if its zero */ + if (MP_IS_ZERO(a)) { + *str++ = '0'; + *str = '\0'; + if (written != NULL) { + *written = 2u; + } + return MP_OKAY; + } + + if ((err = mp_init_copy(&t, a)) != MP_OKAY) { + return err; + } + + /* 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 = 0u; + while (!MP_IS_ZERO(&t)) { + if (--maxlen < 1u) { + /* no more room */ + err = MP_BUF; + goto LBL_ERR; + } + if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) { + goto LBL_ERR; + } + *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 + */ + s_mp_reverse((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + digs++; + + if (written != NULL) { + *written = (a->sign == MP_NEG) ? (digs + 1u): digs; + } + +LBL_ERR: + mp_clear(&t); + return err; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_to_sbin.c b/lib/hcrypto/libtommath/bn_mp_to_sbin.c new file mode 100644 index 000000000..dbaf53e1f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_to_sbin.c @@ -0,0 +1,22 @@ +#include "tommath_private.h" +#ifdef BN_MP_TO_SBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* store in signed [big endian] format */ +mp_err mp_to_sbin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) +{ + mp_err err; + if (maxlen == 0u) { + return MP_BUF; + } + if ((err = mp_to_ubin(a, buf + 1, maxlen - 1u, written)) != MP_OKAY) { + return err; + } + if (written != NULL) { + (*written)++; + } + buf[0] = (a->sign == MP_ZPOS) ? (unsigned char)0 : (unsigned char)1; + return MP_OKAY; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_to_signed_bin.c b/lib/hcrypto/libtommath/bn_mp_to_signed_bin.c deleted file mode 100644 index 9df83ca52..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_to_signed_bin.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c b/lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c deleted file mode 100644 index 677f827d4..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_to_signed_bin_n.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_to_ubin.c b/lib/hcrypto/libtommath/bn_mp_to_ubin.c new file mode 100644 index 000000000..1681ca7ce --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_to_ubin.c @@ -0,0 +1,41 @@ +#include "tommath_private.h" +#ifdef BN_MP_TO_UBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* store in unsigned [big endian] format */ +mp_err mp_to_ubin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) +{ + size_t x, count; + mp_err err; + mp_int t; + + count = mp_ubin_size(a); + if (count > maxlen) { + return MP_BUF; + } + + if ((err = mp_init_copy(&t, a)) != MP_OKAY) { + return err; + } + + for (x = count; x --> 0u;) { +#ifndef MP_8BIT + buf[x] = (unsigned char)(t.dp[0] & 255u); +#else + buf[x] = (unsigned char)(t.dp[0] | ((t.dp[1] & 1u) << 7)); +#endif + if ((err = mp_div_2d(&t, 8, &t, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + } + + if (written != NULL) { + *written = count; + } + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c b/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c deleted file mode 100644 index c137f104a..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c b/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c deleted file mode 100644 index 0dc00c623..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_to_unsigned_bin_n.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_toom_mul.c b/lib/hcrypto/libtommath/bn_mp_toom_mul.c deleted file mode 100644 index b99634246..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_toom_mul.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_toom_sqr.c b/lib/hcrypto/libtommath/bn_mp_toom_sqr.c deleted file mode 100644 index 48880d035..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_toom_sqr.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_toradix.c b/lib/hcrypto/libtommath/bn_mp_toradix.c deleted file mode 100644 index 0adc28d2f..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_toradix.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_toradix_n.c b/lib/hcrypto/libtommath/bn_mp_toradix_n.c deleted file mode 100644 index 28085124e..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_toradix_n.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_ubin_size.c b/lib/hcrypto/libtommath/bn_mp_ubin_size.c new file mode 100644 index 000000000..21230b48c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_ubin_size.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef BN_MP_UBIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* get the size for an unsigned equivalent */ +size_t mp_ubin_size(const mp_int *a) +{ + size_t size = (size_t)mp_count_bits(a); + return (size / 8u) + (((size & 7u) != 0u) ? 1u : 0u); +} +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_unpack.c b/lib/hcrypto/libtommath/bn_mp_unpack.c new file mode 100644 index 000000000..d4eb90e0c --- /dev/null +++ b/lib/hcrypto/libtommath/bn_mp_unpack.c @@ -0,0 +1,49 @@ +#include "tommath_private.h" +#ifdef BN_MP_UNPACK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on gmp's mpz_import. + * see http://gmplib.org/manual/Integer-Import-and-Export.html + */ +mp_err mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size, + mp_endian endian, size_t nails, const void *op) +{ + mp_err err; + size_t odd_nails, nail_bytes, i, j; + unsigned char odd_nail_mask; + + mp_zero(rop); + + if (endian == MP_NATIVE_ENDIAN) { + MP_GET_ENDIANNESS(endian); + } + + odd_nails = (nails % 8u); + odd_nail_mask = 0xff; + for (i = 0; i < odd_nails; ++i) { + odd_nail_mask ^= (unsigned char)(1u << (7u - i)); + } + nail_bytes = nails / 8u; + + for (i = 0; i < count; ++i) { + for (j = 0; j < (size - nail_bytes); ++j) { + unsigned char byte = *((const unsigned char *)op + + (((order == MP_MSB_FIRST) ? i : ((count - 1u) - i)) * size) + + ((endian == MP_BIG_ENDIAN) ? (j + nail_bytes) : (((size - 1u) - j) - nail_bytes))); + + if ((err = mp_mul_2d(rop, (j == 0u) ? (int)(8u - odd_nails) : 8, rop)) != MP_OKAY) { + return err; + } + + rop->dp[0] |= (j == 0u) ? (mp_digit)(byte & odd_nail_mask) : (mp_digit)byte; + rop->used += 1; + } + } + + mp_clamp(rop); + + return MP_OKAY; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c b/lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c deleted file mode 100644 index 6dc3bd5fc..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_mp_unsigned_bin_size.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_xor.c b/lib/hcrypto/libtommath/bn_mp_xor.c index 59ff2e183..71e7ca187 100644 --- a/lib/hcrypto/libtommath/bn_mp_xor.c +++ b/lib/hcrypto/libtommath/bn_mp_xor.c @@ -1,51 +1,56 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ -/* XOR two ints together */ -int -mp_xor (mp_int * a, mp_int * b, mp_int * c) +/* two complement xor */ +mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c) { - int res, ix, px; - mp_int t, *x; + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + mp_sign csign = (a->sign != b->sign) ? MP_NEG : MP_ZPOS; - 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; - } + if (c->alloc < used) { + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + } - 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; + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (a->sign == MP_NEG) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (b->sign == MP_NEG) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x ^ y; + + /* convert to to sign-magnitude if negative */ + if (csign == MP_NEG) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = csign; + mp_clamp(c); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_xor.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_zero.c b/lib/hcrypto/libtommath/bn_mp_zero.c index b0977d443..72a255efc 100644 --- a/lib/hcrypto/libtommath/bn_mp_zero.c +++ b/lib/hcrypto/libtommath/bn_mp_zero.c @@ -1,36 +1,13 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* set to zero */ -void mp_zero (mp_int * a) +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; - } + a->sign = MP_ZPOS; + a->used = 0; + MP_ZERO_DIGITS(a->dp, a->alloc); } #endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_zero.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_mp_zero_multi.c b/lib/hcrypto/libtommath/bn_mp_zero_multi.c deleted file mode 100644 index 339a75fbf..000000000 --- a/lib/hcrypto/libtommath/bn_mp_zero_multi.c +++ /dev/null @@ -1,35 +0,0 @@ -#include -#ifdef BN_MP_ZERO_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 - -/* set to zero */ -void mp_zero_multi (mp_int * mp, ...) -{ - mp_int* next_mp = mp; - va_list args; - va_start(args, mp); - while (next_mp != NULL) { - mp_zero(next_mp); - next_mp = va_arg(args, mp_int*); - } - va_end(args); -} -#endif - -/* $Source: /cvs/libtom/libtommath/bn_mp_zero.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_prime_tab.c b/lib/hcrypto/libtommath/bn_prime_tab.c index bd252477e..a6c07f8da 100644 --- a/lib/hcrypto/libtommath/bn_prime_tab.c +++ b/lib/hcrypto/libtommath/bn_prime_tab.c @@ -1,61 +1,61 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + 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, + 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, + 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, + 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, + 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 + 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 }; + +#if defined(__GNUC__) && __GNUC__ >= 4 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +const mp_digit *s_mp_prime_tab = ltm_prime_tab; +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) && _MSC_VER >= 1500 +#pragma warning(push) +#pragma warning(disable: 4996) +const mp_digit *s_mp_prime_tab = ltm_prime_tab; +#pragma warning(pop) +#else +const mp_digit *s_mp_prime_tab = ltm_prime_tab; #endif -/* $Source: /cvs/libtom/libtommath/bn_prime_tab.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ +#endif diff --git a/lib/hcrypto/libtommath/bn_reverse.c b/lib/hcrypto/libtommath/bn_reverse.c deleted file mode 100644 index ddfa827a0..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bn_reverse.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_add.c b/lib/hcrypto/libtommath/bn_s_mp_add.c index e7f54f4cf..c946aa80d 100644 --- a/lib/hcrypto/libtommath/bn_s_mp_add.c +++ b/lib/hcrypto/libtommath/bn_s_mp_add.c @@ -1,109 +1,91 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) { - mp_int *x; - int olduse, res, min, max; + const mp_int *x; + mp_err err; + int olduse, 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; - } + /* 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; + /* init result */ + if (c->alloc < (max + 1)) { + if ((err = mp_grow(c, max + 1)) != MP_OKAY) { + return err; } - } + } - /* add carry */ - *tmpc++ = u; + /* get old used digit count and set new one */ + olduse = c->used; + c->used = max + 1; - /* clear digits above oldused */ - for (i = c->used; i < olduse; i++) { - *tmpc++ = 0; - } - } + { + mp_digit u, *tmpa, *tmpb, *tmpc; + int i; - mp_clamp (c); - return MP_OKAY; + /* 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)MP_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)MP_DIGIT_BIT; + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + } + + /* add carry */ + *tmpc++ = u; + + /* clear digits above oldused */ + MP_ZERO_DIGITS(tmpc, olduse - c->used); + } + + mp_clamp(c); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_s_mp_add.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_balance_mul.c b/lib/hcrypto/libtommath/bn_s_mp_balance_mul.c new file mode 100644 index 000000000..7ece5d794 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_balance_mul.c @@ -0,0 +1,81 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_BALANCE_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single-digit multiplication with the smaller number as the single-digit */ +mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + int count, len_a, len_b, nblocks, i, j, bsize; + mp_int a0, tmp, A, B, r; + mp_err err; + + len_a = a->used; + len_b = b->used; + + nblocks = MP_MAX(a->used, b->used) / MP_MIN(a->used, b->used); + bsize = MP_MIN(a->used, b->used) ; + + if ((err = mp_init_size(&a0, bsize + 2)) != MP_OKAY) { + return err; + } + if ((err = mp_init_multi(&tmp, &r, NULL)) != MP_OKAY) { + mp_clear(&a0); + return err; + } + + /* Make sure that A is the larger one*/ + if (len_a < len_b) { + B = *a; + A = *b; + } else { + A = *a; + B = *b; + } + + for (i = 0, j=0; i < nblocks; i++) { + /* Cut a slice off of a */ + a0.used = 0; + for (count = 0; count < bsize; count++) { + a0.dp[count] = A.dp[ j++ ]; + a0.used++; + } + mp_clamp(&a0); + /* Multiply with b */ + if ((err = mp_mul(&a0, &B, &tmp)) != MP_OKAY) { + goto LBL_ERR; + } + /* Shift tmp to the correct position */ + if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) { + goto LBL_ERR; + } + /* Add to output. No carry needed */ + if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* The left-overs; there are always left-overs */ + if (j < A.used) { + a0.used = 0; + for (count = 0; j < A.used; count++) { + a0.dp[count] = A.dp[ j++ ]; + a0.used++; + } + mp_clamp(&a0); + if ((err = mp_mul(&a0, &B, &tmp)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) { + goto LBL_ERR; + } + } + + mp_exch(&r,c); +LBL_ERR: + mp_clear_multi(&a0, &tmp, &r,NULL); + return err; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_exptmod.c b/lib/hcrypto/libtommath/bn_s_mp_exptmod.c index deb4b4ddb..c3bfa95e8 100644 --- a/lib/hcrypto/libtommath/bn_s_mp_exptmod.c +++ b/lib/hcrypto/libtommath/bn_s_mp_exptmod.c @@ -1,252 +1,198 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + #ifdef MP_LOW_MEM - #define TAB_SIZE 32 +# define TAB_SIZE 32 +# define MAX_WINSIZE 5 #else - #define TAB_SIZE 256 +# define TAB_SIZE 256 +# define MAX_WINSIZE 0 #endif -int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) +mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const 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*); + mp_int M[TAB_SIZE], res, mu; + mp_digit buf; + mp_err err; + int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + mp_err(*redux)(mp_int *x, const mp_int *m, const mp_int *mu); - /* 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; - } + /* 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 + winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize; - /* 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]); + /* init M array */ + /* init first cell */ + if ((err = mp_init(&M[1])) != MP_OKAY) { 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; + /* 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; } - /* 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; + /* create mu, used for Barrett reduction */ + if ((err = mp_init(&mu)) != MP_OKAY) goto LBL_M; - /* 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 (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; + } - /* 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; - } + /* 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; - /* else we add it to the window */ - bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; + /* compute the value at M[1<<(winsize-1)] by squaring + * M[1] (winsize-1) times + */ + if ((err = mp_copy(&M[1], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU; - 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; - } + for (x = 0; x < (winsize - 1); x++) { + /* square it */ + if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)], + &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU; + + /* reduce modulo P */ + if ((err = redux(&M[(size_t)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, 1uL); + + /* 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)MP_DIGIT_BIT; } - /* 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; + /* grab the next msb from the exponent */ + y = (buf >> (mp_digit)(MP_DIGIT_BIT - 1)) & 1uL; + 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; } - /* 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; + /* 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; } - 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; - } - } - } - } + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; - mp_exch (&res, Y); - err = MP_OKAY; -LBL_RES:mp_clear (&res); -LBL_MU:mp_clear (&mu); + 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; + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear(&M[x]); + } + return err; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_s_mp_exptmod.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_exptmod_fast.c b/lib/hcrypto/libtommath/bn_s_mp_exptmod_fast.c new file mode 100644 index 000000000..682ded845 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_exptmod_fast.c @@ -0,0 +1,254 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_EXPTMOD_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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 +# define MAX_WINSIZE 5 +#else +# define TAB_SIZE 256 +# define MAX_WINSIZE 0 +#endif + +mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) +{ + mp_int M[TAB_SIZE], res; + mp_digit buf, mp; + int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + mp_err err; + + /* 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. + */ + mp_err(*redux)(mp_int *x, const mp_int *n, mp_digit rho); + + /* 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; + } + + winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize; + + /* init M array */ + /* init first cell */ + if ((err = mp_init_size(&M[1], P->alloc)) != 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_size(&M[x], P->alloc)) != 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) { + if (MP_HAS(MP_MONTGOMERY_SETUP)) { + /* now setup montgomery */ + if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) goto LBL_M; + } else { + err = MP_VAL; + goto LBL_M; + } + + /* automatically pick the comba one if available (saves quite a few calls/ifs) */ + if (MP_HAS(S_MP_MONTGOMERY_REDUCE_FAST) && + (((P->used * 2) + 1) < MP_WARRAY) && + (P->used < MP_MAXFAST)) { + redux = s_mp_montgomery_reduce_fast; + } else if (MP_HAS(MP_MONTGOMERY_REDUCE)) { + /* use slower baseline Montgomery method */ + redux = mp_montgomery_reduce; + } else { + err = MP_VAL; + goto LBL_M; + } + } else if (redmode == 1) { + if (MP_HAS(MP_DR_SETUP) && MP_HAS(MP_DR_REDUCE)) { + /* 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; + } + } else if (MP_HAS(MP_REDUCE_2K_SETUP) && MP_HAS(MP_REDUCE_2K)) { + /* 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; + } + + /* setup result */ + if ((err = mp_init_size(&res, P->alloc)) != 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) { + if (MP_HAS(MP_MONTGOMERY_CALC_NORMALIZATION)) { + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization(&res, P)) != MP_OKAY) goto LBL_RES; + + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod(G, &res, P, &M[1])) != MP_OKAY) goto LBL_RES; + } else { + err = MP_VAL; + goto LBL_RES; + } + } else { + mp_set(&res, 1uL); + 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[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_RES; + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_RES; + if ((err = redux(&M[(size_t)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)MP_DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (mp_digit)(buf >> (MP_DIGIT_BIT - 1)) & 1uL; + 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 diff --git a/lib/hcrypto/libtommath/bn_s_mp_get_bit.c b/lib/hcrypto/libtommath/bn_s_mp_get_bit.c new file mode 100644 index 000000000..28598dfec --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_get_bit.c @@ -0,0 +1,21 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_GET_BIT_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Get bit at position b and return MP_YES if the bit is 1, MP_NO if it is 0 */ +mp_bool s_mp_get_bit(const mp_int *a, unsigned int b) +{ + mp_digit bit; + int limb = (int)(b / MP_DIGIT_BIT); + + if (limb >= a->used) { + return MP_NO; + } + + bit = (mp_digit)1 << (b % MP_DIGIT_BIT); + return ((a->dp[limb] & bit) != 0u) ? MP_YES : MP_NO; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_invmod_fast.c b/lib/hcrypto/libtommath/bn_s_mp_invmod_fast.c new file mode 100644 index 000000000..677d7ab69 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_invmod_fast.c @@ -0,0 +1,118 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_INVMOD_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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 + */ +mp_err s_mp_invmod_fast(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x, y, u, v, B, D; + mp_sign neg; + mp_err err; + + /* 2. [modified] b must be odd */ + if (MP_IS_EVEN(b)) { + return MP_VAL; + } + + /* init all our temps */ + if ((err = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { + return err; + } + + /* x == modulus, y == value to invert */ + if ((err = mp_copy(b, &x)) != MP_OKAY) goto LBL_ERR; + + /* we need y = |a| */ + if ((err = mp_mod(a, b, &y)) != MP_OKAY) goto LBL_ERR; + + /* if one of x,y is zero return an error! */ + if (MP_IS_ZERO(&x) || MP_IS_ZERO(&y)) { + err = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR; + mp_set(&D, 1uL); + +top: + /* 4. while u is even do */ + while (MP_IS_EVEN(&u)) { + /* 4.1 u = u/2 */ + if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR; + + /* 4.2 if B is odd then */ + if (MP_IS_ODD(&B)) { + if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR; + } + /* B = B/2 */ + if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR; + } + + /* 5. while v is even do */ + while (MP_IS_EVEN(&v)) { + /* 5.1 v = v/2 */ + if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR; + + /* 5.2 if D is odd then */ + if (MP_IS_ODD(&D)) { + /* D = (D-x)/2 */ + if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR; + } + /* D = D/2 */ + if ((err = 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 ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR; + } else { + /* v - v - u, D = D - B */ + if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* if not zero goto step 4 */ + if (!MP_IS_ZERO(&u)) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d(&v, 1uL) != MP_EQ) { + err = MP_VAL; + goto LBL_ERR; + } + + /* b is now the inverse */ + neg = a->sign; + while (D.sign == MP_NEG) { + if ((err = mp_add(&D, b, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* too big */ + while (mp_cmp_mag(&D, b) != MP_LT) { + if ((err = mp_sub(&D, b, &D)) != MP_OKAY) goto LBL_ERR; + } + + mp_exch(&D, c); + c->sign = neg; + err = MP_OKAY; + +LBL_ERR: + mp_clear_multi(&x, &y, &u, &v, &B, &D, NULL); + return err; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_invmod_slow.c b/lib/hcrypto/libtommath/bn_s_mp_invmod_slow.c new file mode 100644 index 000000000..4c5db3300 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_invmod_slow.c @@ -0,0 +1,119 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_INVMOD_SLOW_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* hac 14.61, pp608 */ +mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x, y, u, v, A, B, C, D; + mp_err err; + + /* b cannot be negative */ + if ((b->sign == MP_NEG) || MP_IS_ZERO(b)) { + return MP_VAL; + } + + /* init temps */ + if ((err = mp_init_multi(&x, &y, &u, &v, + &A, &B, &C, &D, NULL)) != MP_OKAY) { + return err; + } + + /* x = a, y = b */ + if ((err = mp_mod(a, b, &x)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(b, &y)) != MP_OKAY) goto LBL_ERR; + + /* 2. [modified] if x,y are both even then return an error! */ + if (MP_IS_EVEN(&x) && MP_IS_EVEN(&y)) { + err = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR; + mp_set(&A, 1uL); + mp_set(&D, 1uL); + +top: + /* 4. while u is even do */ + while (MP_IS_EVEN(&u)) { + /* 4.1 u = u/2 */ + if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR; + + /* 4.2 if A or B is odd then */ + if (MP_IS_ODD(&A) || MP_IS_ODD(&B)) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((err = mp_add(&A, &y, &A)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR; + } + /* A = A/2, B = B/2 */ + if ((err = mp_div_2(&A, &A)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR; + } + + /* 5. while v is even do */ + while (MP_IS_EVEN(&v)) { + /* 5.1 v = v/2 */ + if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR; + + /* 5.2 if C or D is odd then */ + if (MP_IS_ODD(&C) || MP_IS_ODD(&D)) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((err = mp_add(&C, &y, &C)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR; + } + /* C = C/2, D = D/2 */ + if ((err = mp_div_2(&C, &C)) != MP_OKAY) goto LBL_ERR; + if ((err = 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 ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&A, &C, &A)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR; + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&C, &A, &C)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* if not zero goto step 4 */ + if (!MP_IS_ZERO(&u)) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d(&v, 1uL) != MP_EQ) { + err = MP_VAL; + goto LBL_ERR; + } + + /* if its too low */ + while (mp_cmp_d(&C, 0uL) == MP_LT) { + if ((err = mp_add(&C, b, &C)) != MP_OKAY) goto LBL_ERR; + } + + /* too big */ + while (mp_cmp_mag(&C, b) != MP_LT) { + if ((err = mp_sub(&C, b, &C)) != MP_OKAY) goto LBL_ERR; + } + + /* C is now the inverse */ + mp_exch(&C, c); + err = MP_OKAY; +LBL_ERR: + mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL); + return err; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_karatsuba_mul.c b/lib/hcrypto/libtommath/bn_s_mp_karatsuba_mul.c new file mode 100644 index 000000000..85899fb87 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_karatsuba_mul.c @@ -0,0 +1,174 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_KARATSUBA_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* c = |a| * |b| using Karatsuba Multiplication using + * three half size multiplications + * + * Let B represent the radix [e.g. 2**MP_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. + */ +mp_err s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x0, x1, y0, y1, t1, x0y0, x1y1; + int B; + mp_err err = MP_MEM; /* default the return code to an error */ + + /* min # of digits */ + B = MP_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 LBL_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; + + { + int x; + 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))<used; + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if (mp_init_size(&x0, B) != MP_OKAY) + goto LBL_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; + + { + int x; + 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))<used > MP_WARRAY) { + return MP_VAL; + } + + /* get old used count */ + olduse = x->used; + + /* grow a as required */ + if (x->alloc < (n->used + 1)) { + if ((err = mp_grow(x, n->used + 1)) != MP_OKAY) { + return err; + } + } + + /* first we have to get the digits of the input into + * an array of double precision words W[...] + */ + { + mp_word *_W; + 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] */ + if (ix < ((n->used * 2) + 1)) { + MP_ZERO_BUFFER(_W, sizeof(mp_word) * (size_t)(((n->used * 2) + 1) - ix)); + } + } + + /* 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) + */ + mp_digit mu; + mu = ((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 + */ + { + int iy; + mp_digit *tmpn; + 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)MP_DIGIT_BIT; + } + + /* now we have to propagate the carries and + * shift the words downward [all those least + * significant digits we zeroed]. + */ + { + mp_digit *tmpx; + 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)MP_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++ = *_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 + */ + MP_ZERO_DIGITS(tmpx, olduse - ix); + } + + /* 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 diff --git a/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c b/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c index c5892181f..64509d4cb 100644 --- a/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c +++ b/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c @@ -1,90 +1,74 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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_err s_mp_mul_digs(const mp_int *a, const 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; + mp_int t; + mp_err err; + int 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); - } + /* can we use the fast multiplier? */ + if ((digs < MP_WARRAY) && + (MP_MIN(a->used, b->used) < MP_MAXFAST)) { + return s_mp_mul_digs_fast(a, b, c, digs); + } - if ((res = mp_init_size (&t, digs)) != MP_OKAY) { - return res; - } - t.used = digs; + if ((err = mp_init_size(&t, digs)) != MP_OKAY) { + return err; + } + 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; + /* 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); + /* limit ourselves to making digs digits of output */ + pb = MP_MIN(b->used, digs - ix); - /* setup some aliases */ - /* copy of the digit from a used within the nested loop */ - tmpx = a->dp[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 destination shifted ix places */ + tmpt = t.dp + ix; - /* an alias for the digits of b */ - tmpy = b->dp; + /* 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); + /* 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)); + /* 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; - } - } + /* get the carry word from the result */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + /* set carry if it is placed below digs */ + if ((ix + iy) < digs) { + *tmpt = u; + } + } - mp_clamp (&t); - mp_exch (&t, c); + mp_clamp(&t); + mp_exch(&t, c); - mp_clear (&t); - return MP_OKAY; + mp_clear(&t); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_digs.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_mul_digs_fast.c b/lib/hcrypto/libtommath/bn_s_mp_mul_digs_fast.c new file mode 100644 index 000000000..b2a287b02 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_mul_digs_fast.c @@ -0,0 +1,90 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_MUL_DIGS_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. + * + */ +mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + int olduse, pa, ix, iz; + mp_err err; + mp_digit W[MP_WARRAY]; + mp_word _W; + + /* grow the destination as required */ + if (c->alloc < digs) { + if ((err = mp_grow(c, digs)) != MP_OKAY) { + return err; + } + } + + /* number of output digits to produce */ + pa = MP_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 = MP_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 = MP_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)MP_DIGIT_BIT; + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + mp_digit *tmpc; + tmpc = c->dp; + for (ix = 0; 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] */ + MP_ZERO_DIGITS(tmpc, olduse - ix); + } + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c b/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c index 2b718f23c..2bb2a5098 100644 --- a/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c +++ b/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c @@ -1,81 +1,64 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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_err s_mp_mul_high_digs(const mp_int *a, const 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; + mp_int t; + int pa, pb, ix, iy; + mp_err err; + 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 + /* can we use the fast multiplier? */ + if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST) + && ((a->used + b->used + 1) < MP_WARRAY) + && (MP_MIN(a->used, b->used) < MP_MAXFAST)) { + return s_mp_mul_high_digs_fast(a, b, c, digs); + } - if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { - return res; - } - t.used = a->used + b->used + 1; + if ((err = mp_init_size(&t, a->used + b->used + 1)) != MP_OKAY) { + return err; + } + t.used = a->used + b->used + 1; - pa = a->used; - pb = b->used; - for (ix = 0; ix < pa; ix++) { - /* clear the carry */ - u = 0; + 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]; + /* 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 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); + /* 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); + 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)); + /* 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; + /* carry the carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + *tmpt = u; + } + mp_clamp(&t); + mp_exch(&t, c); + mp_clear(&t); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_high_digs.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs_fast.c b/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs_fast.c new file mode 100644 index 000000000..a2c4fb692 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs_fast.c @@ -0,0 +1,81 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_MUL_HIGH_DIGS_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. + */ +mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + int olduse, pa, ix, iz; + mp_err err; + mp_digit W[MP_WARRAY]; + mp_word _W; + + /* grow the destination as required */ + pa = a->used + b->used; + if (c->alloc < pa) { + if ((err = mp_grow(c, pa)) != MP_OKAY) { + return err; + } + } + + /* 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 = MP_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 = MP_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)MP_DIGIT_BIT; + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + 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] */ + MP_ZERO_DIGITS(tmpc, olduse - ix); + } + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_prime_is_divisible.c b/lib/hcrypto/libtommath/bn_s_mp_prime_is_divisible.c new file mode 100644 index 000000000..ffd5093e6 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_prime_is_divisible.c @@ -0,0 +1,35 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_PRIME_IS_DIVISIBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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 + */ +mp_err s_mp_prime_is_divisible(const mp_int *a, mp_bool *result) +{ + int ix; + mp_err err; + mp_digit res; + + /* default to not */ + *result = MP_NO; + + for (ix = 0; ix < PRIVATE_MP_PRIME_TAB_SIZE; ix++) { + /* what is a mod LBL_prime_tab[ix] */ + if ((err = mp_mod_d(a, s_mp_prime_tab[ix], &res)) != MP_OKAY) { + return err; + } + + /* is the residue zero? */ + if (res == 0u) { + *result = MP_YES; + return MP_OKAY; + } + } + + return MP_OKAY; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_rand_jenkins.c b/lib/hcrypto/libtommath/bn_s_mp_rand_jenkins.c new file mode 100644 index 000000000..da0771c5f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_rand_jenkins.c @@ -0,0 +1,52 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_RAND_JENKINS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Bob Jenkins' http://burtleburtle.net/bob/rand/smallprng.html */ +/* Chosen for speed and a good "mix" */ +typedef struct { + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; +} ranctx; + +static ranctx jenkins_x; + +#define rot(x,k) (((x)<<(k))|((x)>>(64-(k)))) +static uint64_t s_rand_jenkins_val(void) +{ + uint64_t e = jenkins_x.a - rot(jenkins_x.b, 7); + jenkins_x.a = jenkins_x.b ^ rot(jenkins_x.c, 13); + jenkins_x.b = jenkins_x.c + rot(jenkins_x.d, 37); + jenkins_x.c = jenkins_x.d + e; + jenkins_x.d = e + jenkins_x.a; + return jenkins_x.d; +} + +void s_mp_rand_jenkins_init(uint64_t seed) +{ + uint64_t i; + jenkins_x.a = 0xf1ea5eedULL; + jenkins_x.b = jenkins_x.c = jenkins_x.d = seed; + for (i = 0uLL; i < 20uLL; ++i) { + (void)s_rand_jenkins_val(); + } +} + +mp_err s_mp_rand_jenkins(void *p, size_t n) +{ + char *q = (char *)p; + while (n > 0u) { + int i; + uint64_t x = s_rand_jenkins_val(); + for (i = 0; (i < 8) && (n > 0u); ++i, --n) { + *q++ = (char)(x & 0xFFuLL); + x >>= 8; + } + } + return MP_OKAY; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c b/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c new file mode 100644 index 000000000..27339bff8 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_rand_platform.c @@ -0,0 +1,148 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_RAND_PLATFORM_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* First the OS-specific special cases + * - *BSD + * - Windows + */ +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +#define BN_S_READ_ARC4RANDOM_C +static mp_err s_read_arc4random(void *p, size_t n) +{ + arc4random_buf(p, n); + return MP_OKAY; +} +#endif + +#if defined(_WIN32) || defined(_WIN32_WCE) +#define BN_S_READ_WINCSP_C + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif +#ifdef _WIN32_WCE +#define UNDER_CE +#define ARM +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#include + +static mp_err s_read_wincsp(void *p, size_t n) +{ + static HCRYPTPROV hProv = 0; + if (hProv == 0) { + HCRYPTPROV h = 0; + if (!CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL, + (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && + !CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) { + return MP_ERR; + } + hProv = h; + } + return CryptGenRandom(hProv, (DWORD)n, (BYTE *)p) == TRUE ? MP_OKAY : MP_ERR; +} +#endif /* WIN32 */ + +#if !defined(BN_S_READ_WINCSP_C) && defined(__linux__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2, 25) +#define BN_S_READ_GETRANDOM_C +#include +#include + +static mp_err s_read_getrandom(void *p, size_t n) +{ + char *q = (char *)p; + while (n > 0u) { + ssize_t ret = getrandom(q, n, 0); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + return MP_ERR; + } + q += ret; + n -= (size_t)ret; + } + return MP_OKAY; +} +#endif +#endif + +/* We assume all platforms besides windows provide "/dev/urandom". + * In case yours doesn't, define MP_NO_DEV_URANDOM at compile-time. + */ +#if !defined(BN_S_READ_WINCSP_C) && !defined(MP_NO_DEV_URANDOM) +#define BN_S_READ_URANDOM_C +#ifndef MP_DEV_URANDOM +#define MP_DEV_URANDOM "/dev/urandom" +#endif +#include +#include +#include + +static mp_err s_read_urandom(void *p, size_t n) +{ + int fd; + char *q = (char *)p; + + do { + fd = open(MP_DEV_URANDOM, O_RDONLY); + } while ((fd == -1) && (errno == EINTR)); + if (fd == -1) return MP_ERR; + + while (n > 0u) { + ssize_t ret = read(fd, p, n); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + close(fd); + return MP_ERR; + } + q += ret; + n -= (size_t)ret; + } + + close(fd); + return MP_OKAY; +} +#endif + +#if defined(MP_PRNG_ENABLE_LTM_RNG) +#define BN_S_READ_LTM_RNG +unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); +void (*ltm_rng_callback)(void); + +static mp_err s_read_ltm_rng(void *p, size_t n) +{ + unsigned long res; + if (ltm_rng == NULL) return MP_ERR; + res = ltm_rng(p, n, ltm_rng_callback); + if (res != n) return MP_ERR; + return MP_OKAY; +} +#endif + +mp_err s_read_arc4random(void *p, size_t n); +mp_err s_read_wincsp(void *p, size_t n); +mp_err s_read_getrandom(void *p, size_t n); +mp_err s_read_urandom(void *p, size_t n); +mp_err s_read_ltm_rng(void *p, size_t n); + +mp_err s_mp_rand_platform(void *p, size_t n) +{ + mp_err err = MP_ERR; + if ((err != MP_OKAY) && MP_HAS(S_READ_ARC4RANDOM)) err = s_read_arc4random(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_GETRANDOM)) err = s_read_getrandom(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_URANDOM)) err = s_read_urandom(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_LTM_RNG)) err = s_read_ltm_rng(p, n); + return err; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_reverse.c b/lib/hcrypto/libtommath/bn_s_mp_reverse.c new file mode 100644 index 000000000..c549e605e --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_reverse.c @@ -0,0 +1,22 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_REVERSE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reverse an array, used for radix code */ +void s_mp_reverse(unsigned char *s, size_t len) +{ + size_t ix, iy; + unsigned char t; + + ix = 0u; + iy = len - 1u; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_sqr.c b/lib/hcrypto/libtommath/bn_s_mp_sqr.c index c1c3826db..505c9f053 100644 --- a/lib/hcrypto/libtommath/bn_s_mp_sqr.c +++ b/lib/hcrypto/libtommath/bn_s_mp_sqr.c @@ -1,84 +1,69 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ -int s_mp_sqr (mp_int * a, mp_int * b) +mp_err s_mp_sqr(const mp_int *a, mp_int *b) { - mp_int t; - int res, ix, iy, pa; - mp_word r; - mp_digit u, tmpx, *tmpt; + mp_int t; + int ix, iy, pa; + mp_err err; + mp_word r; + mp_digit u, tmpx, *tmpt; - pa = a->used; - if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { - return res; - } + pa = a->used; + if ((err = mp_init_size(&t, (2 * pa) + 1)) != MP_OKAY) { + return err; + } - /* default used is maximum possible size */ - t.used = 2*pa + 1; + /* 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]); + 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)); + /* 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)); + /* get the carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); - /* left hand side of A[ix] * A[iy] */ - tmpx = a->dp[ix]; + /* 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); + /* 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]); + 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); + /* 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)); + /* 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)); - } - } + /* get carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + /* propagate upwards */ + while (u != 0uL) { + r = (mp_word)*tmpt + (mp_word)u; + *tmpt++ = (mp_digit)(r & (mp_word)MP_MASK); + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + } - mp_clamp (&t); - mp_exch (&t, b); - mp_clear (&t); - return MP_OKAY; + mp_clamp(&t); + mp_exch(&t, b); + mp_clear(&t); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_s_mp_sqr.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_sqr_fast.c b/lib/hcrypto/libtommath/bn_s_mp_sqr_fast.c new file mode 100644 index 000000000..4a8a8912f --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_sqr_fast.c @@ -0,0 +1,97 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_SQR_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. +*/ + +mp_err s_mp_sqr_fast(const mp_int *a, mp_int *b) +{ + int olduse, pa, ix, iz; + mp_digit W[MP_WARRAY], *tmpx; + mp_word W1; + mp_err err; + + /* grow the destination as required */ + pa = a->used + a->used; + if (b->alloc < pa) { + if ((err = mp_grow(b, pa)) != MP_OKAY) { + return err; + } + } + + /* 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 = MP_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 = MP_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 = MP_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 (((unsigned)ix & 1u) == 0u) { + _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)MP_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] */ + MP_ZERO_DIGITS(tmpb, olduse - ix); + } + mp_clamp(b); + return MP_OKAY; +} +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_sub.c b/lib/hcrypto/libtommath/bn_s_mp_sub.c index 6a60c3932..5672dab51 100644 --- a/lib/hcrypto/libtommath/bn_s_mp_sub.c +++ b/lib/hcrypto/libtommath/bn_s_mp_sub.c @@ -1,89 +1,71 @@ -#include +#include "tommath_private.h" #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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ /* 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) +mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) { - int olduse, res, min, max; + int olduse, min, max; + mp_err err; - /* find sizes */ - min = b->used; - max = a->used; + /* 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; + /* init result */ + if (c->alloc < max) { + if ((err = mp_grow(c, max)) != MP_OKAY) { + return err; + } + } + olduse = c->used; + c->used = max; - { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; + { + mp_digit u, *tmpa, *tmpb, *tmpc; + int i; - /* alias for digit pointers */ - tmpa = a->dp; - tmpb = b->dp; - tmpc = c->dp; + /* 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; + /* 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)); + /* 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_SIZEOF_BITS(mp_digit) - 1u); - /* Clear carry from T[i] */ - *tmpc++ &= MP_MASK; - } + /* 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; + /* 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)); + /* U = carry bit of T[i] */ + u = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u); - /* Clear carry from T[i] */ - *tmpc++ &= MP_MASK; - } + /* 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; - } - } + /* clear digits above used (since we may not have grown result above) */ + MP_ZERO_DIGITS(tmpc, olduse - c->used); + } - mp_clamp (c); - return MP_OKAY; + mp_clamp(c); + return MP_OKAY; } #endif - -/* $Source: /cvs/libtom/libtommath/bn_s_mp_sub.c,v $ */ -/* $Revision: 1.4 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/bn_s_mp_toom_mul.c b/lib/hcrypto/libtommath/bn_s_mp_toom_mul.c new file mode 100644 index 000000000..86901b074 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_toom_mul.c @@ -0,0 +1,215 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_TOOM_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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...). +*/ + +/* + This file contains code from J. Arndt's book "Matters Computational" + and the accompanying FXT-library with permission of the author. +*/ + +/* + Setup from + + Chung, Jaewook, and M. Anwar Hasan. "Asymmetric squaring formulae." + 18th IEEE Symposium on Computer Arithmetic (ARITH'07). IEEE, 2007. + + The interpolation from above needed one temporary variable more + than the interpolation here: + + Bodrato, Marco, and Alberto Zanoni. "What about Toom-Cook matrices optimality." + Centro Vito Volterra Universita di Roma Tor Vergata (2006) +*/ + +mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int S1, S2, T1, a0, a1, a2, b0, b1, b2; + int B, count; + mp_err err; + + /* init temps */ + if ((err = mp_init_multi(&S1, &S2, &T1, NULL)) != MP_OKAY) { + return err; + } + + /* B */ + B = MP_MIN(a->used, b->used) / 3; + + /** a = a2 * x^2 + a1 * x + a0; */ + if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0; + + for (count = 0; count < B; count++) { + a0.dp[count] = a->dp[count]; + a0.used++; + } + mp_clamp(&a0); + if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1; + for (; count < (2 * B); count++) { + a1.dp[count - B] = a->dp[count]; + a1.used++; + } + mp_clamp(&a1); + if ((err = mp_init_size(&a2, B + (a->used - (3 * B)))) != MP_OKAY) goto LBL_ERRa2; + for (; count < a->used; count++) { + a2.dp[count - (2 * B)] = a->dp[count]; + a2.used++; + } + mp_clamp(&a2); + + /** b = b2 * x^2 + b1 * x + b0; */ + if ((err = mp_init_size(&b0, B)) != MP_OKAY) goto LBL_ERRb0; + for (count = 0; count < B; count++) { + b0.dp[count] = b->dp[count]; + b0.used++; + } + mp_clamp(&b0); + if ((err = mp_init_size(&b1, B)) != MP_OKAY) goto LBL_ERRb1; + for (; count < (2 * B); count++) { + b1.dp[count - B] = b->dp[count]; + b1.used++; + } + mp_clamp(&b1); + if ((err = mp_init_size(&b2, B + (b->used - (3 * B)))) != MP_OKAY) goto LBL_ERRb2; + for (; count < b->used; count++) { + b2.dp[count - (2 * B)] = b->dp[count]; + b2.used++; + } + mp_clamp(&b2); + + /** \\ S1 = (a2+a1+a0) * (b2+b1+b0); */ + /** T1 = a2 + a1; */ + if ((err = mp_add(&a2, &a1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = T1 + a0; */ + if ((err = mp_add(&T1, &a0, &S2)) != MP_OKAY) goto LBL_ERR; + + /** c = b2 + b1; */ + if ((err = mp_add(&b2, &b1, c)) != MP_OKAY) goto LBL_ERR; + + /** S1 = c + b0; */ + if ((err = mp_add(c, &b0, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 * S2; */ + if ((err = mp_mul(&S1, &S2, &S1)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = (4*a2+2*a1+a0) * (4*b2+2*b1+b0); */ + /** T1 = T1 + a2; */ + if ((err = mp_add(&T1, &a2, &T1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = T1 << 1; */ + if ((err = mp_mul_2(&T1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = T1 + a0; */ + if ((err = mp_add(&T1, &a0, &T1)) != MP_OKAY) goto LBL_ERR; + + /** c = c + b2; */ + if ((err = mp_add(c, &b2, c)) != MP_OKAY) goto LBL_ERR; + + /** c = c << 1; */ + if ((err = mp_mul_2(c, c)) != MP_OKAY) goto LBL_ERR; + + /** c = c + b0; */ + if ((err = mp_add(c, &b0, c)) != MP_OKAY) goto LBL_ERR; + + /** S2 = T1 * c; */ + if ((err = mp_mul(&T1, c, &S2)) != MP_OKAY) goto LBL_ERR; + + /** \\S3 = (a2-a1+a0) * (b2-b1+b0); */ + /** a1 = a2 - a1; */ + if ((err = mp_sub(&a2, &a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 + a0; */ + if ((err = mp_add(&a1, &a0, &a1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = b2 - b1; */ + if ((err = mp_sub(&b2, &b1, &b1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = b1 + b0; */ + if ((err = mp_add(&b1, &b0, &b1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 * b1; */ + if ((err = mp_mul(&a1, &b1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = a2 * b2; */ + if ((err = mp_mul(&a2, &b2, &b1)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = (S2 - S3)/3; */ + /** S2 = S2 - a1; */ + if ((err = mp_sub(&S2, &a1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 / 3; \\ this is an exact division */ + if ((err = mp_div_3(&S2, &S2, NULL)) != MP_OKAY) goto LBL_ERR; + + /** a1 = S1 - a1; */ + if ((err = mp_sub(&S1, &a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 >> 1; */ + if ((err = mp_div_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a0 = a0 * b0; */ + if ((err = mp_mul(&a0, &b0, &a0)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - a0; */ + if ((err = mp_sub(&S1, &a0, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 - S1; */ + if ((err = mp_sub(&S2, &S1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 >> 1; */ + if ((err = mp_div_2(&S2, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - a1; */ + if ((err = mp_sub(&S1, &a1, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - b1; */ + if ((err = mp_sub(&S1, &b1, &S1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = b1 << 1; */ + if ((err = mp_mul_2(&b1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 - T1; */ + if ((err = mp_sub(&S2, &T1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 - S2; */ + if ((err = mp_sub(&a1, &S2, &a1)) != MP_OKAY) goto LBL_ERR; + + + /** P = b1*x^4+ S2*x^3+ S1*x^2+ a1*x + a0; */ + if ((err = mp_lshd(&b1, 4 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&S2, 3 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &S2, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&S1, 2 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &S1, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a1, 1 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &a1, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &a0, c)) != MP_OKAY) goto LBL_ERR; + + /** a * b - P */ + + +LBL_ERR: + mp_clear(&b2); +LBL_ERRb2: + mp_clear(&b1); +LBL_ERRb1: + mp_clear(&b0); +LBL_ERRb0: + mp_clear(&a2); +LBL_ERRa2: + mp_clear(&a1); +LBL_ERRa1: + mp_clear(&a0); +LBL_ERRa0: + mp_clear_multi(&S1, &S2, &T1, NULL); + return err; +} + +#endif diff --git a/lib/hcrypto/libtommath/bn_s_mp_toom_sqr.c b/lib/hcrypto/libtommath/bn_s_mp_toom_sqr.c new file mode 100644 index 000000000..f2ffb30c2 --- /dev/null +++ b/lib/hcrypto/libtommath/bn_s_mp_toom_sqr.c @@ -0,0 +1,147 @@ +#include "tommath_private.h" +#ifdef BN_S_MP_TOOM_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* squaring using Toom-Cook 3-way algorithm */ + +/* + This file contains code from J. Arndt's book "Matters Computational" + and the accompanying FXT-library with permission of the author. +*/ + +/* squaring using Toom-Cook 3-way algorithm */ +/* + Setup and interpolation from algorithm SQR_3 in + + Chung, Jaewook, and M. Anwar Hasan. "Asymmetric squaring formulae." + 18th IEEE Symposium on Computer Arithmetic (ARITH'07). IEEE, 2007. + +*/ +mp_err s_mp_toom_sqr(const mp_int *a, mp_int *b) +{ + mp_int S0, a0, a1, a2; + mp_digit *tmpa, *tmpc; + int B, count; + mp_err err; + + + /* init temps */ + if ((err = mp_init(&S0)) != MP_OKAY) { + return err; + } + + /* B */ + B = a->used / 3; + + /** a = a2 * x^2 + a1 * x + a0; */ + if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0; + + a0.used = B; + if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1; + a1.used = B; + if ((err = mp_init_size(&a2, B + (a->used - (3 * B)))) != MP_OKAY) goto LBL_ERRa2; + + tmpa = a->dp; + tmpc = a0.dp; + for (count = 0; count < B; count++) { + *tmpc++ = *tmpa++; + } + tmpc = a1.dp; + for (; count < (2 * B); count++) { + *tmpc++ = *tmpa++; + } + tmpc = a2.dp; + for (; count < a->used; count++) { + *tmpc++ = *tmpa++; + a2.used++; + } + mp_clamp(&a0); + mp_clamp(&a1); + mp_clamp(&a2); + + /** S0 = a0^2; */ + if ((err = mp_sqr(&a0, &S0)) != MP_OKAY) goto LBL_ERR; + + /** \\S1 = (a2 + a1 + a0)^2 */ + /** \\S2 = (a2 - a1 + a0)^2 */ + /** \\S1 = a0 + a2; */ + /** a0 = a0 + a2; */ + if ((err = mp_add(&a0, &a2, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S1 - a1; */ + /** b = a0 - a1; */ + if ((err = mp_sub(&a0, &a1, b)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1 + a1; */ + /** a0 = a0 + a1; */ + if ((err = mp_add(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1^2; */ + /** a0 = a0^2; */ + if ((err = mp_sqr(&a0, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S2^2; */ + /** b = b^2; */ + if ((err = mp_sqr(b, b)) != MP_OKAY) goto LBL_ERR; + + /** \\ S3 = 2 * a1 * a2 */ + /** \\S3 = a1 * a2; */ + /** a1 = a1 * a2; */ + if ((err = mp_mul(&a1, &a2, &a1)) != MP_OKAY) goto LBL_ERR; + /** \\S3 = S3 << 1; */ + /** a1 = a1 << 1; */ + if ((err = mp_mul_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** \\S4 = a2^2; */ + /** a2 = a2^2; */ + if ((err = mp_sqr(&a2, &a2)) != MP_OKAY) goto LBL_ERR; + + /** \\ tmp = (S1 + S2)/2 */ + /** \\tmp = S1 + S2; */ + /** b = a0 + b; */ + if ((err = mp_add(&a0, b, b)) != MP_OKAY) goto LBL_ERR; + /** \\tmp = tmp >> 1; */ + /** b = b >> 1; */ + if ((err = mp_div_2(b, b)) != MP_OKAY) goto LBL_ERR; + + /** \\ S1 = S1 - tmp - S3 */ + /** \\S1 = S1 - tmp; */ + /** a0 = a0 - b; */ + if ((err = mp_sub(&a0, b, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1 - S3; */ + /** a0 = a0 - a1; */ + if ((err = mp_sub(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = tmp - S4 -S0 */ + /** \\S2 = tmp - S4; */ + /** b = b - a2; */ + if ((err = mp_sub(b, &a2, b)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S2 - S0; */ + /** b = b - S0; */ + if ((err = mp_sub(b, &S0, b)) != MP_OKAY) goto LBL_ERR; + + + /** \\P = S4*x^4 + S3*x^3 + S2*x^2 + S1*x + S0; */ + /** P = a2*x^4 + a1*x^3 + b*x^2 + a0*x + S0; */ + + if ((err = mp_lshd(&a2, 4 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a1, 3 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(b, 2 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a0, 1 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&a2, &a1, &a2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&a2, b, b)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(b, &a0, b)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(b, &S0, b)) != MP_OKAY) goto LBL_ERR; + /** a^2 - P */ + + +LBL_ERR: + mp_clear(&a2); +LBL_ERRa2: + mp_clear(&a1); +LBL_ERRa1: + mp_clear(&a0); +LBL_ERRa0: + mp_clear(&S0); + + return err; +} + +#endif diff --git a/lib/hcrypto/libtommath/bncore.c b/lib/hcrypto/libtommath/bncore.c deleted file mode 100644 index 919e3b33b..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/bncore.c,v $ */ -/* $Revision: 1.5 $ */ -/* $Date: 2006/12/28 01:25:13 $ */ diff --git a/lib/hcrypto/libtommath/booker.pl b/lib/hcrypto/libtommath/booker.pl deleted file mode 100644 index 49f1889d1..000000000 --- a/lib/hcrypto/libtommath/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/lib/hcrypto/libtommath/callgraph.txt b/lib/hcrypto/libtommath/callgraph.txt deleted file mode 100644 index 2efcf245b..000000000 --- a/lib/hcrypto/libtommath/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/lib/hcrypto/libtommath/changes.txt b/lib/hcrypto/libtommath/changes.txt index b0da4da4f..ebf7382a0 100644 --- a/lib/hcrypto/libtommath/changes.txt +++ b/lib/hcrypto/libtommath/changes.txt @@ -1,5 +1,105 @@ +XXX XXth, 2019 +v1.2.0 + -- A huge refactoring of the library happened - renaming, + deprecating and replacing existing functions by improved API's. + + All deprecated functions, macros and symbols are only marked as such + so this version is still API and ABI compatible to v1.x. + + -- Daniel Mendler was pushing for those changes and contributing a load of patches, + refactorings, code reviews and whatnotelse. + -- Christoph Zurnieden re-worked internals of the library, improved the performance, + did code reviews and wrote documentation. + -- Francois Perrad did some refactoring and took again care of linting the sources and + provided all fixes. + -- Jan Nijtmans, Karel Miko and Joachim Breitner contributed various patches. + + -- Private symbols can now be hidden for the shared library builds, disabled by default. + -- All API's follow a single code style, are prefixed the same etc. + -- Unified, safer and improved API's + -- Less magic numbers - return values (where appropriate) and most flags are now enums, + this was implemented in a backwards compatible way where return values were int. + -- API's with return values are now by default marked as "warn on unsused result", this + can be disabled if required (which will most likely hide bugs), c.f. MP_WUR in tommath.h + -- Provide a whole set of setters&getters for different primitive types (long, uint32_t, etc.) + -- All those primitive setters are now optimized. + -- It's possible to automatically tune the cutoff values for Karatsuba&Toom-Cook + -- The custom allocators which were formerly known as XMALLOC(), XFREE() etc. are now available + as MP_MALLOC(), MP_REALLOC(), MP_CALLOC() and MP_FREE(). MP_REALLOC() and MP_FREE() now also + provide the allocated size to ease the usage of simple allocators without tracking. + -- Building is now also possible with MSVC 2015, 2017 and 2019 (use makefile.msvc) + -- Added mp_decr() and mp_incr() + -- Added mp_log_u32() + -- Improved prime-checking + -- Improved Toom-Cook multiplication + -- Removed the LTM book (`make docs` now builds the user manual) + + +Jan 28th, 2019 +v1.1.0 + -- Christoph Zurnieden contributed FIPS 186.4 compliant + prime-checking (PR #113), several other fixes and a load of documentation + -- Daniel Mendler provided two's-complement functions (PR #124) + and mp_{set,get}_double() (PR #123) + -- Francois Perrad took care of linting the sources, provided all fixes and + a astylerc to auto-format the sources. + -- A bunch of patches by Kevin B Kenny have been back-ported from TCL + -- Jan Nijtmans provided the patches to `const`ify all API + function arguments (also from TCL) + -- mp_rand() has now several native random provider implementations + and doesn't rely on `rand()` anymore + -- Karel Miko provided fixes when building for MS Windows + and re-worked the makefile generating process + -- The entire environment and build logic has been extended and improved + regarding auto-detection of platforms, libtool and a lot more + -- Prevent some potential BOF cases + -- Improved/fixed mp_lshd() and mp_invmod() + -- A load more bugs were fixed by various contributors + + +Aug 29th, 2017 +v1.0.1 + -- Dmitry Kovalenko provided fixes to mp_add_d() and mp_init_copy() + -- Matt Johnston contributed some improvements to mp_div_2d(), + mp_exptmod_fast(), mp_mod() and mp_mulmod() + -- Julien Nabet provided a fix to the error handling in mp_init_multi() + -- Ben Gardner provided a fix regarding usage of reserved keywords + -- Fixed mp_rand() to fill the correct number of bits + -- Fixed mp_invmod() + -- Use the same 64-bit detection code as in libtomcrypt + -- Correct usage of DESTDIR, PREFIX, etc. when installing the library + -- Francois Perrad updated all the perl scripts to an actual perl version + + +Feb 5th, 2016 +v1.0 + -- Bump to 1.0 + -- Dirkjan Bussink provided a faster version of mp_expt_d() + -- Moritz Lenz contributed a fix to mp_mod() + and provided mp_get_long() and mp_set_long() + -- Fixed bugs in mp_read_radix(), mp_radix_size + Thanks to shameister, Gerhard R, + -- Christopher Brown provided mp_export() and mp_import() + -- Improvements in the code of mp_init_copy() + Thanks to ramkumarkoppu, + -- lomereiter provided mp_balance_mul() + -- Alexander Boström from the heimdal project contributed patches to + mp_prime_next_prime() and mp_invmod() and added a mp_isneg() macro + -- Fix build issues for Linux x32 ABI + -- Added mp_get_long_long() and mp_set_long_long() + -- Carlin provided a patch to use arc4random() instead of rand() + on platforms where it is supported + -- Karel Miko provided mp_sqrtmod_prime() + + +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. +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 @@ -16,11 +116,11 @@ v0.39 -- Jim Wigginton pointed out my Montgomery examples in figures 6.4 and 6. 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. + -- [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 @@ -30,8 +130,8 @@ v0.36 -- LTM_PRIME_2MSB_ON was fixed and the "OFF" flag was removed. -- 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. + -- 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 @@ -42,7 +142,7 @@ v0.35 -- Stupid XOR function missing line again... oops. -- [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 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! @@ -53,7 +153,7 @@ v0.34 -- Fixed two more small errors in mp_prime_random_ex() -- 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 + -- 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. @@ -70,7 +170,7 @@ v0.33 -- Fixed "small" variant for mp_div() which would munge with negative div 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 + -- 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 @@ -78,7 +178,7 @@ v0.32 -- Added "makefile.shared" for shared object support 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 + -- 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 ;-) @@ -107,8 +207,8 @@ v0.30 -- Added "mp_toradix_n" which stores upto "n-1" least significant digits 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. + ++ 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 ;-) diff --git a/lib/hcrypto/libtommath/demo/demo.c b/lib/hcrypto/libtommath/demo/demo.c deleted file mode 100644 index 2442611f9..000000000 --- a/lib/hcrypto/libtommath/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: /cvs/libtom/libtommath/demo/demo.c,v $ */ -/* $Revision: 1.3 $ */ -/* $Date: 2005/06/24 11:32:07 $ */ diff --git a/lib/hcrypto/libtommath/demo/mtest_opponent.c b/lib/hcrypto/libtommath/demo/mtest_opponent.c new file mode 100644 index 000000000..7fbd35ebc --- /dev/null +++ b/lib/hcrypto/libtommath/demo/mtest_opponent.c @@ -0,0 +1,402 @@ +#include "shared.h" + +#ifdef LTM_MTEST_REAL_RAND +#define LTM_MTEST_RAND_SEED time(NULL) +#else +#define LTM_MTEST_RAND_SEED 23 +#endif + +static void draw(mp_int *a) +{ + ndraw(a, ""); +} + +#define FGETS(str, size, stream) \ + { \ + char *ret = fgets(str, size, stream); \ + if (!ret) { fprintf(stderr, "\n%d: fgets failed\n", __LINE__); goto LBL_ERR; } \ + } + +static int mtest_opponent(void) +{ + char cmd[4096]; + char buf[4096]; + int ix; + unsigned rr; + 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; + + srand(LTM_MTEST_RAND_SEED); + + if (mp_init_multi(&a, &b, &c, &d, &e, &f, NULL)!= MP_OKAY) + return EXIT_FAILURE; + + 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 = add_d_n = sub_d_n = 0; + +#ifndef MP_FIXED_CUTOFFS + /* force KARA and TOOM to enable despite cutoffs */ + KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 8; + TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 16; +#endif + + 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) - 1u] = '\0'; + printf("%-6s ]\r", cmd); + fflush(stdout); + if (strcmp(cmd, "mul2d") == 0) { + ++mul2d_n; + FGETS(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + FGETS(buf, 4095, stdin); + sscanf(buf, "%u", &rr); + FGETS(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + + mp_mul_2d(&a, (int)rr, &a); + a.sign = b.sign; + if (mp_cmp(&a, &b) != MP_EQ) { + printf("mul2d failed, rr == %u\n", rr); + draw(&a); + draw(&b); + goto LBL_ERR; + } + } else if (strcmp(cmd, "div2d") == 0) { + ++div2d_n; + FGETS(buf, 4095, stdin); + mp_read_radix(&a, buf, 64); + FGETS(buf, 4095, stdin); + sscanf(buf, "%u", &rr); + FGETS(buf, 4095, stdin); + mp_read_radix(&b, buf, 64); + + mp_div_2d(&a, (int)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 == %u\n", rr); + draw(&a); + draw(&b); + goto LBL_ERR; + } + } else if (strcmp(cmd, "add") == 0) { + ++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); + goto LBL_ERR; + } + + /* test the sign/unsigned storage functions */ + + rr = (unsigned)mp_sbin_size(&c); + mp_to_sbin(&c, (unsigned char *) cmd, (size_t)rr, NULL); + memset(cmd + rr, rand() & 0xFF, sizeof(cmd) - rr); + mp_from_sbin(&d, (unsigned char *) cmd, (size_t)rr); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("mp_signed_bin failure!\n"); + draw(&c); + draw(&d); + goto LBL_ERR; + } + + rr = (unsigned)mp_ubin_size(&c); + mp_to_ubin(&c, (unsigned char *) cmd, (size_t)rr, NULL); + memset(cmd + rr, rand() & 0xFF, sizeof(cmd) - rr); + mp_from_ubin(&d, (unsigned char *) cmd, (size_t)rr); + if (mp_cmp_mag(&c, &d) != MP_EQ) { + printf("mp_unsigned_bin failure!\n"); + draw(&c); + draw(&d); + goto LBL_ERR; + } + + } else if (strcmp(cmd, "sub") == 0) { + ++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); + goto LBL_ERR; + } + } else if (strcmp(cmd, "mul") == 0) { + ++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); + goto LBL_ERR; + } + } else if (strcmp(cmd, "div") == 0) { + ++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); + goto LBL_ERR; + } + + } else if (strcmp(cmd, "sqr") == 0) { + ++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); + goto LBL_ERR; + } + } else if (strcmp(cmd, "gcd") == 0) { + ++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); + goto LBL_ERR; + } + } else if (strcmp(cmd, "lcm") == 0) { + ++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); + goto LBL_ERR; + } + } else if (strcmp(cmd, "expt") == 0) { + ++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); + goto LBL_ERR; + } + } else if (strcmp(cmd, "invmod") == 0) { + ++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, 1uL) != MP_EQ) { + printf("inv [wrong value from MPI?!] failure\n"); + draw(&a); + draw(&b); + draw(&c); + draw(&d); + draw(&e); + mp_gcd(&a, &b, &e); + draw(&e); + goto LBL_ERR; + } + + } else if (strcmp(cmd, "div2") == 0) { + ++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); + goto LBL_ERR; + } + } else if (strcmp(cmd, "mul2") == 0) { + ++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); + goto LBL_ERR; + } + } else if (strcmp(cmd, "add_d") == 0) { + ++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, (mp_digit)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); + goto LBL_ERR; + } + } else if (strcmp(cmd, "sub_d") == 0) { + ++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, (mp_digit)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); + goto LBL_ERR; + } + } else if (strcmp(cmd, "exit") == 0) { + printf("\nokay, exiting now\n"); + break; + } + } + + mp_clear_multi(&a, &b, &c, &d, &e, &f, NULL); + printf("\n"); + return 0; + +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, &e, &f, NULL); + printf("\n"); + return EXIT_FAILURE; +} + +int main(void) +{ + print_header(); + + return mtest_opponent(); +} diff --git a/lib/hcrypto/libtommath/demo/shared.c b/lib/hcrypto/libtommath/demo/shared.c new file mode 100644 index 000000000..dc8e05a6a --- /dev/null +++ b/lib/hcrypto/libtommath/demo/shared.c @@ -0,0 +1,42 @@ +#include "shared.h" + +void ndraw(mp_int *a, const char *name) +{ + char *buf = NULL; + int size; + + mp_radix_size(a, 10, &size); + buf = (char *)malloc((size_t) size); + if (buf == NULL) { + fprintf(stderr, "\nndraw: malloc(%d) failed\n", size); + exit(EXIT_FAILURE); + } + + printf("%s: ", name); + mp_to_decimal(a, buf, (size_t) size); + printf("%s\n", buf); + mp_to_hex(a, buf, (size_t) size); + printf("0x%s\n", buf); + + free(buf); +} + +void print_header(void) +{ +#ifdef MP_8BIT + printf("Digit size 8 Bit \n"); +#endif +#ifdef MP_16BIT + printf("Digit size 16 Bit \n"); +#endif +#ifdef MP_32BIT + printf("Digit size 32 Bit \n"); +#endif +#ifdef MP_64BIT + printf("Digit size 64 Bit \n"); +#endif + printf("Size of mp_digit: %u\n", (unsigned int)sizeof(mp_digit)); + printf("Size of mp_word: %u\n", (unsigned int)sizeof(mp_word)); + printf("MP_DIGIT_BIT: %d\n", MP_DIGIT_BIT); + printf("MP_PREC: %d\n", MP_PREC); +} diff --git a/lib/hcrypto/libtommath/demo/shared.h b/lib/hcrypto/libtommath/demo/shared.h new file mode 100644 index 000000000..4d5eb53b2 --- /dev/null +++ b/lib/hcrypto/libtommath/demo/shared.h @@ -0,0 +1,21 @@ +#include +#include +#include + +/* + * Configuration + */ +#ifndef LTM_DEMO_TEST_REDUCE_2K_L +/* This test takes a moment so we disable it by default, but it can be: + * 0 to disable testing + * 1 to make the test with P = 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF + * 2 to make the test with P = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F + */ +#define LTM_DEMO_TEST_REDUCE_2K_L 0 +#endif + +#define MP_WUR /* TODO: result checks disabled for now */ +#include "tommath_private.h" + +extern void ndraw(mp_int* a, const char* name); +extern void print_header(void); diff --git a/lib/hcrypto/libtommath/demo/test.c b/lib/hcrypto/libtommath/demo/test.c new file mode 100644 index 000000000..7b29a4ce9 --- /dev/null +++ b/lib/hcrypto/libtommath/demo/test.c @@ -0,0 +1,2522 @@ +#include +#include "shared.h" + +static long rand_long(void) +{ + long x; + if (s_mp_rand_source(&x, sizeof(x)) != MP_OKAY) { + fprintf(stderr, "s_mp_rand_source failed\n"); + exit(EXIT_FAILURE); + } + return x; +} + +static int rand_int(void) +{ + int x; + if (s_mp_rand_source(&x, sizeof(x)) != MP_OKAY) { + fprintf(stderr, "s_mp_rand_source failed\n"); + exit(EXIT_FAILURE); + } + return x; +} + +static int32_t rand_int32(void) +{ + int32_t x; + if (s_mp_rand_source(&x, sizeof(x)) != MP_OKAY) { + fprintf(stderr, "s_mp_rand_source failed\n"); + exit(EXIT_FAILURE); + } + return x; +} + +static int64_t rand_int64(void) +{ + int64_t x; + if (s_mp_rand_source(&x, sizeof(x)) != MP_OKAY) { + fprintf(stderr, "s_mp_rand_source failed\n"); + exit(EXIT_FAILURE); + } + return x; +} + +static uint32_t uabs32(int32_t x) +{ + return x > 0 ? (uint32_t)x : -(uint32_t)x; +} + +static uint64_t uabs64(int64_t x) +{ + return x > 0 ? (uint64_t)x : -(uint64_t)x; +} + +/* This function prototype is needed + * to test dead code elimination + * which is used for feature detection. + * + * If the feature detection does not + * work as desired we will get a linker error. + */ +void does_not_exist(void); + +static int test_feature_detection(void) +{ +#define BN_TEST_FEATURE1_C + if (!MP_HAS(TEST_FEATURE1)) { + does_not_exist(); + return EXIT_FAILURE; + } + +#define BN_TEST_FEATURE2_C 1 + if (MP_HAS(TEST_FEATURE2)) { + does_not_exist(); + return EXIT_FAILURE; + } + +#define BN_TEST_FEATURE3_C 0 + if (MP_HAS(TEST_FEATURE3)) { + does_not_exist(); + return EXIT_FAILURE; + } + +#define BN_TEST_FEATURE4_C something + if (MP_HAS(TEST_FEATURE4)) { + does_not_exist(); + return EXIT_FAILURE; + } + + if (MP_HAS(TEST_FEATURE5)) { + does_not_exist(); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int test_trivial_stuff(void) +{ + mp_int a, b, c, d; + mp_err e; + if ((e = mp_init_multi(&a, &b, &c, &d, NULL)) != MP_OKAY) { + return EXIT_FAILURE; + } + (void)mp_error_to_string(e); + + /* a: 0->5 */ + mp_set(&a, 5u); + /* a: 5-> b: -5 */ + mp_neg(&a, &b); + if (mp_cmp(&a, &b) != MP_GT) { + goto LBL_ERR; + } + if (mp_cmp(&b, &a) != MP_LT) { + goto LBL_ERR; + } + /* a: 5-> a: -5 */ + mp_neg(&a, &a); + if (mp_cmp(&b, &a) != MP_EQ) { + goto LBL_ERR; + } + /* a: -5-> b: 5 */ + mp_abs(&a, &b); + if (mp_isneg(&b) != MP_NO) { + goto LBL_ERR; + } + /* a: -5-> b: -4 */ + mp_add_d(&a, 1uL, &b); + if (mp_isneg(&b) != MP_YES) { + goto LBL_ERR; + } + if (mp_get_i32(&b) != -4) { + goto LBL_ERR; + } + if (mp_get_u32(&b) != (uint32_t)-4) { + goto LBL_ERR; + } + if (mp_get_mag_u32(&b) != 4) { + goto LBL_ERR; + } + /* a: -5-> b: 1 */ + mp_add_d(&a, 6uL, &b); + if (mp_get_u32(&b) != 1) { + goto LBL_ERR; + } + /* a: -5-> a: 1 */ + mp_add_d(&a, 6uL, &a); + if (mp_get_u32(&a) != 1) { + goto LBL_ERR; + } + mp_zero(&a); + /* a: 0-> a: 6 */ + mp_add_d(&a, 6uL, &a); + if (mp_get_u32(&a) != 6) { + goto LBL_ERR; + } + + mp_set(&a, 42u); + mp_set(&b, 1u); + mp_neg(&b, &b); + mp_set(&c, 1u); + mp_exptmod(&a, &b, &c, &d); + + mp_set(&c, 7u); + mp_exptmod(&a, &b, &c, &d); + + if (mp_iseven(&a) == mp_isodd(&a)) { + goto LBL_ERR; + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int check_get_set_i32(mp_int *a, int32_t b) +{ + mp_clear(a); + if (mp_shrink(a) != MP_OKAY) return EXIT_FAILURE; + + mp_set_i32(a, b); + if (mp_shrink(a) != MP_OKAY) return EXIT_FAILURE; + if (mp_get_i32(a) != b) return EXIT_FAILURE; + if (mp_get_u32(a) != (uint32_t)b) return EXIT_FAILURE; + if (mp_get_mag_u32(a) != uabs32(b)) return EXIT_FAILURE; + + mp_set_u32(a, (uint32_t)b); + if (mp_get_u32(a) != (uint32_t)b) return EXIT_FAILURE; + if (mp_get_i32(a) != (int32_t)(uint32_t)b) return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static int test_mp_get_set_i32(void) +{ + int i; + mp_int a; + + if (mp_init(&a) != MP_OKAY) { + return EXIT_FAILURE; + } + + check_get_set_i32(&a, 0); + check_get_set_i32(&a, -1); + check_get_set_i32(&a, 1); + check_get_set_i32(&a, INT32_MIN); + check_get_set_i32(&a, INT32_MAX); + + for (i = 0; i < 1000; ++i) { + int32_t b = rand_int32(); + if (check_get_set_i32(&a, b) != EXIT_SUCCESS) { + goto LBL_ERR; + } + } + + mp_clear(&a); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + +static int check_get_set_i64(mp_int *a, int64_t b) +{ + mp_clear(a); + if (mp_shrink(a) != MP_OKAY) return EXIT_FAILURE; + + mp_set_i64(a, b); + if (mp_shrink(a) != MP_OKAY) return EXIT_FAILURE; + if (mp_get_i64(a) != b) return EXIT_FAILURE; + if (mp_get_u64(a) != (uint64_t)b) return EXIT_FAILURE; + if (mp_get_mag_u64(a) != uabs64(b)) return EXIT_FAILURE; + + mp_set_u64(a, (uint64_t)b); + if (mp_get_u64(a) != (uint64_t)b) return EXIT_FAILURE; + if (mp_get_i64(a) != (int64_t)(uint64_t)b) return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static int test_mp_get_set_i64(void) +{ + int i; + mp_int a; + + if (mp_init(&a) != MP_OKAY) { + return EXIT_FAILURE; + } + + check_get_set_i64(&a, 0); + check_get_set_i64(&a, -1); + check_get_set_i64(&a, 1); + check_get_set_i64(&a, INT64_MIN); + check_get_set_i64(&a, INT64_MAX); + + for (i = 0; i < 1000; ++i) { + int64_t b = rand_int64(); + if (check_get_set_i64(&a, b) != EXIT_SUCCESS) { + goto LBL_ERR; + } + } + + mp_clear(&a); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + +static int test_mp_fread_fwrite(void) +{ + mp_int a, b; + mp_err e; + FILE *tmp = NULL; + if ((e = mp_init_multi(&a, &b, NULL)) != MP_OKAY) { + return EXIT_FAILURE; + } + + mp_set_ul(&a, 123456uL); + tmp = tmpfile(); + if ((e = mp_fwrite(&a, 64, tmp)) != MP_OKAY) { + goto LBL_ERR; + } + rewind(tmp); + if ((e = mp_fread(&b, 64, tmp)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_get_u32(&b) != 123456uL) { + goto LBL_ERR; + } + fclose(tmp); + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + if (tmp != NULL) fclose(tmp); + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static mp_err very_random_source(void *out, size_t size) +{ + memset(out, 0xff, size); + return MP_OKAY; +} + +static int test_mp_rand(void) +{ + mp_int a, b; + int n; + mp_err err; + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + mp_rand_source(very_random_source); + for (n = 1; n < 1024; ++n) { + if ((err = mp_rand(&a, n)) != MP_OKAY) { + printf("Failed mp_rand() %s.\n", mp_error_to_string(err)); + break; + } + if ((err = mp_incr(&a)) != MP_OKAY) { + printf("Failed mp_incr() %s.\n", mp_error_to_string(err)); + break; + } + if ((err = mp_div_2d(&a, n * MP_DIGIT_BIT, &b, NULL)) != MP_OKAY) { + printf("Failed mp_div_2d() %s.\n", mp_error_to_string(err)); + break; + } + if (mp_cmp_d(&b, 1) != MP_EQ) { + ndraw(&a, "mp_rand() a"); + ndraw(&b, "mp_rand() b"); + err = MP_ERR; + break; + } + } + mp_rand_source(s_mp_rand_jenkins); + mp_clear_multi(&a, &b, NULL); + return err == MP_OKAY ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static int test_mp_kronecker(void) +{ + struct mp_kronecker_st { + long n; + int c[21]; + }; + static struct mp_kronecker_st kronecker[] = { + /*-10, -9, -8, -7,-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10*/ + { -10, { 0, -1, 0, -1, 0, 0, 0, 1, 0, -1, 0, 1, 0, -1, 0, 0, 0, 1, 0, 1, 0 } }, + { -9, { -1, 0, -1, 1, 0, -1, -1, 0, -1, -1, 0, 1, 1, 0, 1, 1, 0, -1, 1, 0, 1 } }, + { -8, { 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0 } }, + { -7, { 1, -1, -1, 0, 1, 1, -1, 1, -1, -1, 0, 1, 1, -1, 1, -1, -1, 0, 1, 1, -1 } }, + { -6, { 0, 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0 } }, + { -5, { 0, -1, 1, -1, 1, 0, -1, -1, 1, -1, 0, 1, -1, 1, 1, 0, -1, 1, -1, 1, 0 } }, + { -4, { 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0 } }, + { -3, { -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1 } }, + { -2, { 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0 } }, + { -1, { -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1 } }, + { 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 1, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }, + { 2, { 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0 } }, + { 3, { 1, 0, -1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, -1, 0, -1, -1, 0, 1 } }, + { 4, { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 } }, + { 5, { 0, 1, -1, -1, 1, 0, 1, -1, -1, 1, 0, 1, -1, -1, 1, 0, 1, -1, -1, 1, 0 } }, + { 6, { 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0 } }, + { 7, { -1, 1, 1, 0, 1, -1, 1, 1, 1, 1, 0, 1, 1, 1, 1, -1, 1, 0, 1, 1, -1 } }, + { 8, { 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0 } }, + { 9, { 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 } }, + { 10, { 0, 1, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0 } } + }; + + long k, m; + int i, cnt; + mp_err err; + mp_int a, b; + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + mp_set_ul(&a, 0uL); + mp_set_ul(&b, 1uL); + if ((err = mp_kronecker(&a, &b, &i)) != MP_OKAY) { + printf("Failed executing mp_kronecker(0 | 1) %s.\n", mp_error_to_string(err)); + goto LBL_ERR; + } + if (i != 1) { + printf("Failed trivial mp_kronecker(0 | 1) %d != 1\n", i); + goto LBL_ERR; + } + for (cnt = 0; cnt < (int)(sizeof(kronecker)/sizeof(kronecker[0])); ++cnt) { + k = kronecker[cnt].n; + mp_set_l(&a, k); + /* only test positive values of a */ + for (m = -10; m <= 10; m++) { + mp_set_l(&b, m); + if ((err = mp_kronecker(&a, &b, &i)) != MP_OKAY) { + printf("Failed executing mp_kronecker(%ld | %ld) %s.\n", kronecker[cnt].n, m, mp_error_to_string(err)); + goto LBL_ERR; + } + if ((err == MP_OKAY) && (i != kronecker[cnt].c[m + 10])) { + printf("Failed trivial mp_kronecker(%ld | %ld) %d != %d\n", kronecker[cnt].n, m, i, kronecker[cnt].c[m + 10]); + goto LBL_ERR; + } + } + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_complement(void) +{ + int i; + + mp_int a, b, c; + if (mp_init_multi(&a, &b, &c, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + for (i = 0; i < 1000; ++i) { + long l = rand_long(); + mp_set_l(&a, l); + mp_complement(&a, &b); + + l = ~l; + mp_set_l(&c, l); + + if (mp_cmp(&b, &c) != MP_EQ) { + printf("\nmp_complement() bad result!"); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_signed_rsh(void) +{ + int i; + + mp_int a, b, d; + if (mp_init_multi(&a, &b, &d, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + for (i = 0; i < 1000; ++i) { + long l; + int em; + + l = rand_long(); + mp_set_l(&a, l); + + em = abs(rand_int()) % 32; + + mp_set_l(&d, l >> em); + + mp_signed_rsh(&a, em, &b); + if (mp_cmp(&b, &d) != MP_EQ) { + printf("\nmp_signed_rsh() bad result!"); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &d, NULL); + return EXIT_FAILURE; + +} + +static int test_mp_xor(void) +{ + int i; + + mp_int a, b, c, d; + if (mp_init_multi(&a, &b, &c, &d, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + for (i = 0; i < 1000; ++i) { + long l, em; + + l = rand_long(); + mp_set_l(&a,l); + + em = rand_long(); + mp_set_l(&b, em); + + mp_set_l(&d, l ^ em); + + mp_xor(&a, &b, &c); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("\nmp_xor() bad result!"); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; + +} + +static int test_mp_or(void) +{ + int i; + + mp_int a, b, c, d; + if (mp_init_multi(&a, &b, &c, &d, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + for (i = 0; i < 1000; ++i) { + long l, em; + + l = rand_long(); + mp_set_l(&a, l); + + em = rand_long(); + mp_set_l(&b, em); + + mp_set_l(&d, l | em); + + mp_or(&a, &b, &c); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("\nmp_or() bad result!"); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_mp_and(void) +{ + int i; + + mp_int a, b, c, d; + if (mp_init_multi(&a, &b, &c, &d, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + for (i = 0; i < 1000; ++i) { + long l, em; + + l = rand_long(); + mp_set_l(&a, l); + + em = rand_long(); + mp_set_l(&b, em); + + mp_set_l(&d, l & em); + + mp_and(&a, &b, &c); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("\nmp_and() bad result!"); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_mp_invmod(void) +{ + mp_int a, b, c, d; + if (mp_init_multi(&a, &b, &c, &d, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + /* mp_invmod corner-case of https://github.com/libtom/libtommath/issues/118 */ + { + const char *a_ = "47182BB8DF0FFE9F61B1F269BACC066B48BA145D35137D426328DC3F88A5EA44"; + const char *b_ = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"; + const char *should_ = "0521A82E10376F8E4FDEF9A32A427AC2A0FFF686E00290D39E3E4B5522409596"; + + if (mp_read_radix(&a, a_, 16) != MP_OKAY) { + printf("\nmp_read_radix(a) failed!"); + goto LBL_ERR; + } + if (mp_read_radix(&b, b_, 16) != MP_OKAY) { + printf("\nmp_read_radix(b) failed!"); + goto LBL_ERR; + } + if (mp_read_radix(&c, should_, 16) != MP_OKAY) { + printf("\nmp_read_radix(should) failed!"); + goto LBL_ERR; + } + + if (mp_invmod(&a, &b, &d) != MP_OKAY) { + printf("\nmp_invmod() failed!"); + goto LBL_ERR; + } + + if (mp_cmp(&c, &d) != MP_EQ) { + printf("\nmp_invmod() bad result!"); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; + +} + +#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) +static int test_mp_set_double(void) +{ + int i; + + mp_int a, b; + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + /* test mp_get_double/mp_set_double */ + if (mp_set_double(&a, +1.0/0.0) != MP_VAL) { + printf("\nmp_set_double should return MP_VAL for +inf"); + goto LBL_ERR; + } + if (mp_set_double(&a, -1.0/0.0) != MP_VAL) { + printf("\nmp_set_double should return MP_VAL for -inf"); + goto LBL_ERR; + } + if (mp_set_double(&a, +0.0/0.0) != MP_VAL) { + printf("\nmp_set_double should return MP_VAL for NaN"); + goto LBL_ERR; + } + if (mp_set_double(&a, -0.0/0.0) != MP_VAL) { + printf("\nmp_set_double should return MP_VAL for NaN"); + goto LBL_ERR; + } + + for (i = 0; i < 1000; ++i) { + int tmp = rand_int(); + double dbl = (double)tmp * rand_int() + 1; + if (mp_set_double(&a, dbl) != MP_OKAY) { + printf("\nmp_set_double() failed"); + goto LBL_ERR; + } + if (dbl != mp_get_double(&a)) { + printf("\nmp_get_double() bad result!"); + goto LBL_ERR; + } + if (mp_set_double(&a, -dbl) != MP_OKAY) { + printf("\nmp_set_double() failed"); + goto LBL_ERR; + } + if (-dbl != mp_get_double(&a)) { + printf("\nmp_get_double() bad result!"); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; + +} +#endif + +static int test_mp_get_u32(void) +{ + unsigned long t; + int i; + + mp_int a, b; + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + for (i = 0; i < 1000; ++i) { + t = (unsigned long)rand_long() & 0xFFFFFFFFuL; + mp_set_ul(&a, t); + if (t != mp_get_u32(&a)) { + printf("\nmp_get_u32() bad result!"); + goto LBL_ERR; + } + } + mp_set_ul(&a, 0uL); + if (mp_get_u32(&a) != 0) { + printf("\nmp_get_u32() bad result!"); + goto LBL_ERR; + } + mp_set_ul(&a, 0xFFFFFFFFuL); + if (mp_get_u32(&a) != 0xFFFFFFFFuL) { + printf("\nmp_get_u32() bad result!"); + goto LBL_ERR; + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_get_ul(void) +{ + unsigned long s, t; + int i; + + mp_int a, b; + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + for (i = 0; i < ((int)MP_SIZEOF_BITS(unsigned long) - 1); ++i) { + t = (1UL << (i+1)) - 1; + if (!t) + t = ~0UL; + printf(" t = 0x%lx i = %d\r", t, i); + do { + mp_set_ul(&a, t); + s = mp_get_ul(&a); + if (s != t) { + printf("\nmp_get_ul() bad result! 0x%lx != 0x%lx", s, t); + goto LBL_ERR; + } + t <<= 1; + } while (t != 0uL); + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_get_u64(void) +{ + unsigned long long q, r; + int i; + + mp_int a, b; + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + for (i = 0; i < (int)(MP_SIZEOF_BITS(unsigned long long) - 1); ++i) { + r = (1ULL << (i+1)) - 1; + if (!r) + r = ~0ULL; + printf(" r = 0x%llx i = %d\r", r, i); + do { + mp_set_u64(&a, r); + q = mp_get_u64(&a); + if (q != r) { + printf("\nmp_get_u64() bad result! 0x%llx != 0x%llx", q, r); + goto LBL_ERR; + } + r <<= 1; + } while (r != 0uLL); + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; + +} + +static int test_mp_sqrt(void) +{ + int i, n; + + mp_int a, b, c; + if (mp_init_multi(&a, &b, &c, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + for (i = 0; i < 1000; ++i) { + printf("%6d\r", i); + fflush(stdout); + n = (rand_int() & 15) + 1; + mp_rand(&a, n); + if (mp_sqrt(&a, &b) != MP_OKAY) { + printf("\nmp_sqrt() error!"); + goto LBL_ERR; + } + mp_root_u32(&a, 2uL, &c); + if (mp_cmp_mag(&b, &c) != MP_EQ) { + printf("mp_sqrt() bad result!\n"); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_is_square(void) +{ + int i, n; + + mp_int a, b; + mp_bool res; + + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + for (i = 0; i < 1000; ++i) { + printf("%6d\r", i); + fflush(stdout); + + /* test mp_is_square false negatives */ + n = (rand_int() & 7) + 1; + mp_rand(&a, n); + mp_sqr(&a, &a); + if (mp_is_square(&a, &res) != MP_OKAY) { + printf("\nfn:mp_is_square() error!"); + goto LBL_ERR; + } + if (res == MP_NO) { + printf("\nfn:mp_is_square() bad result!"); + goto LBL_ERR; + } + + /* test for false positives */ + mp_add_d(&a, 1uL, &a); + if (mp_is_square(&a, &res) != MP_OKAY) { + printf("\nfp:mp_is_square() error!"); + goto LBL_ERR; + } + if (res == MP_YES) { + printf("\nfp:mp_is_square() bad result!"); + goto LBL_ERR; + } + + } + printf("\n\n"); + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_sqrtmod_prime(void) +{ + struct mp_sqrtmod_prime_st { + unsigned long p; + unsigned long n; + mp_digit r; + }; + + static struct mp_sqrtmod_prime_st sqrtmod_prime[] = { + { 5, 14, 3 }, + { 7, 9, 4 }, + { 113, 2, 62 } + }; + int i; + + mp_int a, b, c; + if (mp_init_multi(&a, &b, &c, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + /* r^2 = n (mod p) */ + for (i = 0; i < (int)(sizeof(sqrtmod_prime)/sizeof(sqrtmod_prime[0])); ++i) { + mp_set_ul(&a, sqrtmod_prime[i].p); + mp_set_ul(&b, sqrtmod_prime[i].n); + if (mp_sqrtmod_prime(&b, &a, &c) != MP_OKAY) { + printf("Failed executing %d. mp_sqrtmod_prime\n", (i+1)); + goto LBL_ERR; + } + if (mp_cmp_d(&c, sqrtmod_prime[i].r) != MP_EQ) { + printf("Failed %d. trivial mp_sqrtmod_prime\n", (i+1)); + ndraw(&c, "r"); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_prime_rand(void) +{ + int ix; + mp_err err; + mp_int a, b; + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + /* test for size */ + for (ix = 10; ix < 128; ix++) { + printf("Testing (not safe-prime): %9d bits \r", ix); + fflush(stdout); + err = mp_prime_rand(&a, 8, ix, (rand_int() & 1) ? 0 : MP_PRIME_2MSB_ON); + if (err != MP_OKAY) { + printf("\nfailed with error: %s\n", mp_error_to_string(err)); + goto LBL_ERR; + } + if (mp_count_bits(&a) != ix) { + printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix); + goto LBL_ERR; + } + } + printf("\n"); + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_prime_is_prime(void) +{ + int ix; + mp_err err; + mp_bool cnt, fu; + + mp_int a, b; + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + /* strong Miller-Rabin pseudoprime to the first 200 primes (F. Arnault) */ + puts("Testing mp_prime_is_prime() with Arnault's pseudoprime 803...901 \n"); + mp_read_radix(&a, + "91xLNF3roobhzgTzoFIG6P13ZqhOVYSN60Fa7Cj2jVR1g0k89zdahO9/kAiRprpfO1VAp1aBHucLFV/qLKLFb+zonV7R2Vxp1K13ClwUXStpV0oxTNQVjwybmFb5NBEHImZ6V7P6+udRJuH8VbMEnS0H8/pSqQrg82OoQQ2fPpAk6G1hkjqoCv5s/Yr", + 64); + mp_prime_is_prime(&a, mp_prime_rabin_miller_trials(mp_count_bits(&a)), &cnt); + if (cnt == MP_YES) { + printf("Arnault's pseudoprime is not prime but mp_prime_is_prime says it is.\n"); + goto LBL_ERR; + } + /* About the same size as Arnault's pseudoprime */ + puts("Testing mp_prime_is_prime() with certified prime 2^1119 + 53\n"); + mp_set(&a, 1uL); + mp_mul_2d(&a,1119,&a); + mp_add_d(&a, 53uL, &a); + err = mp_prime_is_prime(&a, mp_prime_rabin_miller_trials(mp_count_bits(&a)), &cnt); + /* small problem */ + if (err != MP_OKAY) { + printf("\nfailed with error: %s\n", mp_error_to_string(err)); + } + /* large problem */ + if (cnt == MP_NO) { + printf("A certified prime is a prime but mp_prime_is_prime says it is not.\n"); + } + if ((err != MP_OKAY) || (cnt == MP_NO)) { + printf("prime tested was: 0x"); + mp_fwrite(&a,16,stdout); + putchar('\n'); + goto LBL_ERR; + } + for (ix = 16; ix < 128; ix++) { + printf("Testing ( safe-prime): %9d bits \r", ix); + fflush(stdout); + err = mp_prime_rand(&a, 8, ix, ((rand_int() & 1) ? 0 : MP_PRIME_2MSB_ON) | MP_PRIME_SAFE); + if (err != MP_OKAY) { + printf("\nfailed with error: %s\n", mp_error_to_string(err)); + goto LBL_ERR; + } + if (mp_count_bits(&a) != ix) { + printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix); + goto LBL_ERR; + } + /* let's see if it's really a safe prime */ + mp_sub_d(&a, 1uL, &b); + mp_div_2(&b, &b); + err = mp_prime_is_prime(&b, mp_prime_rabin_miller_trials(mp_count_bits(&b)), &cnt); + /* small problem */ + if (err != MP_OKAY) { + printf("\nfailed with error: %s\n", mp_error_to_string(err)); + } + /* large problem */ + if (cnt == MP_NO) { + printf("\nsub is not prime!\n"); + } + mp_prime_frobenius_underwood(&b, &fu); + if (fu == MP_NO) { + printf("\nfrobenius-underwood says sub is not prime!\n"); + } + if ((err != MP_OKAY) || (cnt == MP_NO)) { + printf("prime tested was: 0x"); + mp_fwrite(&a,16,stdout); + putchar('\n'); + printf("sub tested was: 0x"); + mp_fwrite(&b,16,stdout); + putchar('\n'); + goto LBL_ERR; + } + + } + /* Check regarding problem #143 */ +#ifndef MP_8BIT + mp_read_radix(&a, + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", + 16); + err = mp_prime_strong_lucas_selfridge(&a, &cnt); + /* small problem */ + if (err != MP_OKAY) { + printf("\nmp_prime_strong_lucas_selfridge failed with error: %s\n", mp_error_to_string(err)); + } + /* large problem */ + if (cnt == MP_NO) { + printf("\n\nissue #143 - mp_prime_strong_lucas_selfridge FAILED!\n"); + } + if ((err != MP_OKAY) || (cnt == MP_NO)) { + printf("prime tested was: 0x"); + mp_fwrite(&a,16,stdout); + putchar('\n'); + goto LBL_ERR; + } +#endif + + printf("\n\n"); + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; + +} + + +static int test_mp_prime_next_prime(void) +{ + mp_err err; + mp_int a, b, c; + + mp_init_multi(&a, &b, &c, NULL); + + + /* edge cases */ + mp_set(&a, 0u); + if ((err = mp_prime_next_prime(&a, 5, 0)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_cmp_d(&a, 2u) != MP_EQ) { + printf("mp_prime_next_prime: output should have been 2 but was: "); + mp_fwrite(&a,10,stdout); + putchar('\n'); + goto LBL_ERR; + } + + mp_set(&a, 0u); + if ((err = mp_prime_next_prime(&a, 5, 1)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_cmp_d(&a, 3u) != MP_EQ) { + printf("mp_prime_next_prime: output should have been 3 but was: "); + mp_fwrite(&a,10,stdout); + putchar('\n'); + goto LBL_ERR; + } + + mp_set(&a, 2u); + if ((err = mp_prime_next_prime(&a, 5, 0)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_cmp_d(&a, 3u) != MP_EQ) { + printf("mp_prime_next_prime: output should have been 3 but was: "); + mp_fwrite(&a,10,stdout); + putchar('\n'); + goto LBL_ERR; + } + + mp_set(&a, 2u); + if ((err = mp_prime_next_prime(&a, 5, 1)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_cmp_d(&a, 3u) != MP_EQ) { + printf("mp_prime_next_prime: output should have been 3 but was: "); + mp_fwrite(&a,10,stdout); + putchar('\n'); + goto LBL_ERR; + } + mp_set(&a, 8); + if ((err = mp_prime_next_prime(&a, 5, 1)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_cmp_d(&a, 11u) != MP_EQ) { + printf("mp_prime_next_prime: output should have been 11 but was: "); + mp_fwrite(&a,10,stdout); + putchar('\n'); + goto LBL_ERR; + } + /* 2^300 + 157 is a 300 bit large prime to guarantee a multi-limb bigint */ + if ((err = mp_2expt(&a, 300)) != MP_OKAY) { + goto LBL_ERR; + } + mp_set_u32(&b, 157); + if ((err = mp_add(&a, &b, &a)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_copy(&a, &b)) != MP_OKAY) { + goto LBL_ERR; + } + + /* 2^300 + 385 is the next prime */ + mp_set_u32(&c, 228); + if ((err = mp_add(&b, &c, &b)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_prime_next_prime(&a, 5, 0)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_cmp(&a, &b) != MP_EQ) { + printf("mp_prime_next_prime: output should have been\n"); + mp_fwrite(&b,10,stdout); + putchar('\n'); + printf("but was:\n"); + mp_fwrite(&a,10,stdout); + putchar('\n'); + goto LBL_ERR; + } + + /* Use another temporary variable or recompute? Mmh... */ + if ((err = mp_2expt(&a, 300)) != MP_OKAY) { + goto LBL_ERR; + } + mp_set_u32(&b, 157); + if ((err = mp_add(&a, &b, &a)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_copy(&a, &b)) != MP_OKAY) { + goto LBL_ERR; + } + + /* 2^300 + 631 is the next prime congruent to 3 mod 4*/ + mp_set_u32(&c, 474); + if ((err = mp_add(&b, &c, &b)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_prime_next_prime(&a, 5, 1)) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_cmp(&a, &b) != MP_EQ) { + printf("mp_prime_next_prime (bbs): output should have been\n"); + mp_fwrite(&b,10,stdout); + putchar('\n'); + printf("but was:\n"); + mp_fwrite(&a,10,stdout); + putchar('\n'); + goto LBL_ERR; + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_montgomery_reduce(void) +{ + mp_digit mp; + int ix, i, n; + char buf[4096]; + + /* size_t written; */ + + mp_int a, b, c, d, e; + if (mp_init_multi(&a, &b, &c, &d, &e, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + /* test montgomery */ + for (i = 1; i <= 10; i++) { + if (i == 10) + i = 1000; + printf(" digit size: %2d\r", i); + fflush(stdout); + 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_int()) % (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) { +/* *INDENT-OFF* */ + printf("d = e mod a, c = e MOD a\n"); + mp_to_decimal(&a, buf, sizeof(buf)); printf("a = %s\n", buf); + mp_to_decimal(&e, buf, sizeof(buf)); printf("e = %s\n", buf); + mp_to_decimal(&d, buf, sizeof(buf)); printf("d = %s\n", buf); + mp_to_decimal(&c, buf, sizeof(buf)); printf("c = %s\n", buf); + + printf("compare no compare!\n"); goto LBL_ERR; +/* *INDENT-ON* */ + } + /* only one big montgomery reduction */ + if (i > 10) { + n = 1000; + ix = 100; + } + } + } + } + + printf("\n\n"); + + mp_clear_multi(&a, &b, &c, &d, &e, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, &e, NULL); + return EXIT_FAILURE; + +} + +static int test_mp_read_radix(void) +{ + char buf[4096]; + size_t written; + mp_err err; + + mp_int a; + if (mp_init_multi(&a, NULL)!= MP_OKAY) goto LTM_ERR; + + if ((err = mp_read_radix(&a, "123456", 10)) != MP_OKAY) goto LTM_ERR; + + if ((err = mp_to_radix(&a, buf, SIZE_MAX, &written, 10)) != MP_OKAY) goto LTM_ERR; + printf(" '123456' a == %s, length = %zu\n", buf, written); + + /* See comment in bn_mp_to_radix.c */ + /* + if( (err = mp_to_radix(&a, buf, 3u, &written, 10) ) != MP_OKAY) goto LTM_ERR; + printf(" '56' a == %s, length = %zu\n", buf, written); + + if( (err = mp_to_radix(&a, buf, 4u, &written, 10) ) != MP_OKAY) goto LTM_ERR; + printf(" '456' a == %s, length = %zu\n", buf, written); + if( (err = mp_to_radix(&a, buf, 30u, &written, 10) ) != MP_OKAY) goto LTM_ERR; + printf(" '123456' a == %s, length = %zu, error = %s\n", + buf, written, mp_error_to_string(err)); + */ + if ((err = mp_read_radix(&a, "-123456", 10)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_to_radix(&a, buf, SIZE_MAX, &written, 10)) != MP_OKAY) goto LTM_ERR; + printf(" '-123456' a == %s, length = %zu\n", buf, written); + + if ((err = mp_read_radix(&a, "0", 10)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_to_radix(&a, buf, SIZE_MAX, &written, 10)) != MP_OKAY) goto LTM_ERR; + printf(" '0' a == %s, length = %zu\n", buf, written); + + + + /* Although deprecated it needs to function as long as it isn't dropped */ + /* + printf("Testing deprecated mp_toradix_n\n"); + if( (err = mp_read_radix(&a, "-123456", 10) ) != MP_OKAY) goto LTM_ERR; + if( (err = mp_toradix_n(&a, buf, 10, 3) ) != MP_OKAY) goto LTM_ERR; + printf("a == %s\n", buf); + if( (err = mp_toradix_n(&a, buf, 10, 4) ) != MP_OKAY) goto LTM_ERR; + printf("a == %s\n", buf); + if( (err = mp_toradix_n(&a, buf, 10, 30) ) != MP_OKAY) goto LTM_ERR; + printf("a == %s\n", buf); + */ + + + while (0) { + char *s = fgets(buf, sizeof(buf), stdin); + if (s != buf) break; + mp_read_radix(&a, buf, 10); + mp_prime_next_prime(&a, 5, 1); + mp_to_radix(&a, buf, sizeof(buf), NULL, 10); + printf("%s, %lu\n", buf, (unsigned long)a.dp[0] & 3uL); + } + + mp_clear(&a); + return EXIT_SUCCESS; +LTM_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + +static int test_mp_cnt_lsb(void) +{ + int ix; + + mp_int a, b; + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + mp_set(&a, 1uL); + for (ix = 0; ix < 1024; ix++) { + if (mp_cnt_lsb(&a) != ix) { + printf("Failed at %d, %d\n", ix, mp_cnt_lsb(&a)); + goto LBL_ERR; + } + mp_mul_2(&a, &a); + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; + +} + +static int test_mp_reduce_2k(void) +{ + int ix, cnt; + + mp_int a, b, c, d; + if (mp_init_multi(&a, &b, &c, &d, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + /* test mp_reduce_2k */ + for (cnt = 3; cnt <= 128; ++cnt) { + mp_digit tmp; + + mp_2expt(&a, cnt); + mp_sub_d(&a, 2uL, &a); /* a = 2**cnt - 2 */ + + printf("\r %4d bits", cnt); + printf("(%d)", mp_reduce_is_2k(&a)); + mp_reduce_2k_setup(&a, &tmp); + printf("(%lu)", (unsigned long) tmp); + for (ix = 0; ix < 1000; ix++) { + if (!(ix & 127)) { + printf("."); + fflush(stdout); + } + mp_rand(&b, (cnt / MP_DIGIT_BIT + 1) * 2); + mp_copy(&c, &b); + mp_mod(&c, &a, &c); + mp_reduce_2k(&b, &a, 2uL); + if (mp_cmp(&c, &b) != MP_EQ) { + printf("FAILED\n"); + goto LBL_ERR; + } + } + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_mp_div_3(void) +{ + int cnt; + + mp_int a, b, c, d, e; + if (mp_init_multi(&a, &b, &c, &d, &e, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + /* test mp_div_3 */ + mp_set(&d, 3uL); + for (cnt = 0; cnt < 10000;) { + mp_digit r2; + + if (!(++cnt & 127)) { + printf("%9d\r", cnt); + fflush(stdout); + } + mp_rand(&a, abs(rand_int()) % 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("\nmp_div_3 => Failure\n"); + goto LBL_ERR; + } + } + printf("\nPassed div_3 testing"); + + mp_clear_multi(&a, &b, &c, &d, &e, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, &e, NULL); + return EXIT_FAILURE; +} + +static int test_mp_dr_reduce(void) +{ + mp_digit mp; + int cnt; + unsigned rr; + int ix; + + mp_int a, b, c; + if (mp_init_multi(&a, &b, &c, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + + /* test the DR reduction */ + for (cnt = 2; cnt < 32; cnt++) { + printf("\r%d digit modulus", 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("."); + fflush(stdout); + } + mp_sqr(&b, &b); + mp_add_d(&b, 1uL, &b); + mp_copy(&b, &c); + + mp_mod(&b, &a, &b); + mp_dr_setup(&a, &mp); + mp_dr_reduce(&c, &a, mp); + + if (mp_cmp(&b, &c) != MP_EQ) { + printf("Failed on trial %u\n", rr); + goto LBL_ERR; + } + } while (++rr < 500); + printf(" passed"); + fflush(stdout); + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_reduce_2k_l(void) +{ +# if LTM_DEMO_TEST_REDUCE_2K_L + mp_int a, b, c, d; + int cnt; + char buf[4096]; + size_t length[1]; + if (mp_init_multi(&a, &b, NULL)!= MP_OKAY) { + return EXIT_FAILURE; + } + /* test the mp_reduce_2k_l code */ +# if LTM_DEMO_TEST_REDUCE_2K_L == 1 + /* 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 LTM_DEMO_TEST_REDUCE_2K_L == 2 + /* 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); +# else +# error oops +# endif + *length = sizeof(buf); + mp_to_radix(&a, buf, length, 10); + printf("\n\np==%s, length = %zu\n", buf, *length); + /* 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"); + goto LBL_ERR; + } + 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 < (int)(1uL << 20); cnt++) { + mp_sqr(&b, &b); + mp_add_d(&b, 1uL, &b); + mp_reduce_2k_l(&b, &a, &d); + mp_sqr(&c, &c); + mp_add_d(&c, 1uL, &c); + mp_mod(&c, &a, &c); + if (mp_cmp(&b, &c) != MP_EQ) { + printf("mp_reduce_2k_l() failed at step %d\n", cnt); + mp_to_hex(&b, buf, sizeof(buf)); + printf("b == %s\n", buf); + mp_to_hex(&c, buf, sizeof(buf)); + printf("c == %s\n", buf); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +#else + return EXIT_SUCCESS; +# endif /* LTM_DEMO_TEST_REDUCE_2K_L */ +} +/* stripped down version of mp_radix_size. The faster version can be off by up t +o +3 */ +/* TODO: This function should be removed, replaced by mp_radix_size, mp_radix_size_overestimate in 2.0 */ +static mp_err s_rs(const mp_int *a, int radix, uint32_t *size) +{ + mp_err res; + uint32_t digs = 0u; + mp_int t; + mp_digit d; + *size = 0u; + if (mp_iszero(a) == MP_YES) { + *size = 2u; + return MP_OKAY; + } + if (radix == 2) { + *size = (uint32_t)mp_count_bits(a) + 1u; + return MP_OKAY; + } + if ((res = mp_init_copy(&t, a)) != MP_OKAY) { + return res; + } + t.sign = MP_ZPOS; + 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); + *size = digs + 1; + return MP_OKAY; +} +static int test_mp_log_u32(void) +{ + mp_int a; + mp_digit d; + uint32_t base, lb, size; + const uint32_t max_base = MP_MIN(UINT32_MAX, MP_DIGIT_MAX); + + if (mp_init(&a) != MP_OKAY) { + goto LBL_ERR; + } + + /* + base a result + 0 x MP_VAL + 1 x MP_VAL + */ + mp_set(&a, 42uL); + base = 0u; + if (mp_log_u32(&a, base, &lb) != MP_VAL) { + goto LBL_ERR; + } + base = 1u; + if (mp_log_u32(&a, base, &lb) != MP_VAL) { + goto LBL_ERR; + } + /* + base a result + 2 0 MP_VAL + 2 1 0 + 2 2 1 + 2 3 1 + */ + base = 2u; + mp_zero(&a); + if (mp_log_u32(&a, base, &lb) != MP_VAL) { + goto LBL_ERR; + } + + for (d = 1; d < 4; d++) { + mp_set(&a, d); + if (mp_log_u32(&a, base, &lb) != MP_OKAY) { + goto LBL_ERR; + } + if (lb != ((d == 1)?0uL:1uL)) { + goto LBL_ERR; + } + } + /* + base a result + 3 0 MP_VAL + 3 1 0 + 3 2 0 + 3 3 1 + */ + base = 3u; + mp_zero(&a); + if (mp_log_u32(&a, base, &lb) != MP_VAL) { + goto LBL_ERR; + } + for (d = 1; d < 4; d++) { + mp_set(&a, d); + if (mp_log_u32(&a, base, &lb) != MP_OKAY) { + goto LBL_ERR; + } + if (lb != ((d < base)?0uL:1uL)) { + goto LBL_ERR; + } + } + + /* + bases 2..64 with "a" a random large constant. + The range of bases tested allows to check with + radix_size. + */ + if (mp_rand(&a, 10) != MP_OKAY) { + goto LBL_ERR; + } + for (base = 2u; base < 65u; base++) { + if (mp_log_u32(&a, base, &lb) != MP_OKAY) { + goto LBL_ERR; + } + if (s_rs(&a,(int)base, &size) != MP_OKAY) { + goto LBL_ERR; + } + /* radix_size includes the memory needed for '\0', too*/ + size -= 2; + if (lb != size) { + goto LBL_ERR; + } + } + + /* + bases 2..64 with "a" a random small constant to + test the part of mp_ilogb that uses native types. + */ + if (mp_rand(&a, 1) != MP_OKAY) { + goto LBL_ERR; + } + for (base = 2u; base < 65u; base++) { + if (mp_log_u32(&a, base, &lb) != MP_OKAY) { + goto LBL_ERR; + } + if (s_rs(&a,(int)base, &size) != MP_OKAY) { + goto LBL_ERR; + } + size -= 2; + if (lb != size) { + goto LBL_ERR; + } + } + + /*Test upper edgecase with base UINT32_MAX and number (UINT32_MAX/2)*UINT32_MAX^10 */ + mp_set(&a, max_base); + if (mp_expt_u32(&a, 10uL, &a) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_add_d(&a, max_base / 2, &a) != MP_OKAY) { + goto LBL_ERR; + } + if (mp_log_u32(&a, max_base, &lb) != MP_OKAY) { + goto LBL_ERR; + } + if (lb != 10u) { + goto LBL_ERR; + } + + mp_clear(&a); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + +static int test_mp_incr(void) +{ + mp_int a, b; + mp_err e = MP_OKAY; + + if ((e = mp_init_multi(&a, &b, NULL)) != MP_OKAY) { + goto LTM_ERR; + } + + /* Does it increment inside the limits of a MP_xBIT limb? */ + mp_set(&a, MP_MASK/2); + if ((e = mp_incr(&a)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp_d(&a, (MP_MASK/2uL) + 1uL) != MP_EQ) { + goto LTM_ERR; + } + + /* Does it increment outside of the limits of a MP_xBIT limb? */ + mp_set(&a, MP_MASK); + mp_set(&b, MP_MASK); + if ((e = mp_incr(&a)) != MP_OKAY) { + goto LTM_ERR; + } + if ((e = mp_add_d(&b, 1uL, &b)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp(&a, &b) != MP_EQ) { + goto LTM_ERR; + } + + /* Does it increment from -1 to 0? */ + mp_set(&a, 1uL); + a.sign = MP_NEG; + if ((e = mp_incr(&a)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp_d(&a, 0uL) != MP_EQ) { + goto LTM_ERR; + } + + /* Does it increment from -(MP_MASK + 1) to -MP_MASK? */ + mp_set(&a, MP_MASK); + if ((e = mp_add_d(&a, 1uL, &a)) != MP_OKAY) { + goto LTM_ERR; + } + a.sign = MP_NEG; + if ((e = mp_incr(&a)) != MP_OKAY) { + goto LTM_ERR; + } + if (a.sign != MP_NEG) { + goto LTM_ERR; + } + a.sign = MP_ZPOS; + if (mp_cmp_d(&a, MP_MASK) != MP_EQ) { + goto LTM_ERR; + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LTM_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_decr(void) +{ + mp_int a, b; + mp_err e = MP_OKAY; + + if ((e = mp_init_multi(&a, &b, NULL)) != MP_OKAY) { + goto LTM_ERR; + } + + /* Does it decrement inside the limits of a MP_xBIT limb? */ + mp_set(&a, MP_MASK/2); + if ((e = mp_decr(&a)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp_d(&a, (MP_MASK/2uL) - 1uL) != MP_EQ) { + goto LTM_ERR; + } + + /* Does it decrement outside of the limits of a MP_xBIT limb? */ + mp_set(&a, MP_MASK); + if ((e = mp_add_d(&a, 1uL, &a)) != MP_OKAY) { + goto LTM_ERR; + } + if ((e = mp_decr(&a)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp_d(&a, MP_MASK) != MP_EQ) { + goto LTM_ERR; + } + + /* Does it decrement from 0 to -1? */ + mp_zero(&a); + if ((e = mp_decr(&a)) != MP_OKAY) { + goto LTM_ERR; + } + if (a.sign == MP_NEG) { + a.sign = MP_ZPOS; + if (mp_cmp_d(&a, 1uL) != MP_EQ) { + goto LTM_ERR; + } + } else { + goto LTM_ERR; + } + + + /* Does it decrement from -MP_MASK to -(MP_MASK + 1)? */ + mp_set(&a, MP_MASK); + a.sign = MP_NEG; + mp_set(&b, MP_MASK); + b.sign = MP_NEG; + if ((e = mp_sub_d(&b, 1uL, &b)) != MP_OKAY) { + goto LTM_ERR; + } + if ((e = mp_decr(&a)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp(&a, &b) != MP_EQ) { + goto LTM_ERR; + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LTM_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +/* + Cannot test mp_exp(_d) without mp_root and vice versa. + So one of the two has to be tested from scratch. + + Numbers generated by + for i in {1..10} + do + seed=$(head -c 10000 /dev/urandom | tr -dc '[:digit:]' | head -c 120); + echo $seed; + convertbase $seed 10 64; + done + + (The program "convertbase" uses libtommath's to/from_radix functions) + + Roots were precalculated with Pari/GP + + default(realprecision,1000); + for(n=3,100,r = floor(a^(1/n));printf("\"" r "\", ")) + + All numbers as strings to simplifiy things, especially for the + low-mp branch. +*/ + +static int test_mp_root_u32(void) +{ + mp_int a, c, r; + mp_err e; + int i, j; + + const char *input[] = { + "4n9cbk886QtLQmofprid3l2Q0GD8Yv979Lh8BdZkFE8g2pDUUSMBET/+M/YFyVZ3mBp", + "5NlgzHhmIX05O5YoW5yW5reAlVNtRAlIcN2dfoATnNdc1Cw5lHZUTwNthmK6/ZLKfY6", + "3gweiHDX+ji5utraSe46IJX+uuh7iggs63xIpMP5MriU4Np+LpHI5are8RzS9pKh9xP", + "5QOJUSKMrfe7LkeyJOlupS8h7bjT+TXmZkDzOjZtfj7mdA7cbg0lRX3CuafhjIrpK8S", + "4HtYFldVkyVbrlg/s7kmaA7j45PvLQm+1bbn6ehgP8tVoBmGbv2yDQI1iQQze4AlHyN", + "3bwCUx79NAR7c68OPSp5ZabhZ9aBEr7rWNTO2oMY7zhbbbw7p6shSMxqE9K9nrTNucf", + "4j5RGb78TfuYSzrXn0z6tiAoWiRI81hGY3el9AEa9S+gN4x/AmzotHT2Hvj6lyBpE7q", + "4lwg30SXqZhEHNsl5LIXdyu7UNt0VTWebP3m7+WUL+hsnFW9xJe7UnzYngZsvWh14IE", + "1+tcqFeRuGqjRADRoRUJ8gL4UUSFQVrVVoV6JpwVcKsuBq5G0pABn0dLcQQQMViiVRj", + "hXwxuFySNSFcmbrs/coz4FUAaUYaOEt+l4V5V8vY71KyBvQPxRq/6lsSrG2FHvWDax" + }; + /* roots 3-100 of the above */ + const char *root[10][100] = { + { + "9163694094944489658600517465135586130944", + "936597377180979771960755204040", "948947857956884030956907", + "95727185767390496595", "133844854039712620", "967779611885360", + "20926191452627", "974139547476", "79203891950", "9784027073", + "1667309744", "365848129", "98268452", "31109156", "11275351", + "4574515", "2040800", "986985", "511525", "281431", "163096", + "98914", "62437", "40832", "27556", "19127", "13614", "9913", + "7367", "5577", "4294", "3357", "2662", "2138", "1738", "1428", + "1185", "993", "839", "715", "613", "530", "461", "403", "355", + "314", "279", "249", "224", "202", "182", "166", "151", "138", + "126", "116", "107", "99", "92", "85", "79", "74", "69", "65", "61", + "57", "54", "51", "48", "46", "43", "41", "39", "37", "36", "34", + "32", "31", "30", "28", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "9534798256755061606359588498764080011382", + "964902943621813525741417593772", "971822399862464674540423", + "97646291566833512831", "136141536090599560", "982294733581430", + "21204945933335", "985810529393", "80066084985", "9881613813", + "1682654547", "368973625", "99051783", "31341581", "11354620", + "4604882", "2053633", "992879", "514434", "282959", "163942", + "99406", "62736", "41020", "27678", "19208", "13670", "9952", + "7395", "5598", "4310", "3369", "2671", "2145", "1744", "1433", + "1189", "996", "842", "717", "615", "531", "462", "404", "356", + "315", "280", "250", "224", "202", "183", "166", "151", "138", + "127", "116", "107", "99", "92", "85", "80", "74", "70", "65", "61", + "58", "54", "51", "48", "46", "43", "41", "39", "37", "36", "34", + "32", "31", "30", "29", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "8398539113202579297642815367509019445624", + "877309458945432597462853440936", "900579899458998599215071", + "91643543761699761637", "128935656335800903", "936647990947203", + "20326748623514", "948988882684", "77342677787", "9573063447", + "1634096832", "359076114", "96569670", "30604705", "11103188", + "4508519", "2012897", "974160", "505193", "278105", "161251", + "97842", "61788", "40423", "27291", "18949", "13492", "9826", + "7305", "5532", "4260", "3332", "2642", "2123", "1726", "1418", + "1177", "986", "834", "710", "610", "527", "458", "401", "353", + "312", "278", "248", "223", "201", "181", "165", "150", "137", + "126", "116", "107", "99", "91", "85", "79", "74", "69", "65", "61", + "57", "54", "51", "48", "46", "43", "41", "39", "37", "35", "34", + "32", "31", "30", "28", "27", "26", "25", "24", "23", "22", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "9559098494021810340217797724866627755195", + "966746709063325235560830083787", "973307706084821682248292", + "97770642291138756434", "136290128605981259", "983232784778520", + "21222944848922", "986563584410", "80121684894", "9887903837", + "1683643206", "369174929", "99102220", "31356542", "11359721", + "4606836", "2054458", "993259", "514621", "283057", "163997", + "99437", "62755", "41032", "27686", "19213", "13674", "9955", + "7397", "5599", "4311", "3370", "2672", "2146", "1744", "1433", + "1189", "996", "842", "717", "615", "532", "462", "404", "356", + "315", "280", "250", "224", "202", "183", "166", "151", "138", + "127", "116", "107", "99", "92", "86", "80", "74", "70", "65", "61", + "58", "54", "51", "48", "46", "43", "41", "39", "37", "36", "34", + "32", "31", "30", "29", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "8839202025813295923132694443541993309220", + "911611499784863252820288596270", "928640961450376817534853", + "94017030509441723821", "131792686685970629", "954783483196511", + "20676214073400", "963660189823", "78428929840", "9696237956", + "1653495486", "363032624", "97562430", "30899570", "11203842", + "4547110", "2029216", "981661", "508897", "280051", "162331", + "98469", "62168", "40663", "27446", "19053", "13563", "9877", + "7341", "5558", "4280", "3347", "2654", "2132", "1733", "1424", + "1182", "990", "837", "713", "612", "529", "460", "402", "354", + "313", "279", "249", "223", "201", "182", "165", "150", "138", + "126", "116", "107", "99", "92", "85", "79", "74", "69", "65", "61", + "57", "54", "51", "48", "46", "43", "41", "39", "37", "36", "34", + "32", "31", "30", "28", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "8338442683973420410660145045849076963795", + "872596990706967613912664152945", "896707843885562730147307", + "91315073695274540969", "128539440806486007", "934129001105825", + "20278149285734", "946946589774", "77191347471", "9555892093", + "1631391010", "358523975", "96431070", "30563524", "11089126", + "4503126", "2010616", "973111", "504675", "277833", "161100", + "97754", "61734", "40390", "27269", "18934", "13482", "9819", + "7300", "5528", "4257", "3330", "2641", "2122", "1725", "1417", + "1177", "986", "833", "710", "609", "527", "458", "401", "353", + "312", "278", "248", "222", "200", "181", "165", "150", "137", + "126", "116", "107", "99", "91", "85", "79", "74", "69", "65", "61", + "57", "54", "51", "48", "46", "43", "41", "39", "37", "35", "34", + "32", "31", "30", "28", "27", "26", "25", "24", "23", "22", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "9122818552483814953977703257848970704164", + "933462289569511464780529972314", "946405863353935713909178", + "95513446972056321834", "133588658082928446", + "966158521967027", "20895030642048", "972833934108", + "79107381638", "9773098125", "1665590516", "365497822", + "98180628", "31083090", "11266459", "4571108", "2039360", + "986323", "511198", "281260", "163001", "98858", + "62404", "40811", "27543", "19117", "13608", "9908", + "7363", "5575", "4292", "3356", "2661", "2138", + "1737", "1428", "1185", "993", "839", "714", "613", + "530", "461", "403", "355", "314", "279", "249", + "224", "202", "182", "165", "151", "138", "126", + "116", "107", "99", "92", "85", "79", "74", "69", + "65", "61", "57", "54", "51", "48", "46", "43", + "41", "39", "37", "36", "34", "32", "31", "30", + "28", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", + "16", "16", "15" + }, { + "9151329724083804100369546479681933027521", + "935649419557299174433860420387", "948179413831316112751907", + "95662582675170358900", "133767426788182384", + "967289728859610", "20916775466497", "973745045600", + "79174731802", "9780725058", "1666790321", "365742295", + "98241919", "31101281", "11272665", "4573486", "2040365", + "986785", "511426", "281380", "163067", "98897", + "62427", "40826", "27552", "19124", "13612", "9911", + "7366", "5576", "4294", "3357", "2662", "2138", + "1738", "1428", "1185", "993", "839", "715", "613", + "530", "461", "403", "355", "314", "279", "249", + "224", "202", "182", "165", "151", "138", "126", + "116", "107", "99", "92", "85", "79", "74", "69", + "65", "61", "57", "54", "51", "48", "46", "43", + "41", "39", "37", "36", "34", "32", "31", "30", + "28", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", + "16", "16", "15" + }, { + "6839396355168045468586008471269923213531", + "752078770083218822016981965090", "796178899357307807726034", + "82700643015444840424", "118072966296549115", + "867224751770392", "18981881485802", "892288574037", + "73130030771", "9093989389", "1558462688", "343617470", + "92683740", "29448679", "10708016", "4356820", "1948676", + "944610", "490587", "270425", "156989", "95362", + "60284", "39477", "26675", "18536", "13208", "9627", + "7161", "5426", "4181", "3272", "2596", "2087", + "1697", "1395", "1159", "971", "821", "700", "601", + "520", "452", "396", "348", "308", "274", "245", + "220", "198", "179", "163", "148", "136", "124", + "114", "106", "98", "91", "84", "78", "73", "68", + "64", "60", "57", "53", "50", "48", "45", "43", + "41", "39", "37", "35", "34", "32", "31", "29", + "28", "27", "26", "25", "24", "23", "22", "22", + "21", "20", "19", "19", "18", "18", "17", "17", + "16", "16", "15" + }, { + "4788090721380022347683138981782307670424", + "575601315594614059890185238256", "642831903229558719812840", + "69196031110028430211", "101340693763170691", + "758683936560287", "16854690815260", "801767985909", + "66353290503", "8318415180", "1435359033", "318340531", + "86304307", "27544217", "10054988", "4105446", "1841996", + "895414", "466223", "257591", "149855", "91205", + "57758", "37886", "25639", "17842", "12730", "9290", + "6918", "5248", "4048", "3170", "2518", "2026", + "1649", "1357", "1128", "946", "800", "682", "586", + "507", "441", "387", "341", "302", "268", "240", + "215", "194", "176", "160", "146", "133", "122", + "112", "104", "96", "89", "83", "77", "72", "67", + "63", "59", "56", "53", "50", "47", "45", "42", + "40", "38", "36", "35", "33", "32", "30", "29", + "28", "27", "26", "25", "24", "23", "22", "21", + "21", "20", "19", "19", "18", "17", "17", "16", + "16", "15", "15" + } + }; + + if ((e = mp_init_multi(&a, &c, &r, NULL)) != MP_OKAY) { + return EXIT_FAILURE; + } +#ifdef MP_8BIT + for (i = 0; i < 1; i++) { +#else + for (i = 0; i < 10; i++) { +#endif + mp_read_radix(&a, input[i], 64); +#ifdef MP_8BIT + for (j = 3; j < 10; j++) { +#else + for (j = 3; j < 100; j++) { +#endif + mp_root_u32(&a, (uint32_t)j, &c); + mp_read_radix(&r, root[i][j-3], 10); + if (mp_cmp(&r, &c) != MP_EQ) { + fprintf(stderr, "mp_root_u32 failed at input #%d, root #%d\n", i, j); + goto LTM_ERR; + } + } + } + mp_clear_multi(&a, &c, &r, NULL); + return EXIT_SUCCESS; +LTM_ERR: + mp_clear_multi(&a, &c, &r, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_balance_mul(void) +{ + mp_int a, b, c; + mp_err e = MP_OKAY; + + const char *na = + "4b0I5uMTujCysw+1OOuOyH2FX2WymrHUqi8BBDb7XpkV/4i7vXTbEYUy/kdIfCKu5jT5JEqYkdmnn3jAYo8XShPzNLxZx9yoLjxYRyptSuOI2B1DspvbIVYXY12sxPZ4/HCJ4Usm2MU5lO/006KnDMxuxiv1rm6YZJZ0eZU"; + const char *nb = "3x9vs0yVi4hIq7poAeVcggC3WoRt0zRLKO"; + const char *nc = + "HzrSq9WVt1jDTVlwUxSKqxctu2GVD+N8+SVGaPFRqdxyld6IxDBbj27BPJzYUdR96k3sWpkO8XnDBvupGPnehpQe4KlO/KmN1PjFov/UTZYM+LYzkFcBPyV6hkkL8ePC1rlFLAHzgJMBCXVp4mRqtkQrDsZXXlcqlbTFu69wF6zDEysiX2cAtn/kP9ldblJiwYPCD8hG"; + + if ((e = mp_init_multi(&a, &b, &c, NULL)) != MP_OKAY) { + goto LTM_ERR; + } + + if ((e = mp_read_radix(&a, na, 64)) != MP_OKAY) { + goto LTM_ERR; + } + if ((e = mp_read_radix(&b, nb, 64)) != MP_OKAY) { + goto LTM_ERR; + } + + if ((e = s_mp_balance_mul(&a, &b, &c)) != MP_OKAY) { + goto LTM_ERR; + } + + if ((e = mp_read_radix(&b, nc, 64)) != MP_OKAY) { + goto LTM_ERR; + } + + if (mp_cmp(&b, &c) != MP_EQ) { + goto LTM_ERR; + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LTM_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) +static int test_s_mp_karatsuba_mul(void) +{ + mp_int a, b, c, d; + int size, err; + + if ((err = mp_init_multi(&a, &b, &c, &d, NULL)) != MP_OKAY) { + goto LTM_ERR; + } + for (size = MP_KARATSUBA_MUL_CUTOFF; size < MP_KARATSUBA_MUL_CUTOFF + 20; size++) { + if ((err = mp_rand(&a, size)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = mp_rand(&b, size)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = s_mp_karatsuba_mul(&a, &b, &c)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = s_mp_mul(&a,&b,&d)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp(&c, &d) != MP_EQ) { + fprintf(stderr, "Karatsuba multiplication failed at size %d\n", size); + goto LTM_ERR; + } + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LTM_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_karatsuba_sqr(void) +{ + mp_int a, b, c; + int size, err; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != MP_OKAY) { + goto LTM_ERR; + } + for (size = MP_KARATSUBA_SQR_CUTOFF; size < MP_KARATSUBA_SQR_CUTOFF + 20; size++) { + if ((err = mp_rand(&a, size)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = s_mp_karatsuba_sqr(&a, &b)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = s_mp_sqr(&a, &c)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp(&b, &c) != MP_EQ) { + fprintf(stderr, "Karatsuba squaring failed at size %d\n", size); + goto LTM_ERR; + } + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LTM_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_toom_mul(void) +{ + mp_int a, b, c, d; + int size, err; + +#if (MP_DIGIT_BIT == 60) + int tc_cutoff; +#endif + + if ((err = mp_init_multi(&a, &b, &c, &d, NULL)) != MP_OKAY) { + goto LTM_ERR; + } + /* This number construction is limb-size specific */ +#if (MP_DIGIT_BIT == 60) + if ((err = mp_rand(&a, 1196)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = mp_mul_2d(&a,71787 - mp_count_bits(&a), &a)) != MP_OKAY) { + goto LTM_ERR; + } + + if ((err = mp_rand(&b, 1338)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = mp_mul_2d(&b, 80318 - mp_count_bits(&b), &b)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = mp_mul_2d(&b, 6310, &b)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = mp_2expt(&c, 99000 - 1000)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = mp_add(&b, &c, &b)) != MP_OKAY) { + goto LTM_ERR; + } + + tc_cutoff = TOOM_MUL_CUTOFF; + TOOM_MUL_CUTOFF = INT_MAX; + if ((err = mp_mul(&a, &b, &c)) != MP_OKAY) { + goto LTM_ERR; + } + TOOM_MUL_CUTOFF = tc_cutoff; + if ((err = mp_mul(&a, &b, &d)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp(&c, &d) != MP_EQ) { + fprintf(stderr, "Toom-Cook 3-way multiplication failed for edgecase f1 * f2\n"); + goto LTM_ERR; + } +#endif + + for (size = MP_TOOM_MUL_CUTOFF; size < MP_TOOM_MUL_CUTOFF + 20; size++) { + if ((err = mp_rand(&a, size)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = mp_rand(&b, size)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = s_mp_toom_mul(&a, &b, &c)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = s_mp_mul(&a,&b,&d)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp(&c, &d) != MP_EQ) { + fprintf(stderr, "Toom-Cook 3-way multiplication failed at size %d\n", size); + goto LTM_ERR; + } + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LTM_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_toom_sqr(void) +{ + mp_int a, b, c; + int size, err; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != MP_OKAY) { + goto LTM_ERR; + } + for (size = MP_TOOM_SQR_CUTOFF; size < MP_TOOM_SQR_CUTOFF + 20; size++) { + if ((err = mp_rand(&a, size)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = s_mp_toom_sqr(&a, &b)) != MP_OKAY) { + goto LTM_ERR; + } + if ((err = s_mp_sqr(&a, &c)) != MP_OKAY) { + goto LTM_ERR; + } + if (mp_cmp(&b, &c) != MP_EQ) { + fprintf(stderr, "Toom-Cook 3-way squaring failed at size %d\n", size); + goto LTM_ERR; + } + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LTM_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_read_write_ubin(void) +{ + mp_int a, b, c; + int err; + size_t size, len; + unsigned char *buf = NULL; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != MP_OKAY) { + goto LTM_ERR; + } + + if ((err = mp_rand(&a, 15)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_neg(&a, &b)) != MP_OKAY) goto LTM_ERR; + + size = mp_ubin_size(&a); + printf("mp_to_ubin_size %zu\n", size); + buf = malloc(sizeof(*buf) * size); + if (buf == NULL) { + fprintf(stderr, "test_read_write_binaries (u) failed to allocate %zu bytes\n", + sizeof(*buf) * size); + goto LTM_ERR; + } + + if ((err = mp_to_ubin(&a, buf, size, &len)) != MP_OKAY) goto LTM_ERR; + printf("mp_to_ubin len = %zu\n", len); + + if ((err = mp_from_ubin(&c, buf, len)) != MP_OKAY) goto LTM_ERR; + + if (mp_cmp(&a, &c) != MP_EQ) { + fprintf(stderr, "to/from ubin cycle failed\n"); + goto LTM_ERR; + } + free(buf); + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LTM_ERR: + free(buf); + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_read_write_sbin(void) +{ + mp_int a, b, c; + int err; + size_t size, len; + unsigned char *buf = NULL; + + if ((err = mp_init_multi(&a, &b, &c, NULL)) != MP_OKAY) { + goto LTM_ERR; + } + + if ((err = mp_rand(&a, 15)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_neg(&a, &b)) != MP_OKAY) goto LTM_ERR; + + size = mp_sbin_size(&a); + printf("mp_to_sbin_size %zu\n", size); + buf = malloc(sizeof(*buf) * size); + if (buf == NULL) { + fprintf(stderr, "test_read_write_binaries (s) failed to allocate %zu bytes\n", + sizeof(*buf) * size); + goto LTM_ERR; + } + + if ((err = mp_to_sbin(&b, buf, size, &len)) != MP_OKAY) goto LTM_ERR; + printf("mp_to_sbin len = %zu\n", len); + + if ((err = mp_from_sbin(&c, buf, len)) != MP_OKAY) goto LTM_ERR; + + if (mp_cmp(&b, &c) != MP_EQ) { + fprintf(stderr, "to/from ubin cycle failed\n"); + goto LTM_ERR; + } + + free(buf); + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LTM_ERR: + free(buf); + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_pack_unpack(void) +{ + mp_int a, b; + int err; + size_t written, count; + unsigned char *buf = NULL; + + mp_order order = MP_LSB_FIRST; + mp_endian endianess = MP_NATIVE_ENDIAN; + + if ((err = mp_init_multi(&a, &b, NULL)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_rand(&a, 15)) != MP_OKAY) goto LTM_ERR; + + count = mp_pack_count(&a, 0, 1); + + buf = malloc(count); + if (buf == NULL) { + fprintf(stderr, "test_pack_unpack failed to allocate\n"); + goto LTM_ERR; + } + + if ((err = mp_pack((void *)buf, count, &written, order, 1, + endianess, 0, &a)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_unpack(&b, count, order, 1, + endianess, 0, (const void *)buf)) != MP_OKAY) goto LTM_ERR; + + if (mp_cmp(&a, &b) != MP_EQ) { + fprintf(stderr, "pack/unpack cycle failed\n"); + goto LTM_ERR; + } + + free(buf); + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LTM_ERR: + free(buf); + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int unit_tests(int argc, char **argv) +{ + static const struct { + const char *name; + int (*fn)(void); + } test[] = { +#define T0(n) { #n, test_##n } +#define T1(n, o) { #n, MP_HAS(o) ? test_##n : NULL } +#define T2(n, o1, o2) { #n, MP_HAS(o1) && MP_HAS(o2) ? test_##n : NULL } + T0(feature_detection), + T0(trivial_stuff), + T2(mp_get_set_i32, MP_GET_I32, MP_GET_MAG_U32), + T2(mp_get_set_i64, MP_GET_I64, MP_GET_MAG_U64), + T1(mp_and, MP_AND), + T1(mp_cnt_lsb, MP_CNT_LSB), + T1(mp_complement, MP_COMPLEMENT), + T1(mp_decr, MP_DECR), + T1(mp_div_3, MP_DIV_3), + T1(mp_dr_reduce, MP_DR_REDUCE), + T2(mp_pack_unpack,MP_PACK, MP_UNPACK), + T2(mp_fread_fwrite, MP_FREAD, MP_FWRITE), + T1(mp_get_u32, MP_GET_I32), + T1(mp_get_u64, MP_GET_I64), + T1(mp_get_ul, MP_GET_L), + T1(mp_log_u32, MP_LOG_U32), + T1(mp_incr, MP_INCR), + T1(mp_invmod, MP_INVMOD), + T1(mp_is_square, MP_IS_SQUARE), + T1(mp_kronecker, MP_KRONECKER), + T1(mp_montgomery_reduce, MP_MONTGOMERY_REDUCE), + T1(mp_root_u32, MP_ROOT_U32), + T1(mp_or, MP_OR), + T1(mp_prime_is_prime, MP_PRIME_IS_PRIME), + T1(mp_prime_next_prime, MP_PRIME_NEXT_PRIME), + T1(mp_prime_rand, MP_PRIME_RAND), + T1(mp_rand, MP_RAND), + T1(mp_read_radix, MP_READ_RADIX), + T1(mp_read_write_ubin, MP_TO_UBIN), + T1(mp_read_write_sbin, MP_TO_SBIN), + T1(mp_reduce_2k, MP_REDUCE_2K), + T1(mp_reduce_2k_l, MP_REDUCE_2K_L), +#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) + T1(mp_set_double, MP_SET_DOUBLE), +#endif + T1(mp_signed_rsh, MP_SIGNED_RSH), + T1(mp_sqrt, MP_SQRT), + T1(mp_sqrtmod_prime, MP_SQRTMOD_PRIME), + T1(mp_xor, MP_XOR), + T1(s_mp_balance_mul, S_MP_BALANCE_MUL), + T1(s_mp_karatsuba_mul, S_MP_KARATSUBA_MUL), + T1(s_mp_karatsuba_sqr, S_MP_KARATSUBA_SQR), + T1(s_mp_toom_mul, S_MP_TOOM_MUL), + T1(s_mp_toom_sqr, S_MP_TOOM_SQR) +#undef T2 +#undef T1 + }; + unsigned long i, ok, fail, nop; + uint64_t t; + int j; + + ok = fail = nop = 0; + + t = (uint64_t)time(NULL); + printf("SEED: 0x%"PRIx64"\n\n", t); + s_mp_rand_jenkins_init(t); + mp_rand_source(s_mp_rand_jenkins); + + for (i = 0; i < sizeof(test) / sizeof(test[0]); ++i) { + if (argc > 1) { + for (j = 1; j < argc; ++j) { + if (strstr(test[i].name, argv[j]) != NULL) { + break; + } + } + if (j == argc) continue; + } + printf("TEST %s\n\n", test[i].name); + if (test[i].fn == NULL) { + nop++; + printf("NOP %s\n\n", test[i].name); + } else if (test[i].fn() == EXIT_SUCCESS) { + ok++; + printf("\n\n"); + } else { + fail++; + printf("\n\nFAIL %s\n\n", test[i].name); + } + } + printf("Tests OK/NOP/FAIL: %lu/%lu/%lu\n", ok, nop, fail); + + if (fail != 0) return EXIT_FAILURE; + else return EXIT_SUCCESS; +} + +int main(int argc, char **argv) +{ + print_header(); + + return unit_tests(argc, argv); +} diff --git a/lib/hcrypto/libtommath/demo/timing.c b/lib/hcrypto/libtommath/demo/timing.c index d4660a9b5..f620b8cd4 100644 --- a/lib/hcrypto/libtommath/demo/timing.c +++ b/lib/hcrypto/libtommath/demo/timing.c @@ -1,7 +1,11 @@ -#include #include +#include +#include +#include +#include -ulong64 _tt; +#define MP_WUR +#include #ifdef IOWNANATHLON #include @@ -10,44 +14,52 @@ ulong64 _tt; #define SLEEP #endif +#ifdef LTM_TIMING_REAL_RAND +#define LTM_TIMING_RAND_SEED time(NULL) +#else +#define LTM_TIMING_RAND_SEED 23 +#endif -void ndraw(mp_int * a, char *name) + +static void ndraw(mp_int *a, const char *name) { char buf[4096]; printf("%s: ", name); - mp_toradix(a, buf, 64); + mp_to_radix(a, buf, sizeof(buf), NULL, 64); printf("%s\n", buf); } -static void draw(mp_int * a) +static void draw(mp_int *a) { ndraw(a, ""); } -unsigned long lfsr = 0xAAAAAAAAUL; +static unsigned long lfsr = 0xAAAAAAAAuL; -int lbit(void) +static unsigned int lbit(void) { - if (lfsr & 0x80000000UL) { - lfsr = ((lfsr << 1) ^ 0x8000001BUL) & 0xFFFFFFFFUL; - return 1; + if ((lfsr & 0x80000000uL) != 0uL) { + lfsr = ((lfsr << 1) ^ 0x8000001BuL) & 0xFFFFFFFFuL; + return 1u; } else { lfsr <<= 1; - return 0; + return 0u; } } /* RDTSC from Scott Duplichan */ -static ulong64 TIMFUNC(void) +static uint64_t 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; + /* version from http://www.mcs.anl.gov/~kazutomo/rdtsc.html + * the old code always got a warning issued by gcc, clang did not complain... + */ + unsigned hi, lo; + __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); + return ((uint64_t)lo)|(((uint64_t)hi)<<32); #else /* gcc-IA64 version */ unsigned long result; __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory"); @@ -58,7 +70,7 @@ static ulong64 TIMFUNC(void) return result; #endif - // Microsoft and Intel Windows compilers + /* Microsoft and Intel Windows compilers */ #elif defined _M_IX86 __asm rdtsc #elif defined _M_AMD64 @@ -73,17 +85,51 @@ static ulong64 TIMFUNC(void) #endif } +#if 1 #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); +#else +#define DO2(x) x; x; +#define DO4(x) DO2(x); DO2(x); +#define DO8(x) DO4(x); DO4(x); +#define DO(x) DO8(x); DO8(x); +#endif -int main(void) +#ifdef TIMING_NO_LOGS +#define FOPEN(a, b) NULL +#define FPRINTF(a,b,c,d) +#define FFLUSH(a) +#define FCLOSE(a) (void)(a) +#else +#define FOPEN(a,b) fopen(a,b) +#define FPRINTF(a,b,c,d) fprintf(a,b,c,d) +#define FFLUSH(a) fflush(a) +#define FCLOSE(a) fclose(a) +#endif + +static int should_test(const char *test, int argc, char **argv) { - ulong64 tt, gg, CLK_PER_SEC; + int j; + if (argc > 1) { + for (j = 1; j < argc; ++j) { + if (strstr(test, argv[j]) != NULL) { + return 1; + } + } + if (j == argc) return 0; + } + return 1; +} + +int main(int argc, char **argv) +{ + uint64_t 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; +#ifdef LTM_TIMING_PRIME_IS_PRIME + const char *name; + int m; +#endif + int n, cnt, ix, old_kara_m, old_kara_s, old_toom_m, old_toom_s; unsigned rr; mp_init(&a); @@ -93,227 +139,268 @@ int main(void) mp_init(&e); mp_init(&f); - srand(time(NULL)); + srand(LTM_TIMING_RAND_SEED); - /* 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); + printf("CLK_PER_SEC == %" PRIu64 "\n", CLK_PER_SEC); - 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); +#ifdef LTM_TIMING_PRIME_IS_PRIME + if (should_test("prime", argc, argv)) { + for (m = 0; m < 2; ++m) { + if (m == 0) { + name = " Arnault"; + mp_read_radix(&a, + "91xLNF3roobhzgTzoFIG6P13ZqhOVYSN60Fa7Cj2jVR1g0k89zdahO9/kAiRprpfO1VAp1aBHucLFV/qLKLFb+zonV7R2Vxp1K13ClwUXStpV0oxTNQVjwybmFb5NBEHImZ6V7P6+udRJuH8VbMEnS0H8/pSqQrg82OoQQ2fPpAk6G1hkjqoCv5s/Yr", + 64); + } else { + name = "2^1119 + 53"; + mp_set(&a,1u); + mp_mul_2d(&a,1119,&a); + mp_add_d(&a,53,&a); + } + cnt = mp_prime_rabin_miller_trials(mp_count_bits(&a)); + ix = -cnt; + for (; cnt >= ix; cnt += ix) { + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_prime_is_prime(&a, cnt, &n)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + if ((m == 0) && (n == MP_YES)) { + printf("Arnault's pseudoprime is not prime but mp_prime_is_prime says it is.\n"); + return EXIT_FAILURE; + } + } while (++rr < 100u); + printf("Prime-check\t%s(%2d) => %9" PRIu64 "/sec, %9" PRIu64 " cycles\n", + name, cnt, CLK_PER_SEC / tt, tt); + } } - 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: +#endif - { - char *primes[] = { - /* 2K large moduli */ - "179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586239334100047359817950870678242457666208137217", - "32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638099733077152121140120031150424541696791951097529546801429027668869927491725169", - "1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085902995208257421855249796721729039744118165938433694823325696642096892124547425283", - /* 2K moduli mersenne primes */ - "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", - "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127", - "10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087", - "1475979915214180235084898622737381736312066145333169775147771216478570297878078949377407337049389289382748507531496480477281264838760259191814463365330269540496961201113430156902396093989090226259326935025281409614983499388222831448598601834318536230923772641390209490231836446899608210795482963763094236630945410832793769905399982457186322944729636418890623372171723742105636440368218459649632948538696905872650486914434637457507280441823676813517852099348660847172579408422316678097670224011990280170474894487426924742108823536808485072502240519452587542875349976558572670229633962575212637477897785501552646522609988869914013540483809865681250419497686697771007", - "259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071", - "190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991", + if (should_test("add", argc, argv)) { + log = FOPEN("logs/add.log", "w"); + for (cnt = 8; cnt <= 128; cnt += 8) { + SLEEP; + mp_rand(&a, cnt); + mp_rand(&b, cnt); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_add(&a, &b, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100000u); + printf("Adding\t\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF(log, "%6d %9" PRIu64 "\n", cnt * MP_DIGIT_BIT, tt); + FFLUSH(log); + } + FCLOSE(log); + } - /* DR moduli */ - "14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368612079", - "101745825697019260773923519755878567461315282017759829107608914364075275235254395622580447400994175578963163918967182013639660669771108475957692810857098847138903161308502419410142185759152435680068435915159402496058513611411688900243039", - "736335108039604595805923406147184530889923370574768772191969612422073040099331944991573923112581267542507986451953227192970402893063850485730703075899286013451337291468249027691733891486704001513279827771740183629161065194874727962517148100775228363421083691764065477590823919364012917984605619526140821797602431", - "38564998830736521417281865696453025806593491967131023221754800625044118265468851210705360385717536794615180260494208076605798671660719333199513807806252394423283413430106003596332513246682903994829528690198205120921557533726473585751382193953592127439965050261476810842071573684505878854588706623484573925925903505747545471088867712185004135201289273405614415899438276535626346098904241020877974002916168099951885406379295536200413493190419727789712076165162175783", - "542189391331696172661670440619180536749994166415993334151601745392193484590296600979602378676624808129613777993466242203025054573692562689251250471628358318743978285860720148446448885701001277560572526947619392551574490839286458454994488665744991822837769918095117129546414124448777033941223565831420390846864429504774477949153794689948747680362212954278693335653935890352619041936727463717926744868338358149568368643403037768649616778526013610493696186055899318268339432671541328195724261329606699831016666359440874843103020666106568222401047720269951530296879490444224546654729111504346660859907296364097126834834235287147", - "1487259134814709264092032648525971038895865645148901180585340454985524155135260217788758027400478312256339496385275012465661575576202252063145698732079880294664220579764848767704076761853197216563262660046602703973050798218246170835962005598561669706844469447435461092542265792444947706769615695252256130901271870341005768912974433684521436211263358097522726462083917939091760026658925757076733484173202927141441492573799914240222628795405623953109131594523623353044898339481494120112723445689647986475279242446083151413667587008191682564376412347964146113898565886683139407005941383669325997475076910488086663256335689181157957571445067490187939553165903773554290260531009121879044170766615232300936675369451260747671432073394867530820527479172464106442450727640226503746586340279816318821395210726268291535648506190714616083163403189943334431056876038286530365757187367147446004855912033137386225053275419626102417236133948503", - "1095121115716677802856811290392395128588168592409109494900178008967955253005183831872715423151551999734857184538199864469605657805519106717529655044054833197687459782636297255219742994736751541815269727940751860670268774903340296040006114013971309257028332849679096824800250742691718610670812374272414086863715763724622797509437062518082383056050144624962776302147890521249477060215148275163688301275847155316042279405557632639366066847442861422164832655874655824221577849928863023018366835675399949740429332468186340518172487073360822220449055340582568461568645259954873303616953776393853174845132081121976327462740354930744487429617202585015510744298530101547706821590188733515880733527449780963163909830077616357506845523215289297624086914545378511082534229620116563260168494523906566709418166011112754529766183554579321224940951177394088465596712620076240067370589036924024728375076210477267488679008016579588696191194060127319035195370137160936882402244399699172017835144537488486396906144217720028992863941288217185353914991583400421682751000603596655790990815525126154394344641336397793791497068253936771017031980867706707490224041075826337383538651825493679503771934836094655802776331664261631740148281763487765852746577808019633679", + if (should_test("sub", argc, argv)) { + log = FOPEN("logs/sub.log", "w"); + for (cnt = 8; cnt <= 128; cnt += 8) { + SLEEP; + mp_rand(&a, cnt); + mp_rand(&b, cnt); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_sub(&a, &b, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100000u); - /* generic unrestricted moduli */ - "17933601194860113372237070562165128350027320072176844226673287945873370751245439587792371960615073855669274087805055507977323024886880985062002853331424203", - "2893527720709661239493896562339544088620375736490408468011883030469939904368086092336458298221245707898933583190713188177399401852627749210994595974791782790253946539043962213027074922559572312141181787434278708783207966459019479487", - "347743159439876626079252796797422223177535447388206607607181663903045907591201940478223621722118173270898487582987137708656414344685816179420855160986340457973820182883508387588163122354089264395604796675278966117567294812714812796820596564876450716066283126720010859041484786529056457896367683122960411136319", - "47266428956356393164697365098120418976400602706072312735924071745438532218237979333351774907308168340693326687317443721193266215155735814510792148768576498491199122744351399489453533553203833318691678263241941706256996197460424029012419012634671862283532342656309677173602509498417976091509154360039893165037637034737020327399910409885798185771003505320583967737293415979917317338985837385734747478364242020380416892056650841470869294527543597349250299539682430605173321029026555546832473048600327036845781970289288898317888427517364945316709081173840186150794397479045034008257793436817683392375274635794835245695887", - "436463808505957768574894870394349739623346440601945961161254440072143298152040105676491048248110146278752857839930515766167441407021501229924721335644557342265864606569000117714935185566842453630868849121480179691838399545644365571106757731317371758557990781880691336695584799313313687287468894148823761785582982549586183756806449017542622267874275103877481475534991201849912222670102069951687572917937634467778042874315463238062009202992087620963771759666448266532858079402669920025224220613419441069718482837399612644978839925207109870840278194042158748845445131729137117098529028886770063736487420613144045836803985635654192482395882603511950547826439092832800532152534003936926017612446606135655146445620623395788978726744728503058670046885876251527122350275750995227", - "11424167473351836398078306042624362277956429440521137061889702611766348760692206243140413411077394583180726863277012016602279290144126785129569474909173584789822341986742719230331946072730319555984484911716797058875905400999504305877245849119687509023232790273637466821052576859232452982061831009770786031785669030271542286603956118755585683996118896215213488875253101894663403069677745948305893849505434201763745232895780711972432011344857521691017896316861403206449421332243658855453435784006517202894181640562433575390821384210960117518650374602256601091379644034244332285065935413233557998331562749140202965844219336298970011513882564935538704289446968322281451907487362046511461221329799897350993370560697505809686438782036235372137015731304779072430260986460269894522159103008260495503005267165927542949439526272736586626709581721032189532726389643625590680105784844246152702670169304203783072275089194754889511973916207", - "1214855636816562637502584060163403830270705000634713483015101384881871978446801224798536155406895823305035467591632531067547890948695117172076954220727075688048751022421198712032848890056357845974246560748347918630050853933697792254955890439720297560693579400297062396904306270145886830719309296352765295712183040773146419022875165382778007040109957609739589875590885701126197906063620133954893216612678838507540777138437797705602453719559017633986486649523611975865005712371194067612263330335590526176087004421363598470302731349138773205901447704682181517904064735636518462452242791676541725292378925568296858010151852326316777511935037531017413910506921922450666933202278489024521263798482237150056835746454842662048692127173834433089016107854491097456725016327709663199738238442164843147132789153725513257167915555162094970853584447993125488607696008169807374736711297007473812256272245489405898470297178738029484459690836250560495461579533254473316340608217876781986188705928270735695752830825527963838355419762516246028680280988020401914551825487349990306976304093109384451438813251211051597392127491464898797406789175453067960072008590614886532333015881171367104445044718144312416815712216611576221546455968770801413440778423979", - NULL + printf("Subtracting\t\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF(log, "%6d %9" PRIu64 "\n", cnt * MP_DIGIT_BIT, tt); + FFLUSH(log); + } + FCLOSE(log); + } + + if (should_test("mulsqr", argc, argv)) { + /* do mult/square twice, first without karatsuba and second with */ + old_kara_m = KARATSUBA_MUL_CUTOFF; + old_kara_s = KARATSUBA_SQR_CUTOFF; + /* currently toom-cook cut-off is too high to kick in, so we just use the karatsuba values */ + old_toom_m = old_kara_m; + old_toom_s = old_kara_s; + for (ix = 0; ix < 3; ix++) { + printf("With%s Karatsuba, With%s Toom\n", (ix == 1) ? "" : "out", (ix == 2) ? "" : "out"); + + KARATSUBA_MUL_CUTOFF = (ix == 1) ? old_kara_m : 9999; + KARATSUBA_SQR_CUTOFF = (ix == 1) ? old_kara_s : 9999; + TOOM_MUL_CUTOFF = (ix == 2) ? old_toom_m : 9999; + TOOM_SQR_CUTOFF = (ix == 2) ? old_toom_s : 9999; + + log = FOPEN((ix == 0) ? "logs/mult.log" : (ix == 1) ? "logs/mult_kara.log" : "logs/mult_toom.log", "w"); + for (cnt = 4; cnt <= (10240 / MP_DIGIT_BIT); cnt += 2) { + SLEEP; + mp_rand(&a, cnt); + mp_rand(&b, cnt); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_mul(&a, &b, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100u); + printf("Multiplying\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF(log, "%6d %9" PRIu64 "\n", mp_count_bits(&a), tt); + FFLUSH(log); + } + FCLOSE(log); + + log = FOPEN((ix == 0) ? "logs/sqr.log" : (ix == 1) ? "logs/sqr_kara.log" : "logs/sqr_toom.log", "w"); + for (cnt = 4; cnt <= (10240 / MP_DIGIT_BIT); cnt += 2) { + SLEEP; + mp_rand(&a, cnt); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_sqr(&a, &b)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100u); + printf("Squaring\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF(log, "%6d %9" PRIu64 "\n", mp_count_bits(&a), tt); + FFLUSH(log); + } + FCLOSE(log); + + } + } + + if (should_test("expt", argc, argv)) { + const 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); + 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] != NULL; 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, 1uL, &c); + mp_mod(&b, &c, &b); + mp_set(&c, 3uL); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_exptmod(&c, &b, &a, &d)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 10u); + mp_sub_d(&a, 1uL, &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, 1uL) != MP_EQ) { + printf("Different (%d)!!!\n", mp_count_bits(&a)); + draw(&d); + exit(0); + } + printf("Exponentiating\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF((n < 3) ? logd : (n < 9) ? logc : (n < 16) ? logb : log, + "%6d %9" PRIu64 "\n", mp_count_bits(&a), tt); } + FCLOSE(log); + FCLOSE(logb); + FCLOSE(logc); + FCLOSE(logd); } - 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); + if (should_test("invmod", argc, argv)) { + log = FOPEN("logs/invmod.log", "w"); + for (cnt = 4; cnt <= 32; 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); + do { + mp_add_d(&b, 1uL, &b); + mp_gcd(&a, &b, &c); + } while (mp_cmp_d(&c, 1uL) != 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; + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_invmod(&b, &a, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 1000u); + mp_mulmod(&b, &c, &a, &d); + if (mp_cmp_d(&d, 1uL) != MP_EQ) { + printf("Failed to invert\n"); + return 0; + } + printf("Inverting mod\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles\n", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF(log, "%6d %9" PRIu64 "\n", cnt * MP_DIGIT_BIT, tt); } - 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); } - fclose(log); return 0; } - -/* $Source: /cvs/libtom/libtommath/demo/timing.c,v $ */ -/* $Revision: 1.2 $ */ -/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/dep.pl b/lib/hcrypto/libtommath/dep.pl deleted file mode 100644 index c39e27ea0..000000000 --- a/lib/hcrypto/libtommath/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/lib/hcrypto/libtommath/doc/bn.pdf b/lib/hcrypto/libtommath/doc/bn.pdf new file mode 100644 index 0000000000000000000000000000000000000000..fbf05ead115a622aa1605efb2361b1bd352128d3 GIT binary patch literal 430812 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�m^D8nvu>KXmvk>{oOAf4QkU*+iT4Q&OXoMI9V+^CXbVpUUqEPV z*R74)HkT~EJ-g@kB%YHB)+|qb&VDhS_E30Bl1XIy(FPW!6&9O~U#~R2TXDF$+ij!M z?MXY5YOkJs7w0~|d1j))my*9T>ff!=H}*|VUzyhQ|0~P1BP_06OE(Cd4S629YUA6r z;)zya3j!uaMC7mka4h@E7M}wb3%0mwX1+XoAmjF|`)hCe^JPS&NE%)jiM+&G+w}6u z*PAPi!vrM?&iL%O^!Vx0c$Ka##TTA%7N^|MYp`3DH2HLz@N=`Ivk|x293qykPto&h z=U>dK5cW^xcZ}^^zWE!=TwcC1v~KEEoxN1&R_xJj3;S~qf7YF#GO$|-_^^BRkTK211ZY9;+iH%D{^^&{qMx1nZ;u=25Y*UTy^2sxVIXGVnoa!n`+up6y;_xanE0sZ(N$?rnV;bn*4(^{j(wt$$dVXEwzzzS=WbSe`G$d z+`3szG4Q>|n|rge?#9Vqib`R2&-J$M{37S-U;JD%XX;Zn&wU$0w>|Mp-d9~ZJJdWc zSbDNDUwfL*Q<1XvjXZ&WOx$yXpB+0OxHFIJr-4Of_5de!qzNcG2+7;^Z6d$2au% zCCbYlwzF!hE#dk7LINT2dYkOd#S=m|Y%}gYD7$*)x8lpcbNv=heEIiGg-h9ehI1ae z;XGANpP7VzZ@tp$$T|6Do5fD2b+?zrd=lfBwqsiI0>82~7AcXJJ!Uengt%_}n_MsU z=s-};gsFK;wqbcyI6c0PVfGGg|{(x(4=SI#~9=t8%F?cOh6 zpK{;lzc1cr*0K0#i~Q?Uvzh0nIyo7>)>*K|RB7fs&bRh#|6R9LEK*Onvupv&vglIAv!fp;R&gep)J^rh$H1n|ybVhvnISKP zq)|dJ!!{yhZfFKc34{~E)Nt>~x6OF=yq@cwrkCir^Gh?3f9?l>xEo@#1%PFF(s|bQ$*JN zV$%stjR;?S?`&@MqNj&5*0dJqZJb^G{7mQc!yc2@y*gW%r=9)FHt<%~o$Oh&{u!3Ca+!CR9@j~yg*g(FKfJIp?b&u~+pKMQ@9tf^ zXS#N8dSTtO$R{({l%mDU)URJU*PI!>C@1~0nThO=OQ$4@lpYDLVXrUQQe`0U#XFAe z^CXsc?*GgTvG;)%N#w^a4q3G}!k^r=)gMdehA=i9Aa$>LcOCnlF!WrPT8ep`_F zX-4dZ5AT+=mMiF$J-%=;XVvjjdYo-F$3DHOd)nl3P)cpz!ef(_-k2Pn-n2Dti`#1B zOShDSf(6#xRz7E-u4c_-(AigZo~1CtcgAuF&6GKB?&ye5n7|m$zvZp!>~}Y^)^q08 z3U%I^WvhPM_|a>Io{LKl{5cf#aPh@e)#lRk4{!9D7#{dy#qyo4I`N$a{!=!G6x|A4 zv#dG&;JVkH&$iy(rCigLZ#8j8rPBvSsh~h1DY@2Za(XJ~4b9^goj$_dw()P3Oq$4~ zl!teu_Z1t7X|dj#@kD~wPvx0o~vSD67-h+RHfkOBDcEkeL-8bb;oS) zikLl151G`b-n5PXcJK>tDs%UZux_RJ?l+Sj>1|+mFunec(1M>Fm+pnkRXaTA!ey6~ zvh`f|_osiEKX>QaSLNkf?uNE_UVg3l>!9*9jS5}w{~exnNAAsv`p$6ef7PnEMKd{V z9fg`6Pm<;QUZ@g0%joT!i%zeCf)eADv)HE3=l#5E%hA1`cN`K@3bAfy>VG*uhGF*S zZLQ_!&dy%Ax!wnupIG{Loe&c<`gUxZ>US<+~p3W1gnj=$f+b)%Ih%`(1ZBX|LEFxjgd6 z^mUcp-g9REev~Ekx%#1 z@7+D6(^$gYE9H9P1EIA?3oFkR7Vh67p!`E{^`ww>5qoy-Q|ptpiK)FjZ{EdCNe|nW zGU=F1K2h7(DY{~x#g9e7QTr|&{v^b+>}EuGCb#F=T{&QhXpZvRnC;$CFm&)tsGk<1D+~%6CmbQCY;tX9+hA)lZ zPS1aMe)j79>sfprJLvpxQPNZv>|XG0on2jDGn?7Ldm5VE4-RfDJ21(8)dYk5=H09B zzvK@VapaOX6}zGJgyIJUlZg|(POBRTRWi)3d{d_xsuILFQ&6-i`u%;j*Pr4)riTCXF;jS;OBrONH%h14k@I)-L-}O5)mj_5QRHQDc+4Q~n zwSlO}pZ)2^LFOxW_=iT^DmWz3B+V&uadN`XkD9Ak4%nOw`k-(}s@vFozWY!4We;>F zVyS4&&5*`1;T5g1IkA=C)(G$7+hzj$euo!aa$Yf0KyWRbd%1$%CCPveeK_@(4{ngbL527 zo%Mw~{}ief{eShky!+|VtEyd=+;=Y?f6lgek3))q;GAu{y*Cmm)<<%^349ig4W!;e~*53b+FcP?a$e69oxTpl3jFVchlAO3CFi89jlJL zzGc_M9Tn-88Ef4oX;ZNb<%~sA;AZ$4*m6-_+Z!Fi5vLx z!&Cl!-#W=nF!-jKTXg6Uvv+5$_V2TrweweH#w`#p+Ap)q&veI)>jlpx_T1OJ5N4h&b@E=Lx($o}oQ*C0 zH*S9U`|fGYzH5KeA`A;I?zy(Q?pMy-p#Fwg?m9k4H4d*_oWJH*!tV*HGcES9Myv=q zc890*uY<$dTgR+)zxkei<0rRSsV{MUf>Ozc{R@7t{I#<&*y6kRK{#}uecjQZa$Mfu*GRanxgv7zS^fKYT%qAVJ6Y?{f)-|x1S$eJh?%!(S_rJsG_!#Vb+JIHJ9_Q?)g*u zLW(y$@7XR!k8|NtD}-z&b+D{m?ziIA0w$)*YYJw#&F_{m3h)-p&G0B=eYA}+deS`; z#kDUR8e|w8oC0>TrZ816+jnK_*5z}zB{)5*u{rg~mBB|&Rc5!vjKJ1=Q3YwA{|2vE zuBV*2GcSrc!bJVf^nz)O=jIeQ%@5nemDje+Wo@%i^UIYJ4|N<(I_0_IHD^SNjt<|G zMJpVxRo%4_ov}=ZzkA~L`!^E!4tmU0Iy6g))A)_X+HJA?%eEG*fALC5Oy^8Lb9#Jy zQc<#tXZZ@vc?Bz^f9+zDnry4;usm}1^m^9zh0F@eof(t#Ig?e>QogA0W%Y83tgIID zYu2}D$$MwE#oEOB;(7lck1TZ~ixnE5F?g?d6>{yz`!6?szuU|uV?A}vq-S~^24O7= zmZ&Jzryt&H+7@K(mw3o^n(nRo7oxqtcyk5y_!>VRaNOeL+PLHHw%V%)Whcl9@3fn_ z$4PBdMU&<+u0IkzXZ6>*W(b#5t~sG__Taol34zn91idSZu6&WbXO~tO_dx8(&jKP*O18YS~JI$=almEgom$JcB#zZS>TtE>K8TpxsHE~?6NtI2jUVd zm4u4*onkH(tO{`GH$AcLeuC5M4m-=m1W)!6Hcw%q#gLQci(2-`-^RLLzFZs0waM_n_Te6QG^U`jE@A@YL3Yujm3#n~nWS4AvqU(El>y_TzgoFn| ziFws!XNsp?^Nr-c;qaK@YC*01ZJWiG(!6)FstSV2wOrrqD!Y4ft>fln8~?9*7kZsR z?Sw({>+ANcLas7S58r;Rwt4XXK*#Cjy{w(S<_FL2tGMq_v3c!I?f*h`9EOG#(*%T_ zd5`_J*nQ~4t8O0QjDiHmW6OCKDnAG|Aur9Yrp5Mmz zvisTX9>>>KDms-}Ya&m5dDY_mAnbi$^z*6B@1|JIL`;9k~$hPl-R-<%i!Tf_72uGPL-57~m{^Y1dO zT|N7Hbm^vy7XQ_)6047XSyd6F`{;?w&VsDD@%s*kbGBIQSyE`d$7S6CwTTQjJg#dW z{PdOiLGJJQQ|AZXeEdmx=kcrR+5Dz;+x-5XzVd12nMYHsr~Is{{PtRM+unu8m)F-< zgcxLq>?x}L_E~>n_(7#5kz%4d%kv|*ADFb!;y8Q2+t~Sk9sa9)yyLxK=?RU*)C;Z4 z4`@Wp5pnlrJ->(N#{-tzp&wcfi$>+F78f;jX0BR!V*Wc@ZkZdK z9JzBc#Huta<~F&myss+e!}az7i|4O9iicyZ8b~d-Y?}p<(Qhpgbh;VkNHGJ#H`{)=d;7#%)~ud(VETjqd_R1bslMWwxNCN!o|$1;!DRL% zW9!v(w6?D4P9`YW;W!9#n7ndve=u+;DtrdVruq8C2Ajfe!*@O9tUKX{@VqSoTk zv^@QjfOY5VKH244jVe8inQ)HG@J%YN~{jvRe-<9Bq!x~&^x zUT3^d*k)cU{wwU%r4#*YZr=HHr$aR`%hmIUjs3Q?onLQ$lSmgK#G5C*H5R>LGJ<-CbSPjr%KXG_ItE`^(sGeEmrB?0U6%x|=%XZ--Ad*mTrM z=zq8LuE^MFrLMQXivLKxTXw`U@G6VntNi8c&+{`j?aj81+_vF*@(SY@uPfxd4^Nn4 zb8PLr^!qCoDZJVg?&|lXbJv`O_OCvLlz2btyr!ePl)Y@XNUzClm(-4J!gEh`u&vf! z6vFz)QA(<`)9e04i|NG|#bsaZ_Kr0YuoXM9(e~}_G%mR#fiANczq3vE&}DEt((4w~ z=&8u?E~qQU?8u)-RgQ{h6;~}{jcQr7Y0-JrC%!`L0^y$7J!h@2u*{XZ*x+fiWQXI2 z*ZWQ`+2&n*@}b8>byZ%Y3xa=FnDhM%oc5qDtRp?`b&zP>!0<8Kq!q%iOP(9qzVV{pZm_g9#ZpB^DnL@BYvpNX z`J(8Am@|1BQrr8S(-J3Md!Vh+X`gZ}(5#x#yP3i4#~EIw;Bu=}M?<+AzVU*JFE(er za#i+{X^D!po!%YlzT}&_&}(Ohzn3gcu88`k)jq#6L2pjm^~nZXTrVcSd*OU$r}X2% zSqEmk*c7*lkLQK7(e=pN21dIst8O%!X?SebL+*&@eGfS2JllQ7pXpY7m$re*7w6kE zFN<3ipO7~DAv`lS{$zWAdwON2#WBN@{U;+$0%LrAE-~$2>z(;y)s!AToaoAu!Lj9CJ#9rgzT+La2{y$yfy^2WN^ePL%`w=Fx69i?@t$u7b;-_LK} z%wp|d_cDYZ^vs?nasAYqQxqRWNFQ=VYa;S0RIjb3WA4s41ru$UygYO)h-<(G+LtdO zpC|NEUmT{z|1k5^Fy1St}Q^;%Lx)8v_}} zl65hP|CslLM4Xp3Twi+AM0ZKjYW+W@@tun=U$8G|JHN8%!K;?B`e|(Q@62HJOp*GtOHuM^ z-YhAhKMNBWwodrG@lN}rKMg+*Y8bBA%xhqH!_DTVN$F)iJLQ5q^GaV$*6HPeufb-Q7eBtKFVDYB`p3=Xs_&m(IMI4DWc`M~ zJo&FOa^~;j=kKfaJA7R4dcW4U#g9^^uKwvZV|VHI8~*=FdHL$?t?l<)*jWE9sQFaZ zt|oqX>b^ac#YT6}EeB zee7%2sZyHR&UWsl@`tTq7bMoRcD>m!M&h^{^RBKyC{-d)IEW?fJ`Q*_ZqeFyh5um77? zZc=l;cS&ven&O{b>n0p|apcj}hl;%c+2@bOb6;&;7aDfOgt_P2q8P`ov4=Uui!YWv zwv>5X68Zj+;^HRF8j*ebC#L)TP%P9vxoQ`yh(~cbn`Vp{{o*clw>;a{y*_jy+w>+tK}A!U3xFq zZeJxW_S{W0pSkld!|HQeE2m2HZw=zBeX?uWeYJkZr?=1kJ@`jf>7dc;-KJLmb7q)D z8oFeqmxy(|J?8v+-N(w^-`x-1>RfCe9p7ngboe%B&Ihl5+(+NPx{sxDx5PG1ZeeCY zZ1;U>L~j0VGl75e;uTr`DlnTWcU`%CZ-a`j6@TU&Rj#&0x@<=m4r%ymOM)|rk##I_x{o9-xp^XrUe^Gu{&n?=RN*CQTo>9^8V=` zQ>wI&&awFQ;@{3>sg{_r`e7mf6I@t49S(Elxqm?ajr#3Iw zTDfh<$2q3nG4s~BD_js;Y`C>saI3z`M}{NTdxT=9xG-{G?R9dCanp6HdG+`w&(2+4 zZAXe7PV)tC7OA-L`?kBy|Ji%Cta!CXC+m*Zb1A3g%37Z~oo$;RX#LdU>o4A^!s{Qj zgt_P#kHP0!E`=bWO1V!=O1_cL+La_H^lVqsZgkUb@o@F3GP`v%>%D`B;WEL8LN=N& z&St#XnJ~pSN@?rAT|bmPgXid6`6}{rQIcQ$gPkrL8GrwjF*ujyo2tD~bLW4ZdaoFU z8_lwB)}3!lT&}0;cY*0czQxWvZy&1opX}P@`6`{t}T`Zp&yJiXG=`_ty-Yb>NYOuY8o zUCEWM8Pz789r*KO2VYnWar8&l{&7 z^{%~PHSt<{WA^$@M}w-8n}d5rik99?Z#N2L%zN=5O4qdMf5$6_uTlBuK0doL_2u&X znyD`v_V1{uXlLx*mVV6dl=0J&*s0xGk!zO(9E&b32!44`Aa!eO-mI;HCK7&nI~GaH zwoK;w`tir?V|5y<9oAj{FYBdJ{qN(Zn5pJ$Lh~Q}c~jAM>h#<*%-JI1F^4*>RUUuW z%9eV0W76x)?#I73d3o>srkMHfoLIc;wFiINS#$pF(J)gvc|t3@!^7Nu?@?PR*L{{O zI^uz=veS0n3wxk(*6-@+zC6CGS4ve&Ue#zkKfC#qPS)N#BAP#{BVRPD9qr+{s}^=M zxM)V?pVP|QfFXVSAHw_i?3 zD=3;OayD#!+!QJ9k7pb1%l&-#N^Vxq?H_-Vii|t$A1%7MXWo(R;r#qnMtj{K$+YkO z{JWy)XGQV4>F?#goR#xAyVA>R%}$ta`_xtZ>y_;a_#Woyl7-uGE&)DoHRpzEI6mcA;`r znck$N19lfwPWuIVH~%@gdY9sf6MOag@*EnkvK~@)T*CZ6%*4o>{}4lLfyCDv3vMJ! zoD8g-t|GKIz&zCKcJ%GltamPNb=a6*xz5$`a5%qeNt=IzTv&T=rpulUZ)K(kR@`3V zEu_tnf4d}fXH4gu?ctky#hWjlY_L0{Y-6#?y;I_L>E%o5+g=!Z#!Xj~DA5$IPu==$ z#hS0urVd$ardP4o@b2FG_|_u^lh&}c&rko~&b^OWe2wZP!OiKP{Ja;ot>2NtRJH#q zQ^n5jRle`!Wp}ESL?1Rkz2u;?m9Bnwj7Yn!>pID-J14tB6vPj4dhhx;h2O@n>45Bs zc~K%F{O5MoZuE}L72b5Za?SkD^Q^+c-Z#FLI(4c1ctke;^W@87Dz1APR<|Cwt<7P{ zwU9;b=!7{Mf2`$P?}!QH2dKq&mwY~V*Zc0wWY8*KXmv<=@-PD0y`8SL2QpHSbeCYozC7 zTio?1f4F(snyj;{wq%vB%Gr1Ie_+-DHkAp!_pY3pf3y3P@_WD5Rt*1@jymAKc|vt$DE0Wyk&h0gD(GeskUy^*m}}>9x8A6EBO&h6oyMu5q5at87C< zz=;pGHa+)^d0nm_UH@pZy?@HoGM!s>Hx>n`Yb?K(Q~K#;ckBUpH_U^IC=r*o+ zyi%~1gG2O8kxtrAHPfo}DAg~P3fBaj&NOa%;##&z;+(1M;Xllwti~6yRnA!Ui5i)i z5#94%8|htq+f8WS>+lUFoDo}F4EXmHO@4agweHQ6x4d$fK9X@r@K9o7)MM~^`0n42 zx8e>H7WsW@{hU?u-RFBry)94L>qvv@`mfI(zIqnBB7Nn2H>+8;Ytpnj{-}7R2MYc4 zI=;C*>D%t*HLuT$7tX23ulrl@zigkuv5Ip0`l{~_|E`~(|Ge{~oZX*4ng5O-w$Hn# zDx7vqr7p)osE~8w11*7z&vjo2`q;&u*v>6`cupeU?R%wvdHVudv@vU+(HH;>v?B3 zuPS2w{&C9o9eWS2Tl@S}biDD~9h?giW9458?ECmK_R~7!^-Ob1Ua7B?c`nAf#y{re zSG{i=4%$YF`mMS1=J(xw&u{k3-sX6Be#M0~JC^#s&3x~@A@I%4ZNlpnv@d>NYvIM| z9{l`s>!+v}mTyvGBiA2{3zVv`Pqi$%ZBTeGJ z8>{1+4PJa>uAg(#Dzkgho72nK&RMom65nD~T_NAwB8AEwS~2wJK4f>&h$n|JmQ|p3%gr ze)8kJ2Mx8{)$i5|ef7-XE;v(hO*-z>4$W`3WxroIzd^Qg+q$Cu&jz11eRN6KrnZ`K z{z`SezH5fQnp=)LEASTlers+fwen{E1L^te`6?tWW^bH0?R19X<`ss=8(3Jw-=5vK z#z5%E!t(1^9<-P7J`|IE{*(0xckbVab@ys_)*Q&Wl4GA{Yqif)al@5Ml9h>b4odC{ zyr37UPn>Z(yp_9&?=Iu-Ex|M2n@Pr&Ofvgo&>@;vc+&dl^@C1+@|%If6~nzKX~IpIDeZ6we#(Lcj0TEwu-OzW}W4h^9pv~3g2V$ zELCR0W&wLe-wP7yN=ITl^1W|W?0jvtrQ2`sZmriByyvxtZM2h}bxlgo_E&Q6@iylY zi?zKc8aZRuw%N_ve>3mmTEp{yzZ86ZugyA*Gc9Y`+HcMR%qwqfFSI$mJ$(Ov!82SD zERTPx`KI~1?3$Zt?;G?YbhCc=|CAr*d;M;;)n)J$UfQ@|f1Z8IJ(=&%@=vff->5E@ zFxzxW;aGCS_J@K0-x+Wo@GZS_!dCHE|9SHy-j3_ftaFYqRq;%yDDL~%mxL%GMSKl zXPrI5vri>#>{V-0czZy1UBw1H`QsWEOhIv{iuMRCUc!CKdf&&ljm#`>L?nb~y%fA* za$~h+zz4TCI|P^HOUy43Pij?}vfuo;bc@AL~NnCLpliK~x32;4Dv#mu<&-uK{t7;W;E|ImiACwEWGis85Ff5JRhASdy>!N1LoOf3_3 zdPK_Z-<9y#@c506soN%61JvOiC~c&{j|rN8v* zN}tlR(a#o~GS~6>d5x)W3iH7$9_d%E)O)!c;cT3~^{Z|isBEY+1f5YjND@H zc6|4@4TqJkN4>u5^>b2a&@?ZzFGwy?KBqE%yI+SLWY)}LN8s;xaY zP0?(-@B*J*d=58V_Hmy5XzFHr{8YZ|9ofYk;c;xIxGH$wE3BB!*Ef^xd&9)oHvJ^t zsZ7@xjI$fwE%b|f$p65%PD1_2$&8EM0&LplJxw#pyw6Q)yl#1XZcq5CHL<6CLW2%m z5}LVS@8q|FQt8f$+m0;_4Gx_wqxiB`^Qk6k?@XWK5?S7|Hz&vM1&qao7 zo$mHNnX-#t-|?3`Tg%ZQs*)>5T=(W42 z#bvE;%3r0#%`^)-bPG3m#r$}zFW#W5Qu#I3CF;R~q++d4-`?KlHp+c)`$Qf8%xgc) zY$jKlE4<`*bTG2BI4My__wm9HJ(H6og^!mcPy4#mhyBi_8J|K#W`?I)HH3S*%z5*p zZ_jRppr!k+zN+qMDM?n0o6~Wo>(Kd?1xyN`*YobQka0McUc|#@aqB{{mkfVpTj$5P z6z?jPqgy}Pv`aY_&23sy)uyId>vmDVX3@e=VslKx?(eaS7mRv)_gUp-vDCf$WERYOam4S24|B#5 z4wC1Wi;U35nEgyY>e z?;cR)@HGlnoO1S?DXT@((}3egG&g*VEOT$=&|Unma(_G5j{~c=_N_AL`gV6isGjjr zV}|1gczGum%b#Ce`*6vkV=NKhoCE!|LnceFe`6ian`)-|->7`XYz_u3&C-|FKbyGA zc-bS~?qI*Zd}Z6E>0A{*pZuukkr(sRi;Uf2rT^6T#Tj#>s_yNFxkIl{_4dk{uz+L9 zL#f*WR-#vvUHpz7O1ZeFfn&ytr%IlTCT&j`1n##7{F7>K4lNN7R8Kwf;QRJ?xrpY6 z`vt1^WLiiZG|sK8$qWby+Pt-y#iZNcpLcaHA;!iQ#5Y@GqRVfa3DtdHf8nP3t2t5!|9*OL#P3zE(DH3}?%L+cOL+H{ zhKYwynw?hv_nd$V^C|(ISrr>qgy!&1e=mK8VZqB6r#t%Y&D}F^&Yr4l_dbiWUo(pA zlV%C6J?jzeD`CF)WXYH8g~#{%|NHrB?W06T^^OHhYeHP_{i*ntSyX6iC+Z~9)8pT} z@#xdzC%?|P{pi)7Z)cx;dZj$ea-r#$)!T#mB$WLcV+|^9Mc6!L3uxJXx=l!+oqi(QtE$c|V6>ZV1zC@!eV&eKA?DIZNe-{1ciR;c! z`%fR8{xxl1b;PgJ`wbOOAI;kqId%8X`Bx|ZZ)o#8+`T>ucd zzPa}AnzITDkFtZsr9uwAJ`G-#Qb!^H<(^k+01k4t8CgA^PX{ljf%WQ<7kZzTFF&hXmcH?x+l8fKE<2}hvA$Q%W5@n=|HLDfS9goMtoh%o zdZ*|F-UqcbC59iZ#6b=fV5j z=`ZGsbw|FPwAb0?{-5K)PrdkGFDk#QJm=b^fQ9iXi{Bo;XC_p;f>&_QJcsx5!^&S2 zo^E|V@o933!b0PgiC3Gux)uKjO4YO!+_my~UjHbiU3l_(m*AC0cJREo{Qj|0hwtqh zpTk3|cO`lX3urR(iOlhnp4#CNVpO*2#+m8vtf~(J71Un%l;X^f z)_z-m?3}6ldP36IqvHGOnQoaMw!VM$v+1^--4xNAk73BMh?bJyVm?onZ^b`?J_vg^$L{WYyKJfg6+_*wql+bY_M`eU|EktJn)a1zk-Wyf+0%LJzrFq;s$@~o;dDH- z-)H&1>qW7lIls2dc+6TLm0h3wEO~cmz?m&aQ#RICeerE7bJqTQRBO&5{alMsQQi0H zp|(2|pt0!I(_XUbOl)Xvn} z)pR;HgYCZf({0;6MC5J%7bSXV;o0_G7w%R)W!`S)*1S7j{#kiMBYS)r=hvIt&ey)a z65sx{yRYBBU9eOt|Bu=J@2vOw*XpRrD{Y?RtZG#tI4wf`a@?uN>!GC@ zZhSM_!nSQ%5-aPz*M9fRAG2%{mPm)};o5O{mGJufl}xjj`!K9Zp0F=O{58iysr9pb znT{0OMo+QM__NtC|8cp><|77^v(`?SBq7JSD@t0xKr`e0gbR}!ldoS$;(WShP5ZB^ zZLCuA1y7wK8Ui9OZ0tPLq4(=;R+Yi4un@t-_)A|ZzH{!dPvK~}%<^ohGGFuAHU|HXxWji+ zrE$g*trcr!#rij7$u4fL6y|O;*;vUS+xTE9w}iJy%T$56Cv;|rdAz$LXZY`L=BJ0R zY=n{=RUS*6X4Fx zvDNp?g!ULIWF78P5EC&`<6iG{LSAyhvhh^=*#}lFj1B`WG0VJJOT-u(+eL;?jA>2>)M-2}PIA zH{A63C41)f39GqF`U-N38oZ8iimu`Q_4w&-dHxp36(4w32&B#U`_X29O}TKi{UIHn zbjPb*5_egBJIfj#L|xS4lL|QOa{IQM(-tqsMKwMJ%&co4MY>2Q?UOZD<34jnIjE^F z+=|=8MY3nJUdfqw3&)*+$KoYp#Xuo)Os3ct4G zM-5G{X4=k5R__xqp1C*WK+dJ<0-tYwNwvtEy}xD0pXD>y+0SxMWes*%aMRW2=N3kv zoSQtdZtRnGuJ2@-zVLkOM)v|qu2nuWD>`OADPlX*c3Sb-<`}uY+eMZ~e2XlZmpw1) zsL=S`KBe!r&J4DqWxGyCU76ApckW-9g9ua9!8Xkm+k0DD6gpU+$tWsntcaW^`d`3U zb0N=+-WI1b>8d6&+ouL}R7-Lfv5G8+yw#PJlD2+r;7u>zC7UA+RM#cE`KY0~knvBx z$&tA$Z&|uH|IJk~anZ~yvzsi`R222}W;%z$WUf;TH#IaGZ1(ppe;{%GNkfZBOu)6q zo-B6HsmuaXyfoGcwcV{Mt^57Ytc}ZZ$z?NcJ%hs?dd)(QB%S_**@Ow7Ys+2sWqVan_hSVE zd$gRi>kg@H3b*gOH61_ZBrmhEyNR{;%%<*32YrkznbQtG6)-;elxGI-Z09r1k&Nu( zd69e(njbVKzd8g??22NUuIg18K{)8PnzKJLhXR?Qt`l z$t?a^>Vm8I_h)}aiyp>rjOcVac4m`;w%?jdu}`LGRd3c@r}6fUL8#N-sb`eE?r>zr z{k4vpvLh&NegAv8Ti=aNvD)mMksDWf|8~dvj_pFS_hy7GOiZ4{6*?$ z-6Ctoa-%lwf#=66mKniEEN_=S{c&l+eec%gA<)@5iSPnw@7a3_W|IEK2n2OBn-GF&6%(ZI)pjmn_SxZ6&*REomy-r8DDF*y_2l zXIA%5E)SR2TX#H6{C{Vv+Lo$BJ!U(%crl?xeE$x9k!upSSv`YUoJl~-SN!`~$AjO} zLR_-MG}g!M@V_LmdwVa-W<{k1hhz`t*nH5*5ld^IvC-L|$&LBu1ZE+&b+5iL7-^}g zb_iQ>tFg$W@f(&s@s#Lc&K2`WU=d!#UG?CDppVt0PckchOcT0X?d!WDo#AWrPYJJ{ z$A_O>zU}5@$F}T4@-tSO_}mz=uPhTZKR$6-b5vMCZR=#lOWEoyK3?j~Ny>8>J|9SQ zJYknHZ{v|#Nt-0eCb zM`a@&jtxsMRtD*?e$M!Of0f~AnlH^6R{Z_%{wS5m zSlM-9krA>w6R}n0AV>tNrK!Cw61U zXN)d6C(nd@m3yIJ^nKez1>@$NQ?ry$^gN%l_MFo*0b|c+JTrJ_I-f~DF^6%hVsVF5 z`PqsD1Ml~b;uJsZ?4GIcnL(*7<(=rA_wRfD%C|fB9LLfPGc>`nZqL|^=)>S@!|oQ} zHsh)P9>4Hwp83ypVJ@$JXKue|8dv7|Sod7;b@s?4r8t#KOIPgr`JP>1%43sv^E_$< zSUTh#jvP!DV1IqI{q3ViMvomuLoLrYzjZ$F$VTh4)``eaQd2%blEzzvky2eLc%2=Ek$*$dzZ3 z%(eV7VGeI*r_Qv}N_(hlalAWV#qQnNRttGO_vvo7S<`#v@(b2&!g1GLBnm8>SlXYr zczKU&=(LH;{V(AB;MtHcB*70bnW89!>B&=s|H$3w*#0?qSo z=G(0Evt?@)cXv!OH7tL^XXwarK4+=mU*p0p<>8g)c8*ulWv+JdJy}>XJymf@qr~EQ zJ>5bxddsdw>EH6-9cQMJ^)77fpO9-23bG*{`h|cm)#zR|IZ( ze#hqCd*QPSzr@H@^08f=)GEOyB*At*n2T9beVy|EgB*shw@LlASrKF&f7QKkknhOd89T9>=&>~iCB5;uBtB`NRp zg+w_EQ-#DE(TCJ8@bPWYTNH!){lj)QY>{!_U>7NrL2?BCr? zil*F}&Z2U*ta*dpWlo!w85bOuKe_JNGjTJ++*M6&U$xH3e?0T>mGV4U!^bm!GZff9 zlI*<2y;N%LOeyXCiu?9%xLB*-uzasjnN3W8W|5VhFT?*S#~*HM_E~s%b+MfFn{*wU zk{8d61v!EpZ&%%OcsM^}huzc7&3DyLKdWL|820bX;U#-Edz_7J(I}BTa694NT&r&p z)4qM)yDo9TM)pluoFDJbnicUUJjz}E{m)I)Rv9jmJ9>U&iTQI8 zu76v;G_0xqeq>KW&ULQphHMUprnC31T4Y2P@(7>wQ=Y&VcTLvUHjDk+#23t3nV+Am z^qV(p!sej%sPpLoPfx!*HGN_>Z-fK;;a=qX){SC;+M35A zpZI?H_r5giMrHYz>*v%j9@D>}|NnjI#^eGHruXwEcrZLRKH~W4(`kl8>y`6Xe16ih zapUFS`$Dy@+>VCx_iw$jz41O{Wu%d_)%?c|%v+^m%L_~yw`d=eng3$>*RKBz-cyfU ze-diC`_0^=la4z&D9EfblG!tDZFz9~`E9USl!Otg1=BL7}mJmR!gF zvb!0#)@0t(Zn9a`wd6=;|MJj~l+Xz-mY?sX-Zy&wR+MFx1 z;c?EH3el&Yawdl#eV%TS;m9%3-7}PpeYq8jj^?5*Pd2=7-hK4GNycWQ69@J;vE{Zg z>q$JdS+(lA+$JT4L_y=CiK#qo*H@&}$sAju-62)9WtrKZURN8hg87FSCLLi|ck!&e zLvYur>4n^-k2mTH< zT-Bj?vu0Nozu&ca7KLvjqfai=I@zcc9kl-EgxOP$PmbU3z&vGzB%gNF$0c=w4vXz; z9Ja?~XYaiB_H6m;+4=G6VXu}3I#Y?5mz@jW+K${@toB zqwkR(sJlm`PsJ*{cKK|!k9Dn;jS}n2OS(FteuwFO743g>MUy4@N9>|-?o%}p|3^fWd{G9 zQ)+FczF2)za=weNkkv%_f3>C`UADwL{H1uIR)3#SR7*ijfRXo>juV28S0;yqdKS0M z)j4s0w)5O_t`psloXuk|CpJ|b2=IJkSZ3LFoF`50aB{}8kcyZ!#VR(>Htgo_UwF6w z(BnH>OTz>$Ijt}IxbLis(6LQWJ^wD`osYxkuH5+ntheV+`)I!4WwitQJ(~+HoBbzG zsrf!}rDP1_g&MhH@z?SPFYr_gEM&Od{Mq)8Ss>$?g`1Dx33wj7Ph{I8l^fG|+dln0 z^kk1_MeM_?ibhV~Z&is*=}?%#9>*}#qhO(n-K$NTY92heQl$0ye8TaGx7x~l0&gF+ za!)X8ziWG@t?d52y{bNMjnp#9H5igK*)-nC{q)6Y>+b*99h_`0lrTxwNNH=?W zt>}wGB4+c?gv{Bs@A2^%y}f6@gz*(KPLN*8oVb2-8B=}njFKbwFD&8w6T9xS=D)O! zyN}<$@XmeZ*7O~wOD=8ol;NH7PdH(BTCww-BPXYBjh%5MV8glK+pU^wKL2oiwAE@nBzui#4OufZOBBc5{vJ>Rg~ z{ndqc?o(DiecpWO?{ANLSAP83*t)0oQOml-FxwTIW;opuy)C!sXs^DO_}%Am8Gi-d zcrh~lFi>|n-@d`}=Kg(E`eLUQICjSH`90ml@g}}dL7V?c=SKF(Y|g&kNk^i71$-;^ z{IZOBVq!|TWV>Ejl%{shQL|%tIpVCni?ctP=daqk^Iu|nkDz;U8+Sf$`HaiPMWJ&) zhu`)4*7du8is9|3ssh7?uB?}p4}Kq9x~tyhNI}<4a|LF>qhAh7q4#!@loRz)0zA^jDzU*yQx8L{ayjmFi;QChWQ05tq#W{UE%fH={ z`0gq?N%i!$qq;{=T&r;}$bBp@N7d=unQ!iE-s=C-U8t)ZF){Ql^OLSFwRbB+^thuM z1UX-Z3wkmCu1num7PG>BW!356E#Wh?b}nmKw#axw^vdXxrJWJ4d6;t^xKCb^6kYmd zQrN>!a@#C69?Ul9J2fe+;q32oD~`YH+yDRl!c@+vx0PIijl53E+lt!k{7u^Xq@{n! zDhTba-?6YeQt;@fE9c9VE1vCbn0_I#PUJ$_q7N;CGH*8dvlW}3%`FMO$TGz`I`r|& zCbxdoD_?#$xZi(}nenUV!0FA*1(y%}Ixy@0hI4aQ*?&E|xKiS|a>hlYY)~@{O&DrAW|2I>1dbmE~w0|(;5x;-=?-}HrYnmK~DXg&k=!^w|m!Te##aKTzsl1X6xha z)e?pi4!JcZvHrMRAm2B~Cz0FjPxr&=Eo_$*qzvxPoW;$V?z~?%%Ei!)S*Fs{zc$Eu zZdl-#gI^X)@w?4i`7z4ou!-Wl#?;o7%F>IIYJ~SaE;E<;v!#}!Dn*lLNzAMddD1EY zF^!%q4vS{yy?S)9UAuC@2S zl!;vT&)uEdQP$Vix5A;mz)#oorNoAp;d1t$dOCidzp{q7MJ} zk#Z{Y-pgJjS;llkzpwOfwrJUz?5Q(dx80GycEH^v*d%mWR@#=9odMHSzuxjYyp;dd zf~I}z`q%_)H~h$(ZY%vW;`D~;ax2)EwSQV2b@<>^q2j7Z5+2hwP2O_IL5O>DqQ%BF zlN)aYo9eb4+G6=)&i?k#Os5m$Cp`_w`?shhxZi49(t#ufw|NJmr6$ecJbdNfhmWeJ zFTPFPC9q%emiOYF3wlbb zq;#dF`W`5~-jR0T^4V=Ole8p095*bho@L-_#s8M~rvk^Ei@!uy{rJz=xP6TcmL`f3 zwoas}3DN7r*GAm!ziq}-zkmOs8>i*OC+SH6~i@>MZ#3hpGMjnk$XiEW;8{Oc>D&oX|j4?7Ayo4F=7I6V^&a7in6TG1h& z?-R*$>z>J1-^pvE^qpKay;P?b?RfOl zjPJ&)9#uV7*S5a7W$xUMH$seso+pIG97+hz@c-u_@&46SE|&#Q`RfwHMC$@(z4BJL zo3e~4@St_ef{+%55^n+5V5#)irNQf^Czmz`%v!CM{qFA*Wwkw5{zg1F7gfIBtTJrc zcjo$hFE$;Pv(M%{tk`(PHzFhI|JqlayvvN{o;>w)%EV{$*BEd8s+C;0cz>SH<3;Bx zZs<<9>-NSW{Mxp2Cbx=tqTcvtH$BfQ5ewUPZSBpiZq*wOYAo8TYQS@&V)bs{;K~%6 zjTco57w+%veZaTc{I%|uV=T9%<}gZRL>Gs?s@v}<*z@_;-|bz0-r4@F3Vs^RzSc-w z=KRC(-D`Q;G4n1RK@ux4*YMzl`Jix<{?2 zwQEXFSoGfZotGW^f=QO)&_*@i)(ijadD%>S8TWp%u{gk!_*K?`!EV-)^u~jIr}n3{ zeE4zk^j-~%<8kZ~Z#3>TGX<|TpZmYid~xQSt#wS-P0!?|D|K$ZBy;G*M>c=sPe_{Ga!y(D#eDAC+8^Ontn0Vjvb9QB z^*=7{!zAk&+I`!ztXig=6fT^g!lC~E{kK=PHBB7{<<(Ez$Ya&&dve5kir0?c=O^2& z^b!0w?@gwprrl{(t4lxsz1;ox_@ghie9M!(#>F46zSarMNu12gRTd)0<`^p9 z_5Y%p@A1A9i}g+fDkpEBxA=pRzhT7`FPDrLUN*+&v-ho8-0_ELss4RU!Ny-H(K~&o zCI!4tYBGpd$+^M z-M#B?>aKq)|AXtJd+eVFmg|1Kx>!`b?KLmU+M>7Zd~P59G(L(mNPN4yob|WNyfd01 z=N50W{oHEbe?4_t^yD`Z^W5Ie4n2Hl+UsA(ws~b}#Z)s+X*t%?k=uRn|6^-kLG^7b z-~PEK;^-g2e5iZT#oX8GU%xu{o(xkKXxbxVQMQ|3ks~+U+MFvO;P$yT*~88GnMJGX zB&=g@jIKkW7SU74?*6^GYE0Zj^5~)V?`2;7TaE?Kb$=i|gRTF-uDcfw=@(?)o1v}l%HDb}++c^{cC&_E zpMtkr+sp8&-KuwqE4jD#VBLqk_A7f@jqlZP{woiXy#H+{-`7^XhYY@VwYl<`cLZ>> zK3RU^VYh1N%O6RSsgA7X!H4FmFqz-_u;+uq>aON8gS_a2e|X9aZcDelPER?$`g-yd zx6dt#oBKx~zZ1?C8)k%0lxBa~|+BKvQ<3DwPycl@E~ zUAb89+fn9Yc0I!VwvBuJk{FL2G85CCG>PMLfXAuHH{}bBK_Mq^{BMZ()CTTG$2Ul^}wb(?}MExzQTzix= zeU70h_k^U#x~kHzuU{Q~-@SB-kx0%)pGhV)Ka;lZ`uW^jXas>TyL7!s{-Dx8H`(36)jouL3#SB z$PN>mE6H2e%iiCo|2b>Lu4yw?iCG>iivH%`k?6vt#n6Arkax@1oo@?1U)!54Q+a2q zy864d@^NeQ{_S|MAXnsrL*~H}5%!HeGp7_zFc+7%b9H2#y`M#Ja-`IqsB3BhI^M<+ zR}b#)zW>fWCi85_vb8FDbNT1+`u)G1b%&943WI-Y*HR_k11EJZ8*bdc?wZ-I*w4p$ ztULAzN&eW##LkydDkNqmwZp2o%_I3W&mAkC)Q2;yZoT}qHgom=DK4g^zTJ7wx3BpI zf2{p^eBmokzc)`*5|gKe{XOw=t>^n~x8$>or_E?;TJrFbN>iV~qsh$$9b3l$`Nda7SNVqSc=>9U(2A_>IYD~y zr`_DYPl{Dt7k6xTZRC^(e!Qy2J%1JDS32yls??my!*KBWuVV`juDp?|6Ct#E<*rcc zNeMh}`nR-5lzq+l~Y~$sp!JGe=2j*&j|8_a)e~#PAr5zD!N4}hR+mmOL)FeNV zE2TN^{JX;qNu46stc4iaD(}BPCC6eU({ z!@2jm-)?kU!1hRkd;Wb#zh#*mFH;!g6_05#YfZRDS%sa@oU3H}usc zZceSwE2n!+eyrWWwDQ-giA7Q?1C|)ilvVG^ekc4bS;Y1GX4AyZQ#Pk>9piht@Rk7o z+{{B9NR zcaqGMl$wvNVxC$s%}Kt_#be2auPu|3X8OIls#zo^+Gu<4cIdyCW<|$yUo?hf>=kwF z%Y-MCrR@*xhBu_1S{XRo_t;?--tGV58T5fx+=+f?`^O`sJC(DtqvU1mDt9Dyo zzGd%bwd?Lwv%`reP95SC5=)DebS+>xcp`oKW#P*3S+;>296m%&;C*`GU#`l$V?6>| z0_O^Y8f&(%XxI}UkkrYhBp>E(Z((S0I_K}D3QzZX#k<$v^{BdD-*s!#PDWK%)`p|k zE){Q+)L=B{>)3cj$NNa~uEt9}pRag%{aNtY^#8+}?tKepZ06H^cQfI{nyD=c`TyfPZ$kSo^GULIIyS7kws+&iHv47Yn^rtHT6jY5PPXjCayDDH%p$b{ zgI;A`7S&Qq^J91CXKgfHDblmCu0J-t?K#8JiPN{dtG3PfJ<)-ae@%?I9y76(pUlMLPF1Ce^K{uuO z_}!aN--+X``(yvCV1}1(paRFAggYgF4&Tx*T5~`Bnvraroobd}fBlY)v*hZRAHT(W zZhG;uLxE=(&XY_1_bbqU`F}n6Igj_-q)d$$dFQiE-sW@j&Y1e5KS$@7`G%jFQTHwP zaOvmEoc~uXU6{18L@Lkgaf8gi8=4W-3)+wBE^GWap>9`kQ2mecC<_nEoo^rBUv=|( z>f?12W}Nk6ZVT3Wcge}4Y8BIU?UWvbqdtVKJWi!83^ z@0ggQ$a>N=WmQJBhAF$IW>+tO42BI88sZI`Z}UQL2J zFTVsuomh3FCFsPn)d74v1(yYLs!Co{=USR_=1_)Wp%iDt`OE{8f@X4j)6EiVF+44? z{)4vY`&MHsQRPWanVgp+nN-V?c&BJ@JHWiK-H-Rkqa&&b+8=a8Jm$*hy^s*QB6H%1 zbw%i03HAlIYFJ*I*iSEd@Wkn|n1!@i%NYd==fy^iAv28nbTU}ojd=>1WI`?`${*BD zj}(zLUDGN5UHy>dO;w&&kD|2?QiJAsl;*1T?3%Ty_*vD7b2GUcBw9qJlAf>G#jvVB z#C~1>gM;N0pUq-bf3(SPy3bHqa zex-IA5hrsOO;|5z*)G%*yF<)p!^Hfwb&h9ev`k(Q+$@VTInh?QPetsB-YIZ%U2k@3d#yO;j_Xmjrne-g(c_R*%$uWR9kc3?f!69H!bemx+Fit zdg;0!iB0>N3l53&-ub1Yb%x_s$JwVrCPk-bTkfphf96c!4bLXAriC&$l|7zug!UvY zmzglPb)G_Jgsnqh*PD&1Q#raNE?ri%Y;;(~F49`p746gcEG{hAR47^ZfIZ z&bd$Mh{$<1(dzht#pb}o z7e9LxXC7%5x~N zmLO&uCiN5V8uA5y6ju9KH~kk$tmT^zQi_OnVWxw?cB)_RIR83$|5# z3V$xYeDXVW9rL}j?pM`5y!^Lj`{v!VyI%q{=FS}--dzIt%kW1B}M4elpj+iVN8;c}?=zpnj9?02Q>OPeak%KNt# zt*xytyK$iDlvUNnkQ|I&H; zUF0T*f%LbQngyFA_y76yJjd*K+2vC2pxXy0g>`O^xD!b z0_AqMpFHtnlUt9;<0EH0tQoE@?x~wG|!} z8PaF!kGfAg@Zh2B;#0GdLvESJhul-VvsUQ-amnp^d6hDTr>3v)oj>VU*OKs%4LV<$ z72a-}R}_8AeA|`k(qF0n881sQiiI*HFEMD5m=b>KgoxImGzYV#vUts^mKwkrOL-gvk$KO zm~5G1lX|tk>Ey!4?%A)8ZT>Hvj?Rzf%+vv5&;OFuO&)t$j?oFK4r<~>(?Y=JNgnmS2`u~W)K9m1h zzdk&eACNnFdq=&K@A*rKan}>?`L@RkH`Tk@W+*xEI5QVBK}$+JDyuvs}wGEQ-=X5IaS7cYAZ-bXl%-;m7x;^Eyvl z4!gZG>E5E1>n*eLeXo}KzPvYUlWb3AYlVhzuF|s@<&Q!8e%ME^dA1(2yV?XZud5HpyK&pf|;;{~FgN6HcC}sGBaTfvTFj&#ixd z=G-JD)nyqA9@4x67d=Ug>55%PI)rSQ>#laftbGdHMx42{i8|GI5UZ&-2Eo#&@j z*M2IEdw$dC|C9bJ+r>=zj@evYz-?pcy;bd=_HL(V*Pl!jl2O{q*Uf7CQA;NzT7Fa5c>GfY`)^pX?hO#CLB&W7ozk_?sv**rl9cI8gmxRR%rDMnzXGmOmOd(2S!z% zhsD>k$1E|GkUSD($U4vJkn;rnl}3G&FWBYB{e9x~Dt7ggStcJ}%{sWkbE?7Fuk{Ni zUlF`K@zv`s-BKEpw%46{#vix6$-_?ZWoqT>09$dx5g;yBJ23u75kPK3g?))4g@;a(^DNOze-XX5(Vm zw8vKYfb*Rn#@tp-U61d#+o8hYjBa*a+;3e^AXs`@h5IEE?z ztZn{ft4m7fSMS=vq`(|!EpOsB>GrX`uj5QtB~7aO_By4i^j}HQ$7jm!%P#%;_%fh?|I6;0&u?zteEM|%RsWR@tGrCO)GmaaT^G+?V8*UE z{lUSd+P<>$`h!@dZXBN1o5{5ych7|Fe03Y-Z4-8iMc>~)%k7)uqpZ2%+qb<;C=t@~TqNtpA>HCBPn?Pj;X zSXx*VuYP@I>)iXbyDvU?+VcJ2Sw^J=qK#$?qP_-PEo1FmKcz|Xc(C}r zC#ol^%6mzJv#`~31xKdVoCB6V59Wp3+_fmQ`u%}!y)c89n@lFQ3CJ(2=KQsJMz!yc zL>FFfC671f6xZY@+!i&rar63-V<0mxX!DO1hC&-UB#*nx@=WyWJ;c25-6JNSZw*`a zE!%(|&!TU9`>k@q=T~mr8+R)>h?{PG~% zS;=RDoaA1iP51sUHZ0$b zCojrX=do<)yvy;itB_|x1Do>hM4_=;wer`WkE>sve0?!O^QpI)RD0qR zd+V8g>iY98J~~<=qWS-0_8)uOpS@!D{g$17`8MZMiiz02FHe8|^!U-Qd$m}k`oP?E z?#mg!D@~Bkm|}0%runv4RL9dZDkO9Bx~_{iJRZ;gV>&Y~ZcpW}FHasly74l9*Ynmk zX|IYRvDqCGcLWw*n<^7)dm$+&cY-O9dd z@twAKW6zfRQ@)(JmA&jou0yeVz&Y86N=v8Lq}o;(+5RX|XfXcXqMm$i(G6oomKl6| zUjKRU*Ztku1pX9bQTKamm!7dbnWXUK-lg3ZKZ@-`QrAR?xE(mTA!2txDVxH_`R;66 zR&RQe)j3`D?#r1wp0h99a{2y`RM&3Tn>w2wJ!7mrJGqMSol7;->z7KIYvvwv(o}0L zcvhr$_LXy2`i6tD`x-Th=6(wPkQa4v_teha(aGmBmdC|6XTSPcwR6wnshgB8O#kWPq-pPb<@#Fr%~kyp zZ*KRbytv=1U>C98D|hwOhq7yrElkkjSvW~!*{ujoDXq|-uY}eX&D<_^i*@@?jdORFHKi>!@mlm4abTexicPcy!U-3@D&B|l%!wubd1i@@tljV3jL z?;FEbL~?ZW&k1?Z^!%y3SmXVPp(0MH@?sA80ing=e-$lGeBY3;zD2+JsH<~_lgdkv z4Gpt@KiS!~Nk02DXL9lJ(+dQq{9h3KZ|$Z~ujw5r2Yu7KzDm)x-3 z)goe-?8-uB8OuqY_K<%5|8?rD5N0RlgDeKS_XnIX zZhUxK)GB1jL9e-IIyU-7P0N^j`_@f1`&)WFMKhFNy*cuF0w=2pUz4~0>eLQbvZsp-C+Hxn#(>HzA5>J@%@}VcdgY) z*%juI^XfRK{Lwz~-78quYF0feo_ThS`M2tfce~QBOP=psqQ3Zg>hZP4 z+dhP?DK6YmIrVmU>7Gn?Yu;baWUl0W_|@jtwBFU*SY1fmZH`Cg+w1xY@0>3kHuLe? zz~L3_|FnHcO!(q+eMMQy6^mACR1`i{S1(x6w%UT>39l_Hhs=SJk5_+mAMoG%<8@@@ z(FyKB5n)kzSwD8`|L}FY!2L?>T>BliwJt}T7XL1f4NdrOdF%B-&(K84!@F|@1gg@a zHafoiQ^ERzKh*Dl;{WHr7;g$xZMo60cZJ8qm#M*VOb*PO*M5##ENAT?WwFov_guSq zbM{u&etLUT|J~U-TjMPgpU&!7?0%#^cKKoPQr+7Z10uGy-(R*rCx7Z zzb84xCndT4n5$l&{L=TO_QJcbi(0$O`5rxgD_ObH0bXota@Uk-=mzx^a8}B{)?{dho{dWD0P36%VFL_hHc<@=X|B4R3 zZ@9|$ZqLovr3{zuKDjviRj2Y6bJ=M^MuuX!mj2&bn=URc*c`v(-=SrluWhFMmh?#6 zwct(et{d|eo-r3aKJjnSf#~=*oxHkxKI&?HuiLakbLGdv$6wd_-h5hgqflV_e z{6X02S!~xw7+Dg1htkpTNKl8Z?)v%!W|O5%*?ZObC29+Jb_Tq*$kSQuF2&K~;pyUf zNmY~k-TL=B>7EmXY8RMIV4uDF^i9isKhrE0UAwgCnt${6%LhO1d^F9!rrr8lNuuE^ zf%6}Aj~8=1UT4a?_Pm*T7mxe8*Ec7hK3P&!W%%=R$qUYEtDhB?e~kYA{Bb9HrGS$_ z_^*ToyUw(TNd_br{jaQf7jU}ybl;Wf?qA;umOl(w&}X6Bu6%UrT$aLL;-O#kx}7VG zwyX>BX5Q-7BNYF$qO?&-R@uiX=gx^rjp=vJNol`SOLRXwX?}+2?<(nsHdF~&1#f;%C0x^56>&_g@cl&O(LYDi3 z;rYDxz3-0hdsmU(J3DmS-R;*pZ>_jsd7)myX5Qb7pe2nxr)O?k?RqckDVy)!G^_m3 zcdHh^KeLrTd~^T)IsZO71nq2^@^jO(koX|?7_UdW>aIV$EhDt`Lfsz8=atjmtE%`- zuLxSVNH&JSqFMUe_oK5HbFn@YV(++gk*Clt>hYR0X|9}U)2tm{2}~4KKKM}Tb=>*I zMU$m}9N+K1Z1d;KCy$<8{?XI_%VN7jdesIM4br|r<&}Niv-Ubx>_2|0a@w?j^rM?I zzla#upIAKWeWvf_9WkaS)SnohW4!RWROHEKmI=MtUK_=hW>v-Bi-~!YaKHFD!-vGoex%~dvc}ETN51_BX>(gkkffxQd^C(AIKzbG`z3e$L)W@_D6hV_AY(#S)KJfi!Te!Bp~Q<*Ku7Yv5q-R4_IC+g)eoC zp2MEn!m1Ezz0*K1VEen%^6P#nh_>uv(DV_xQ#-|@$>U*};#-O2K4*~);j0&|OT2V- z`Nzof0!%MXA6sv5?M6n-k}b=%W3!kH;&LukO1|!DS;?HWRi~hIz3{}`g5ZrG@**1N z9ZzftSFAjYnr@F&Y4-hoLjlz^o42t%JGhwmLF;te0VtN_u{^vePU;CEO@=t zcG--7QZiTNO^frgy64)gPxK8}+j!u2*zyG~o6)2B-;1=+eJ!?;SB##eY3D9jcjL_SKoK!( zMU~CWDMh>d*{${c3p?_;nO_v5_(}<-Ws1^*r$STQ|OqB2p&NKrZ8=(F7qr+z!%I(rMwC)3hq z7|42UND7@dPj2r#nfRV#UYhZnE?RUY{r~wfrRduyOV0Z~ZW}-K>wWlt@}sfPKI_?Y zF1PG+l58QIoR5HCLNt|(De0bd=BQZd7 z`9>dUsi$`@?szCI!xkFrE`|g`}d2pc5aEX+c_1FuT5Qb z(du-uOy+;C@`d{?G*2b<%yYQ9_1eFgm;H*R-8?t<$Glj-Y+2`5#_iW`E>Z|Idp}+4 zF;B=}MwN)EbC3Mu`?=Ay!Ls!{TgA->Y7Y+Y@;KS#5mXU>ibqJ;p*H;b^vgD}vGq?F z+Y7@?RO+WRxyamWpEiT_BU_D+)s{Wmmpaz$$(sH9qT=?83z^@Zm$fPs+tIUlj~Q?0 zEY%~q8GiybYFQVGD@*=9YnQ1stKj48qf15CZcdBbcJ6@4)ajWUHyqt=J?&iFF0JTI zuG~*+#FZ}DxL-N?&m>nMZkq{PS8?<9ZwFl+_REJcKg}vgOnbX!|MKTg7Rl~kd%5-J z`Bi(OXE8A!z3sezb++`~k16jz&toWk$LZhIQTX(wgVDr_%UAEU``?*;P)Mb3rOLN! zVTDgUryb$!DSChQ-u&{F;a=w~A}%npOy?+4e0{2MdGxab@vnJfN@iW-z0%m0y~{T2 zWNy^r#!Wx2`u?8XE!^PL62Rc1tMl{BoQJHFmizMCu#sQ{Vv=5^P8I#H za6|Ck6MuIG`;z_#8!zbub?)}F&6xGi?4qE_-s06S(tqdiRxzFx+L4_Rm2Ie?rE8tl z6qvg3^7Z4_c%H`I+!|JUGmvjhQhjGx!UpZnS`FP2t@FH?)RxvbJPXxWu#|I+s@~NP zaW@yVN|ZP>+~4pz`_k@A#`;5bcgw5}*-N)A`SWSkyU3|lM(j6b)Gs;9id>%sP= z(m`+5^>k8#ZM&pf`gE~w zjM6&Y%?BJ3C%ZOJsrz+cl~_LOt9MUIUg$EGXbJgrwm0z4^!;=ss>%Fi*s6<**C?1j z%e`v*_JQnL-_uu1Z%1%k?GK#t!+Z9ktxFxfLY{`bnif}PWX_WC_7fW?_ZFF?v!$gD zEK`5pN!xaGl5Kd?jagmh%iesdntAcHW3bl_o^27*OH56;7Hr-&cj1C_0hg@XPP^XZ zOj9ehi#T^|ZQu4OcmBS5C9$jiMD_#&R)GozLv@FI!AK#;l6JWVs=-Z1ABA1p*V80m zbwy|Isg0|z#_Uj&b+;8OeAF?iSZm`-k3EazvZkHQ&k${NNaNvsHG7w#c9hGjyzV*c zF25DdS)5ZoLreR%)&84Tw>{;v{I*fM`|Unn`G(*3W>2U#RMEZ?yO~v>>(Fg}-Y?uQ zl+230X)b<$G+{?*!3VX4Ym0*Q5KJ?o=c#dh+7U(c9gR56gb+ zXKyWG6SLk_u-buro#MtNdzJm9>J4%ZW>mz^{3zyLS5#S1VxUoPvgO~oKT(#OH*YFX ze#M@3Sx|vL@7jmoECvFNa^llIHa=J6`SCi#Kux!+S+x#ssBul{^IIm4to<4f`T<$>?NC_S908dfOUyG(F# zmqe;^sz_pt`(n>8X3tzE{&UC{-fy#ej}-6vbL-Bv|7{dd+E-CqYPYMVwDfMh{jaBA z4!v2?l)7jstFs@ccfb<&=9ibbU6q*+c`f?jaG^!Tq?0X%IrxWdXxRGIsr3^+sL1^* zwcNGSV)vi7U*{hdzZW&>O;&=C&9e{QoxW?r4L&zjFVnb@aAcFfotMSy>-V0rnRxx* z^aJ+(w)U>3I|2)mz8pN}`>j@Vo8PI_1!k4D`B!8!Z+quMfUpo^XJ>IU!OmlPg9vKOL#@iiFVZ~r*k)^)*q0Nu$=Al=_!xa+Q}BI zyUv|Xjr#H4)9&=^tA#fW?VPu8+U;+2dE$L%(c`Lliirvt*SQY|zTbB|fxS24$QFeS zVyaUXt;^W+VsEYgVon_=rH&11w=6EY9_ci_5$;-Y_xEA*kL%cdw3Vh5%__O<^?=#D z@a^06ud?o@f0Q`Xlf7isgNRq01)@vMYu7!#Wc==uR%}XX*xEne)8_RTR=%@8zVv$h z)T54TT=$)LEn@t9k|^&K)k|3?CTTZ*UpJ>|Lu%smr4Kx&F8am(|K^(ZCG0o1d<$U} zOp!P}mpipJ<=U~=E_+!nDGJ^^^LE9ae+kn|!`xIJth_kU;3Z2KjpNii5*!!+1r_6>$lIAO%*k(-#1E6XfthSVYh3XBDdY( zxeM3j6I-Xg=ieb1&}2A8c=DOvp65&RMYeDGU}yhh>9VjLkA87=hT26xd#^D$c}lC9 zCF4HPg)=lJu9xx7i`Lp7dwnK&$N1yY&Cw!}B^eXGMi|FVM-*FZ4YA zP~dQ-LrW%)v%YCK@3BR*UO%pzYhCdm>}dC;uS-scWrRG~_V2-QwyDn-?9tfs#HOXk zu9DB{)t1t)QxaRGL_JS(7{^}?b`$E_p}5jnseWeYzI7GFkETk>%u4UCR#|X-i{Sr8 zcc-XDruVNPMiS00ez6IY!6hM~Ai%Uhkl?!dmY z>Be_dTaGmEebXUX!m)6kfbp40J{@NDeDe<+DcLK-{)It#-<}ik)3&OsE&cyB{93d0 ziwK+QHKpI#tKAasHHx>+PSLf`xoZ-ibi7XEbEox@3N*5 z>^q?{uTu76)VyDQVzOHE63<&pc&lG!{c@jk>X$I<)P?KLHLeb_`u6p@o@|c( z$wHa(@78_SIu_rV-S|A+(CAFYO2HcCg_f7CoUE?-oZvXfwKr+uN$WemW==}?%8gi& z`o3t&64y^0WsVsFED=Udi#3kzWYu_I>>lRuh(W#kA#3&H6VHXX+TWd$T*!3zaE%{} zU*D>vj;}v%Ts?2%UO0dKVa54cN1Fr!CBKF|i25PyG&Q6mK7RYw=GFVtTz>n0e|%wC zGM~>M#f9a|n~WFt6yN-(zrXHv|F>T4x~p%t&Hu`9^vjZ|O_GLwm#^Jjmpf;6t!84R z?b4NNSH0XZ!zy3rP+f4PB@C|*Jjq-|6dtabNH^VzJ2BH3LTN|5T(6EbDCCmOi@;w zrmdJFbI+t*^~JoLy~=xaPDIW-aU|RGppmA>YxaW49UHPUbidT)Z*#fd>5nHqY*`I4`CIOMNg&rhzaTdBl+fU!itN$ab?Ces_;jOAA!%DwyQVqb3a z?0`h;{Y#71AKQC=5pRxIzTRTC4bK~Xc5c5vJyOKXog;=Rr=*vK>7=5>3j4lT|B&x3 z;p_P~e^;G(YLmD=&+42B%yH>GPkdHQzqD+Ik9*Iir(T+J|K2p;4ho#nSEngjuxMAN z_Fna82XixRq+*pB^%%XbTkGT>uiRAYdF!3R1hot;t`7zW>+-eoH(Xuk!N_PV*YJBs zk7D53tF!m+RGPLwlwGQ+pUZ#66C=hP8~$~rkC!fWGrT(Odd@zMlsnI7FRIIVQ|8k1 zbG62Q>0NqO87i^&zsZLD;;YK7&N^&xtb*siH?So+2d)gS7+jBlvl^?&m2!QHoCukO#;lO1q3v3^TocKO!5 zkDU?^Camh@Jzm2c;&+Qf*6wJ}?V2?ob}R1LHYHZv@<~Z@?0mLYE4MsfoA+i*{p@Sb zhodVp*e>3vH`r9haARiETlPwweQZ|6y({0n|1Rs)DE?vIH)D&7@fTa$LbUZXuX^nG ztnl!3mWS!44~NvMy>@HI)_piWSEREqC$Q-L?k9d*?wL2A^6{GZHt5xChF05`j7#_b zk}@n}NeK1Gkuj0oR>QsH%=)!|rPI8U9#m{-RNzor|F2)hapTwTFFtu+{xY+uug3Cz zm`TQtCbreHvUdH>alJq5Ug$rsgN@qXC+XD1=-cVCym`{d;WB4~%aTS9Bek78U0EL= zD)VnsXh}*6oX6^)mo4fsE!{HU_k*&J(q|_KPdRGoUGYe#aKn@Qbct4xxLW7Nk`ft} z_MMz@*4HJ!%yfE^W)O1a%k5dVXDqHv`mQb{>Kkg=lXQuH-?6)AIQhd?T`|6N(Ql(t z&e2Ir1Feou+x&zlC-KtZm!^(;O6P5vtibB}Zl1m1<9%f}u3uc0`7zyf(}$Ix|8jpX zk!9Fm^n6eI&%NYZw8$oA`nK7x3l{|Zm^SC>6S-^2&yO9Rvpd?oPuo{z%YXKS zH@t6e-kSUM(r1l>#Y!p_W-8ge@8&26G@5yw*(XyI=VBzhwsDd_SN5w%EuD<~g-Y`a zrIubg%6|T^g!~2P8imqx4PRe+{Qc#hl;8I+^yB-E7V*88*1ZV6&o|Gv|Cy3~V`GMl zcbdGAPR8x}$JL$pcB`NBxNyTSzHjQ9x|}-G|4QHc znj-4NgJp2 zqMBP99@&4}OrY-j`T*uFQ@dxJc3z^wQhOt3@5<_w?b+-Z6WQ8yPHzi{EK*t3{p5Oi zg~zm-oH-`^Z6_ZVr0v^jap>HwgXdNsJbm-QE3*P85iYGcH%}=tDJ#~vvoHz1vfjM( z^EK6jAMU=HzB<}(_Z&OtrecA`m3ejh_Ra5=Z&N-tIv@#(?_qaeU@mA`YvhlJ~qwcZ)M(955`MD-WN|>oI3k6iGyuN=S`Qwn4I#+ zsN6|QA6EN3J+|h_F{8CzI@)a}4V&GruR51JQ_S*}<2~o+JMv9ZH59}??RVwcWx;Uo z-Lp`ov%m7s7{0lD=Uu%){l(AIt~LekW-XX3e*B%H9M{3uUUQGzEY92JsofwW@LllF zn`O?A(q<|Jd`}J%d*+cGx@5-*(V&?#_MZyqo_f*MBV6*xMAjvqQ(xSe!;mPr?fK73 zFK)U0=kaB^;^!Eo<+VXOknLSUpxV@^C}p0-UGtNC);7LgV#0p%x7DVG6n4G{=97mE zlN2kCs4U_=FoE0rRF-I5qknU9_u7 zU47E?@P^AYnVI{ICYENNU-IdEd+h8LvdXsiHZ~^pS%e7X6&P}es$8GAaf(9EUgm7| zOBv0lPH<=E%3PgVDl5wPX+cTvYZqac$^Shg#g?w!erUohr^^MRwox~=rc6^_wW=yR z`;?gY>nhf=P}$>F+>=r_*@VY1Ij6NcRrnSLYUtg*a_iSkx6E}}UZJyBiQRr(@n7p; zgRV*V+V<*83m0%Kou+S4b64x^>$ggprK)mW*_8@2U;Avc5$K)}5%@AI{?DuQ2;R5H zw|%&5GxgOM>&3ncFLr$SX+G`!_uoJ7uD@PCx6x}Ozr(F4TUJpiZP!GJZ-H;T4r~m% zHNV&Q%v7V)K&jN1?so-5U5^*P7xXY>D!-GzI{mz90ox|am#5h>toomAnh`D}vi7@O zhJ)1hUccCUEw@bB|CTe)=C4=Zzqe9izeQvH749XX8|)soHZ#QDG`q9yCG(tV5i{!Z zqQ8gg%YVyc4zeoTGI#F##Cd`LX4J$-tv#)@UHh}&%LI>-p!fGq7fy3|>c}?tO2v~) zFK5r5{jucNPQADL|9EkJS@gHr|82AV$#$Muri-7Qy{_L9rD0`K{BY)5--+QyMtiQR zr#IbHTgg||{nn%K^4=>P0z0O0O5MBkP389Tk`30vt~p<4Z(m`rl5xB7c!~3~tl3k$ zLc-#cEoLnDI?T$a(-{Ts34c0j$sm4e{dtWY zDNRO_sw+-uNcbmxb$aREy<@6n!*<=+)nA0lW&|CvJ-NheLe=JWxi!DSFU6d--zr;M zJ=4jyfce|}8JiFPy+X3(wm;K@zZYuMQ)bG3-W`1Er+zm^@jTmH!_Rd2oi;BUx7yUYg@cl>(Yb-6-ctWup$ofJ}+)#N^)xv-;&SEOA+rFf3<<80A zcHWlh-k?({bT#4c*WJo1x4YzB%99uR__U(@{KuV-Zx)yJJ>N6y&#oDBVp-30ddh6N z5Sb(Us@0`sqj1-R05Qw%-p?1GwoHDh)74^KUt3pfJh$-N-R|xA&$?GWc=vPm(VAbC zA8+5B`a+XQQ0S-OjEh_JEl%$`C9lS?{&@EOG@ht zq;@S0DV;f6w=_G|!g#i8=Cg(Q`)2xRrEYs*QF=MnuJ!+Xn^)^6*PL=_y&1c7m63bb z+D3;=er9fGp(@?BCyJ+L7--G<8x+?5vWGLg>3RGzixdA2atPXRcqI3`2$rTznPkBc zb>cyz{O;1Y#`#6bX|+ELbPv{d288e`%W_1VeX5tKGjpo`Wrc#tYo>jR$x;>m!_mNd z<9)!s4NR|->Q6k0d$wc68pBEk4Ws#)+xITqujRPCfzM9n!a3uIyHBpt+7xwDvO+LR z|BT3b_Wi$8rZ1N|aO~ZK+!qH=9XWeyeaNI&9tIq7u}goR%UN;k&c6jWOLorqW4rLd z!sh|Um-qZ|e9>~JUBCR=?~}*R&)eMS%ivg{GsjwYSGhzd>%FXJXVmLwsJw_@<pLxh*%hhgvF{p(nX!Xx|v90rz4>-J7 z%;=vU& zPviDS@B91r&wAy6nc|EBw^F`HT#@X3sQ0*{<52)ppKg@>P95(Q8!6}hODf*`v$!62 zEh`WgJfX~$ekc9v$(3w;CLPSb6eb9j>VUQoPio_Wt=? zwQ-Nt{(V0`{QGp2!h13a)nq%?S`oht-aymiX##i|A$s@9#0if0vZ%Bqpwop9Q}SM-VR z#nfrv0v5D#>^j!bEG)uzSLD`jjRO4zYT5}}>}#e*&YF2%(fi6ajqhpOCSK5Mm~h5C z?3bp-2R~b-n%`~-ck?7WTF&p<^C~>Sd)tvqrrNW*wn$xA`u~7UK&-uQ`Sp`Bo4=%R zv5G`YOih~-vO@g$yi_)wZL5*sm|B=MeZMcg?m=`K{iY_QcKiOSV36l3>*MV7h6^mHpgYlh+26oC?|I zn`Qs`w%x}s8z&uL=QZ3uS9#s`xypX8yz=Vyh?MwjJ^Dv*m%Q(sWX^=E*Y2-1ubC8= zAwGZIZ)wdFzcf!&A|DFBU z%Z>cP4*b(kJ^$PhTZwIsrNlO}AbKmxUh!=I$8I00>sq_7XgOBgY@hG?mqC5Ur8w@^ zkgU@3E}p_euVk#ZUcd0|dU;y;V~b8rz7>B3Qp?K9?&$}ozYBQ&_d$-0#lDU?GmbFw z&-r*Jkx|uAz{*iX;Fxo|O{pE9rEIO-|ALx_pUqM=JRbZ$;C6Y>?|)yaYU+%OS_PaP z-SQ;d4sX7E`*b;5X=!a;u~pZRf||;&pLIV;2dqBwvGuuS&%_(-j0bMUZY-snp<<^!r>^pxHuJIit6+zdF*83e{OR3yrheJgyDje? z@LD^nZV`Fgp1$OY?a?chs?RH}-YS=9|C8%fl+sIA;h7Pb{72#9LOW?Y&k%-%OPn}4 zE-$R|;Qdtiq?s>ru2hYo@r!45q8#DJ8{8$DP2?FD@HndecU!8vK4Hcbqn)RN7ON%e z+E%`q*l}$2o87m!s;DHM2>ZS&Vs%qr8w*G0`MtjN`qQjL&mC{JXZtb5is#ZD^`4^R z?2S!a&+80-{FrGKyrZQ;P|*F{WVKj}IY$JurdV!oj<@pC?&0X2`RvGwbQiDef9qP$ zsLwHHQ`yaSs8(RjyH3OIX1;*E(qX+DUvUMurmpguX}8Fyr}INj!Glv4GEL=MN)5F) ztvMj>A9P)6(W^gko*EX;Rr8;))u%7Y;wzo%=Q;mY(e6p>v@;bSKex?#d$X!)r_P#| zU;D*3dOWM{cp1IKCQek-N#Jc2OZ`sER~9}>ue@dl7nPSeL^H=oML7CKOnK``{3<=XB5+=Ur<9o1oYS+4ByWG~>+-Se8 z%Mjotf3ZBQY`6M?HASi-oM%%e%)A|HeB+VleMOnc8B;}9X=<31Eb4t_DDyB&>v_;# zliG3?kAu~m40|3-{`>Q~?a%A_oE-Cv6+Zlu5~x^jxIq2?udPf9p)=**ZA^W;*v5!` z-}<|2zZouGzT)q;qkP@}rsoE3S^epZiTtje$^rb*tR>4nb?-d$L_9}!rR7XJW|z}K z$3zco_~+Tsb<1v_e%9p~mx^XiIhAzT{{7{pSrLCy72do}UCQHmeZ!{*mydmBa=$R+ zz?{m%8$KG|I&?dJ9g~fhI8{=p3N}$@v$*+`?iYc+8wD!&eX|XI{VhN* z@gg_(&uO7KX3nmB=T2|Zkd~iuCG+S1=;B|ytSl}~>uzAlG0)K~nz}ey~>}Gk>omxv`V#aOHj1yjbnU5Z2Aw}{(k?RcCTUKvMrv!6hF%Jm&bozvHjbM z@4sHWzj^U<@zK2J7NNCJJbG~(=y}M z+XcGzpFg!pLp}KD)Ogj>xzDoiJlTELM)Rlqj^Aso>b&SEkvo~;dKw011GQ+Q`j z&C4%EJ^SCU*9&_1uFt>io!iyzey^e%3`6SOk47)GbZKVzV?9fDLe)goLQ9R$^O(7d zcQbY`jn$K3=RNBtYCe5>^`+ibH_Ojd))rS)mDTWYVa7q?DU*;sF7do3&Z2|X>2U~9BJT_X}wZ|%iee0|T3s1|&-dLG1 zasIPs;lHQ9tTDT&@amaw%>9S4F=`c(>EDIretm4o{-52Ne*2_IndeTeQ@)$tC^hp7 zJ`ol+@(weVyTO|g4#`pmD3Hhe#QRW27`Jh|W%>p&se)FPkZ!9zn=HjrSe55X1s7cC5Z$QXb*<%Aem$f7M3pHk?d0<( zS(s0K+^}iFgG*LbEKeO(wGPft<2c&Uu%U7R)2@xjbH9oDD8eabqGho=~{ z4lVf5cj1Z3rRsJ3o?48WP2WBD&Fj7KvoOht?R|-)$fhYtwTmV&TWry&e|Wy;$UXjN z2^Ye2uJ~`>-of$o)5>ps3jbQ41SA|ktE=2{`Az4wX;I%e=G96VetVoEV^-FlRufUq z<9PAQT>V(v^u5=nX^5E!B>(%Eu#7!tb*G&B$K?MHE|}UH$~shNY?x+nQLgVNyRwmk z1LxUi!7?sPY!}rlGhh9Q@T!=y z?z21|+WfPLeLriOivXLyyyot?68GkOv*J&*?r-#9C~jZV+46&Ri=yL;FU2=<%Oabv z`ArNcj%b)0yFNR!_`h)KriT+H=fUXZQohtl0~!BGpq(kH~05IcqLep2)|R zx9;;(fj*8o3*}$ciYNx|a&6QpZeX_mDE#}B$?w+CyiF=@*Edbw{PN|@{T-`QI(D_R zGjF-{SZK>H_nbTHACl10wS;$_1(U;HT5Zp*S}{j$?QFii z;u0#SpH2P9wMA#;r}7J8+bzyGvbWzp{Pofgft;oBPi}_q*-&NRe!67twb1GvD<{3_ zF5G)$uH^lV4V8iB0S=~x+pm_qNDWAA(Y>_8Z_ewJ?-*FK+EdoP?PX|Jn*BY{TB&hE zpkc+FC)Z-WiMu|yQ?B1~_zY+3{7VNOiv+y^2yU~uu+Bt4gjGgs-Ab64C^ znJUR-c;bl}!}($5RS)^yLkE!A&w=lIUu^TJ)Xtrq^0HWqdAo-!}8YS&FgO*&8euoaJ}D@ZDsKTfI-Rm)oTNaDWi?+lv7j0-{Zb|G&($(Bhn zb>G)7n3>sK-qggh>%!d$02bRDXT_`}OC}FZ;S2Oh5Os{rXx|_3`w{ z_x&x$4vJVFTD|#(xYX&5hDrxI`(~S4TI`z8CfoDL=JZsf%pw_;kM|3Ag&058$~wM= zAuS;yr7l`VCTw9LN5dmM3k!MA3z;*0yM;`2w+F7;8`8M-*RJ5L5LE&Fo&#{7A6 zd(N+4@3y|0DWTM8J>xXn#EJ=r7Kd}~?>H6bUMhCV$984a9;;UYY2GFcFFlR!TK#hR zx@7geq`klPx_`O8CQ0_M>@@rCgPB|2IIfM~-?qNRX_rm8etc)P^6bgaKZx@1oN8Nr zYu$fa*V3DM?;aV&cy2y$L!j<;!p`NBOkUpD%D~MY==j}D)>ypo)UL2LM?urf+UNfl zDBt!vw%6=gT<6~va#hpr$gi*no4nbE>))HyWcRZ#4qwjd`@eVA=k$ut&myzRF6mBC zxECJ2WcQ2TF|#et2iY=dttsi$yC}R>!Do>|{mX-wqnDON*zL5lmGxEAPpw?;TsZOh zt_AH%Z?cy4i?2GV5nib1uJ=SG`q{xK-S#rJ$~%HZmWvIRu$73+Sb4M}oZbCSGw*F7 zuFYS4g{B5B6cL?m(DG(>V4#kf=O@>*$Cm!vb;|5yOs}eCTg&X!+{7hp-8!C|6a^>D zEa|NJt;jLquF)wWrotG@cY)zEzp~t)*D>$hr1gv0_+Gp?+jb#)=EN@sJZ28RxY&2= zDm+tkbBPtSJIv(tz+}T)_tLDuYs_p+O!*tj1T+@;1=sd1Eo3Utn%o@1ZZ-R)!Tn=5 z(>l&N&6;=ML3dF{*3uoUS_v;UN`3Y1ziYN=hhTz-XM?(ghTlTTb$rsAs>)oUa)%cN zpR_vRTELXdb8^O!(!x<_k8l{?cw#yvrDX{(V}Ew zhQ8>?5m%qRVq%a{t=~==pNDVk3r;;{63Do&X`xtZ-u!iEuVoTL*2 z%9qeEH&WXE(Pox?w(;$|wR`rS4N>1}w|RDC?9JxG*X}O(oq6rb1Gi-Lvafsjgl}v= zckf1GyK?x1ye|!mn+l3*zaI8@*61+9_SVWp7pf1a_TG-j&DQxX*Thn0wX|*5TZ==| zS0rrLbEz!-yQOWmLgQce14$YZ)tnBoe-5;6%VgPcgwe?$em+@rTP+aK!sAKlM*3OSe?OUE=NDuT6{pGfX>jUl&Vv#L@!GIFE@j(YM{+ z4Uf*h4K7bFaOF(yp7qdod#UV&RL_ZedvCFtZE;-?vBfuJT8wAjg}=Y%ItO)$tj^rL z@9n{7e`D-}?k~J|Yw^9wC*OCUyqI}lZ;Of||K6jgl1)?!XH+E02pv<-pIDh+>!>pG z+#-!{{qZ){mc2{=|M+_I&(Y66zx;jl@?z#4YyB35i9QayEKjoL%?wz6em1ArR+D%cB$CB+TuK6Ny5L#;>$D3r<`0>)^%WW zY}88WwkuV!I}{pJ(~`Ge^Qn9j|1iE&tio8#>yQ$gtlK1o4Y#&i3%{Ox^vUCvM$aqB za*umBwDtzHxm>ytou{6EKUlx{=yEw#rOv(Dn@e98PC7DU`<>bTagixsWK(5gd|M_S z$xI4;#nj8R-{rs`|H}$rE_*GXzH^nKi06~}YYTc8Y0rPV&d1rHWz`!G^Rl~bTg1#?$z3Z4W~-Fn~p7Du=<(4`>D~|&@}&PuFJixKdP-ba#TlY(&@w#J(WE-J(7>7 zIvTv1E%I>AuO0rM^Wqb$j}>IheYj!2_iKlQW!HDDygO6r^86CEO9!fUxUlI>bhgin zc-x)2_#nT@3_jn|u9h8r6BsUto$^yk+px9El|R*Dw~nK!*Sgz=4BFp}pB~$}PFmQ_ zVgvj(Qof4KNr)we)g!Cn8~}JnHf#eMdmgCp8b*8Yc6PDY;WOsJ}z$0 zkIx_P$8+>1FbWoaU)9%|rlz56(=%uGxz|GJvrCxgX?pV7KwkJCbN-^xJq1(~(7ORsrL-?(|>quB8k-=3`BeDvtc z$D2Q!ulJYhV@WWZ_VcTUMBb7QFZNB1U!8U(a60QBodoF{&;DJMNI4KIU_9x`gIgD^ zS3P(By7`0Oujr6g=D&Zx)Jr#UZoTqVOxuP19Oo=y^yy6f@MBJSXUEiX5` zdh=_)!V!h_;)D;H4 zRZS`gu9JT9U|#S1nY-46{7U??R(6F&=Y2)rr|+XQ6ArihvuXOH~>6@c5lQ*eBE5&Gest$;5U+$0;fw zE^RBlV#21zu_ox-ixpGatdoPSJ9p%Dtc;Fjwp=Z3JzuP>Xw9q#oT`T0wqgcCTpwkx zvV;gN<8ko}Iw5_P<&}A*V>4Uj#%x)CGikHT+~xYbD??Wmw8(qiaA|Rt;^lCObT}Mp z=JRPoUQw#SW6lbxd(Sk510opi%l_aB=M|K_x%=RTYe$oK7ER*$$a_>($8E~Zq)89O zJDex5Pu<9oaz0(=Z8r0-1BP64q&%V#}wj#nXf5{gAfKi9K1e_s;codBv>m4Js?kLngfN7IoK8{Li%TfQ2|_L2r)j zT604aBLf96;L>-?%qdANQqXtHNi0cqNlngAN#(M$<0>vGN=?k=s<<^bJQsAI-oJVA z55MNk-m_XX@XG65@AQ1{>P6o!>8!qfciU-Av((R8-Sb?IKL7iRkwx|Nwo7@xCv>nl zGVn7nZ7`4O+jH^tX7SCNKZl>xD7}25-)(cv5vB9Jiz-A^C!YROVG`X_SNAq0Myr*gf-o^N$Ii+j;ozN0mO|=SPpey{bBK-F^Rjy9$Q81ye1Gx86&cs=(OuRYm2@Q@QND zljg4SxMPsfzg4NQO4Y+zvB+0tDnAGRK}Ng${QL8{`W-87%`@MsGhIbj`Qz4@X-SUR zO$yneP8*sIl;6|LU3+2mnJC78OtKP8=f5775If_mDB`xSl>PghH8=Wt#eQsG-MLJA z;!8#z!yOiB^N$OZ{@Z-WESY29;)LS|)GX7^9hTrYG~?WD0mkHeQ;Ky%JsqO5rZ%=~ zN3DNQ6sA|U<@P!k&(*S0>!nVoEULDUb2dA%zh%%_wkx~mJKtmTXvxWc=Upx^KYuDn^7qck=`UV4nLRLlwBW$wRYJQ~ zzOfCBDx9#ZEq?Lp*4Xev^S;e#on53@z3QPY!z0!O(i^r<*lKo@`>D&U6|4+>tf!X= z<=$0X!mO(L>A};bfg%ZAjS2I2I=+#=F2o_b>z||N8uc^N_I~)F_4&ZEDeG>9S1HJL zaeV&kyss`*YxdW@E9R97ROiV0tG-%xL6$#awo!C{il0t~#y>&ri}T8l`b`UZ{L*|0 z??nlhXMeO$fB*LP?pJ;B{kBY3zb7$Vvc0OfLU`J*yjjcIHOxdGoCy3qIWu%+*OY~> zM%qvAFVj*yI%V%(_Xmc?J091>+E->Z6i<-dB<#*LrE>Yz*tL!qi{3YjsqD-(D%tBB zamDIyh3W3<(!#IL4xjyUli}aV0EOwyaT&}hx1a9JwcUE5*+Mt)qWPA$uWB^p8FW2f z9=%w$xq$z(hV`qpS3Xb8ZHrB|*&|zivw&;X#}m9W|NmUD`9`l$UB)Y$)vnV+*QejV zo$#$_VgEn(?32PwPQH>>$Ce*VFI1@h^;$f|{{R0?_iIkRleg3Ut;@cl`XLi#Jb6 z-F<3hK=$no%pZ))R+~<|?G|!b?3~#$#g0`sZthzD^7c8oMoy7!p4AJa?yeFzGGXAlRidNTg!WS{j zdVFUE*@T(DAE}%d`0i)fp%;3;Wz-t4X@1+J80201W{R3sjAQxoqqZ9_F55eKbylyg zSfSq`S80yQ2B_TN8eB_6R$Q7f-*rVt?y46?0aW^L|SO{`@vnQ9Ii=edsl?o>IvC*YR5Que~#mM$fx09P?e_z(KRAXPR?``Coox7qolR<)^(f=Ig!R zP7&S-6HNA(P1tIq#n|O=`vCv-hL>;N$TKayJr!Hwj;$4MNPOY`Hat52iHS(v{P;vI z#+g_9j!(DPsM#HIVT+c?uIY{q)2?bvPO-Z9ENIf1zG?C23*Y!m_N!{#)*!&Y_U_}y zpMT!jH%F+Xk;6)|)>huPpVgU5yT3AHpVO3zh$^niONXcY%#d5So$okPzxqD?xtl*v zzMS884pg2O|10|TD??|evAym8hi8A>{d4=}#y2;ZWZ&%Onjod^lQC6rg%3c-kjl?KKa_o)L(`t^|u6AxMuP#e&Q??x$?Qr)>rPE*MF^B zT`%e;Fk|U18RiMX?Vb~)JS9Rl-kf@Lnct@!qR-i~ImMSGFP*K`_vQD+mR%7$_11`J zE1p@s{k6)K3E8re*Evt!Xwg`4W|!8bEg5oQ5935`iC%KBTBs}_($pGqtY*^n$DIj> zPU?x@REymZ->Ik|>RV(%d@2=a@qWxvV$A&NW@0s!?*3S4?$GT-9Q+&)bsU1I~ zj=Sv=m~7PTz4!S!GtXdU-c?#VPxOiey*wN!A$@vEnXj>ioQ70%%t5;yhg^QWt&HWl zbzt89;K+BgC(KxJ*Yb(QR{!%xlHce#p4!JLvxwtoTc`v!Vu!JK`7PC7g09JS|4UwbC3NLBPuX>EZG>L^OtIJgrzg*x_*_nG z%3Z(23AO&8>^4a9=EnIyi@#A(w&~!!(%nC`e@|l;Ho07qDzis^$i%h!o>-r|^F{vJ=|4SsEoT;^-9PJ>ot#}ur}R7e-KSAT?^5ffb|5Rq)7Z=@m*KytT zvYxdcWrd?>9CNJ9{bncgXFH3;WBz-w(IHq0EJGvAVFx1<;!i$58hN+>&NjjN{ri(H zPS0Z2*9}^tanO_D_J-NoOt;VGUSKLrcoBBX_G(n7Zf0$H-HZG8B>7gZzqg!UOqDSZ#jMc zdVT$$piaf5d=V=|HW-?mudn)*_V>~Br&=6L`U$6}UYq#+&C9D#i)U5+eRfpee|q49 zwfgb2Qq9SwyV6F+vXp0QFPVhz&_k)|KlBdgb(e(J^fbnlPrPk-IL zy8it9{X2G5CG{_JlTne0J8(IDV^_z)J`VTkQ+1{lZ4_$y*(7}P>9ljV?>*t|TT;Ga zb?n?XnX}ZG*IVY9MKbH(xvjUeT&KeFWAR9N($ zeM`EEt9<;^r^n(Ne}7?p-t6yCDP_0u*~iB`{_{2EteAY)Ofph+TxmJ2%TsWN{=WY@ z-pYrMYK8S2H;lF2lohvFGi=Lqxv#}KxBdj&xqQa-)!{zj)yJQ5tp71ia|LL-`t0!@odA{6s)b>sKaW(J%I|QGkdY`%@fA4MoQR|8OzE0)W zzk8_si-+9B&9nE{U8%KLdY6I!-;>jSGJO9DyPp$JFcJE)vTAVy>!#rRqFw%HS~~9h zGBw(*e(X@uXK}^uQh}MyM|oNpC5}3OKgj9KtITR~S$N`K#?#BzW?gYvvsNu}-8m@> z+uqNU=H*u^nAbDz;b!)Iz&QD?xcqdjFOwc+#2<|CTYvU(gRA3>`>&tO5EOPS&lgy| z@s+}bGtZ0OTx>n4Vzp(XmPDv&?z~zHwbs}*FMevSUVTya>jjhKyD$B!XTNgrE39HX zxYhDt<!`eE!s^to+g5#lVf1X5Q^v7UlYMzXQOXk-=j~~WzVc<# z3~v*O_9;xsX9}!bxUZx%GTd_A=lNpQ57&EUksG%@K4$m5UFmi@%Y(?Q$lFI-#+_-1&N#xeyL8D z=m#ym(>T`2{@Ca2mXi0St(pJ$sq--~L`r{i7uOC=5cI@*1WaR2Svu?`2 zsSBHba;#d;)Odx@L6vLG;$B6$fWnM7hu$CfyjK57&Mkp56}vk@Qj>Ld3-b9~Vf%b1 z;oS9S87nL{x$rt2we4lp`n+alv5%y&{e<+Z9G%;v&F6jD_*uoGvC;3w!e+mhMrslQ zGnBu+xwr3p$(2U$s$J$Oo`3IYRO@nDOtfS%Dwt&DzpmTzcT28ia8!Sx{#;js4O+WT z+P!p0ne<0y(z265vm0hkiMA;8G)-9^d0@Bq-d|sz&-dTXqtacn{9dAq+mnqKu07dp zq$wk%s+)WBX#umfY#3u|>gJy&*`IDb%T{P+;L#FGPFy3aU-IeLF~*y%a}{sfy~*IR z-Ybz~r=@r)KlaGNicd=o-C7j8|9to_o_ZlbVx+@vA6u<7%BZ_nR{j&^%u-qk^3Wkk~d3$p_ktL z9Zd_=?%j-SnpKv>dGM#Y+?BbzGbis-RezIn{gY(N`S6>$ucz!kudvj}>|<(b%m0Eu zA~)|YwB?+$T=8>v)BT9c4XZpar`>gp(VP+%yYWfZtJjPX5{KVw?9kqITlzMyL|l*i zM+25O{BBbE*Tm)Z1Umn)Y8ZWKw25G;o9_ABa*Zs~HUK4vI9p><(fBa`TjGs`COKYe3xV>7tMGl;-l57(KB)CcNMj z>&!U{D*Ow0nhhiPUYxn5_#vHXPjB9LN&|>G@fSYCB+fKh~ zOS_==smRGJoh^uq!(Zyp?R1$*9mZOM46z?0RF&^f?>ZTw+tOq?-TrH@!k&z1dGog$ z&q+Q1C$Q|ul6{6oq7xK@T!a?Qu8a?w7kgRk^-GODAIK zm)NO%^Gi5+CcN3aWXt6~#gJK%6EAtU9qcTUua=*&CH3W!Plh{_s-g^cNZja|t+8#w zipeJXjnzZ$olaF*+0uGmC&6wLhmrKXnuCYz?&LrJG$-Qg&jqvI#yTFmur#y0Sm#g# zUqwNW*2M44sivc^Is)uBnkH4 z^{kt*n_Jw6Va4QwQk#Cy6mIzFdc)fw%=%7_(sYJZ6BsYv<={`N(Iq>z}B zgKJj5416f^**wAZv!}Y!<0Y)0<}YnI^r&u|OVHfdfGU2!^z4Zon{VHGy7)(zS?BA_ zea&}Tk3BeO%+%&{g1_}~P1%3H&`!;T4XKl#Xy)DsGr6pKDDBg+OP1yDYHm&tdZUy$ zSC+v$htutc$IcZEFU0*Xb^WvxNpE~3w9CI(oa52ES)0#^H(MQ%7{Qvt+k9f4~&T!ZN`NHdZxw)nL-t2o91>>ibPyX`M@T>&; zr3qG-v|Y_!?o?VSK9gzru@I)evrGh)J=oO!jLxlFyZxa|SiD)u)UvMuDzne9=!Tn} z|FSvfkzLk*`7Et3#TrU4wZFg5jJo>wrp>;LynWlazkQXhx2XUB{dKWyJ%_5(TzyyT z6KA~DGX%1dZW%m|d*Wj+da25A>t^<*t2_6zBp5ArdbchA!A!2BS=zq~&gAw^f080_0l)q#zxh)gkS5}Zu(biPby_VfiQW`)G$L~HZ8M&_`|%6icM2Qtas66x;%27$ZqMECOg+_dDV9CEPRY&G z(5iRK#g>mMvz}f&9U3WPKeBiYO*<~n|`Ic@DIPy#e)ws%d1Wa&k*T5_B(f`|FW*t6`QMr z&9(o3?9$>APQAM8eg2*Jvh#nxe=fdp!jE<7ffk`_hBMcmN;8@ob@ckvs<&>HKlh#C zE}ydT;7u1nw`$qV!H+ZzSH8S<`qaeRYd5<-Z2Qb<{_!|Ns%j^r@z2TffB2*_C#fB} zA?vc-h{@UTt=U=so6?I~8*ba=oLaT#^2*4Rt^YH^=FIDG%Y)qPQ0o^EqGc5zDMnKKy@29va&{?OgD>Q)nDh1R3hYhrc>Ufc2i(z*{7 z?DcATuU6;o{pcO0B9pWGC{Lv6JBBz_y$^6|gZ+TZ!>K3`maWuBH*ckCvoN9W64z1gLybNt%c>#Qp*cq^SBe~p`!WVUf?zt9oF-*%bJw!Lpc|OOh0L6 z{rZ-FTKfBQ5VVNQ-$cTbt4 zGIl)3$eUd>!Qf$qL1I+)tSKrFZY=)O{ZuSXW=(;iZsOn1b&E>otmW?%c((9|rD-LT zRh?RoFjJ=Oq$Xj-_aevUGzF{Qnv~>l>Qjr>pDCK@7xp^H{!yLL6dZi;xKE|r1~b;| z&CV{YT8A{*_CNcy#bC-lgPM$9#@2h?MUAWvqf0t(r~Xa6Y3?I%dQmO&(i@&-J95=U zm@205$voD*R>~t7=n%^2vyWAVar>I?viS0=FFpL2Hz@D6wyGE0G^a5;ZQ_N7Ul&~N zo-E=K>R9SB^YM@ClTRniFuKg0s_oV)x>)~lg3b0YN8jk>uN2-{Dab6$Kjk^;l(eDU zMP`ohDSoH5^z9;qBf`w28bgD(Y|A-brjy;Cz3$n*PX@XSy;lT%YocfA(fpu9~gOnAg4h|EPBNpAW}Rsdk7y znj$mRj*P31? zb1d4{Sf-lpGCtwsso&RJyyDfWLyCXDo$~#Wb*+z|F>(8~yyprE9rgK_+f)|3I$@cn z{eM-#uN}%R-}w|39e#y##m{=AHEp6)i2ufxpA)4KH@;Y+U#`^ML)Hgbw}gTfSkks^8nD|8$i9Rl#Zr-ODqu0UBW_e625`$_y-@uaPw*=F{NK*!pmlM@#HXVeX1IfA9;Ho`J`V`)bGfiQE!e2Z_J z3G96x{(xhfXit9A<(H10Z?Da~Qkb*McF9aW-5?=rq0Gr4HgDIzZ}JXWX4Yj`_Lr*TS7vQVABvgF|OA9s&Vop@Z` z`RE$M2g__ff4hD(x2973%+#QejR|sXefuKs#P4^#+8 z$E8^u2bGu^4}9KJZaZDEC0N2?)*Bo78eB*qtr-ctf9M?SaFq)|5qdMW3(Sd~o&I zW!zh}w%@+wUVX0HRND62hm6C=cc`W~SR9!v?rUKF;nLm5@eTa@|37IvTy^6&U;QNc zw#E9}oZ zqi~^1iB+?9_N82RUBHrSq~ewF;{4C+d(NF^3iq7&=y>cl?@vmt!NEB#BG#H0%HRBq zXDfc|@Y#H$g-xoV!k_y(cKf&5?4Mf4{Qa?S-0!Ln zW)m~R{0+`Y99vp-@Ky5h1)*-T5}c8L(z|wad9I6BT$ii5p8xUb_k~w|BP&}cnK{k; zcx-v?%_ovYjJggzof9tTgzdifyvQg`ME3Zcf=3Z6+KgYWxQ+gr1%yO@0?PGrb?D=yX&9@7&Tq`nV6;*v!Q|Y{n zf2ro`Ov|Uwwmv`PW9t01(1mHs;f^m$PtM}2Qoo_F(tUmD2g`;XKfnC@n<=n^chkDX z8#SJ;PTciOlyCX^#*HR7-~B!rw|J+9v`NU#%XaHGZ8^JY+4a>Y-FjvOy_@RCGqba8 z&Xc?Mo9j2PI+D?zdEYZde)rArzYk=VIy5|qFrV;j`|YqG{l_;ip9$|5cHB}{(2~Ke z?(8^i_s!?}bCzsik2)LjisHr#tHbVeY*i6|yH=^f z->{owMvx(2LEz-A3w9^X6JcBz$k?|-bERP5^rnu}RD0~UmNnsXyGY^6l-wl`&SqWq6*U)4YxofI(cR#Gh-g|v#186ye-!z%xE`InAyO!B!WpL)FEi&&+wkmTYN7957<>LVqK>rAo6d4 zvj~TP&GZz9*AtA)TNivebFHaZHpI^SE6W9l0`Ru4#ApJ12#X2X)2W_y7M8e#V|()zMhf^zr)l`2BHa=jYjSwK>Wq zy-GYEe!cwNn=`uS9$xi$?f1N6anJU3@&=-9e&+jG{sfuxixmlU+de4mHaB10pFh3) z-67q3d#uX4%TMQ*zuQ0Y-rvvPh3xnI-;^V!Z}{rduXkd1H<#v%?bpo@|86cneS2Qv$a2)1=kq_d+OvnV?|gp!S~RZoqMF?1rw1pzeSh}R+rRC* zzx|xP`t|-QFjw}ES)ajJGsyO!T%mJ+ zl4U9@-V_$}$o&+${)$!W*5fzxns?9JZs3#pI>&{#wb{raspGc%gmn{zxBYTRn4Vi7 zG0)q^OGk!1>7jwAj_kD=R%@Q#ayt=M|K-5!0->Pwg(?!>-RV!7Rvt7zE?+A@;pvsf z8PgTt+RXlDW5m-ZoISm%?wr-UejjJMS9j(dtvWU5sA2UQ&K0{4XmCmTJy~m#s3@Oh zIbrju!*iw{ZjpG|xZP0c)!Ipt>}d_5#~L?pIL>9s)jf;l;Bxi@5whAB7oM?9p84k4 z@xDKDm*1~6PM2#dm?wM4(m&$luLobf+BWfPYuR3X)RM~N`bL;_e~aQ|tJx>5jP~_K zXr}p3VHciik+(>RUwzlvql;B8v#(d(Y(DV~lk&A%Q7Lx66IPNny-e;m=2fmQt}=R4 zwMzV(tmnBhKUu5gXUh8gPJFWcuux||_ne>)jjuGfE5;U8YyV%Fyl4sI+tz27_IbX1 zoV1Alo`yM#ys59>V&&@#>U@9B{d@DtRK?0lvq~e!&9)yD&%R^Y>=i9-GcnD7L;tmf zMy0citW94Y^Ri~KO3ckl30u>+F+z7$?!l{a4VphsZQ5-1x9029e`zl#FVD-Yda_Th zY{3#GExSd({95iB2?9^h}u*g-#PuEl`r&}(aqs*TF{NU0m>z2Hm=gQ`A*Q?oXxP0mI z$(g|)v)H$&*d^XSBpJ2waq{{(WwQ#a|34IqT_1KmpycMlmsX0~za6-Jm``bbS?;;2 z2g={0e~YhsSC_qi#_vgQwSHfjy?zz5VYsB~GocKHXJ4nhO{uAUI(c4Y((*ZPK65)> zO`6Z{bM;#;`%<=#|EDeHXOzc zmNMe;TYVyoe?2HoQ$K64N`^tcQpjeL*B$8`f5{+K9<$}&WYg0;uGU;CRa~@Y za~uy?O_WFpd$K$8YHRHYskxoMALOc~?Fp@vnW0j3_Oid+H}P$Y`Et^-9onU4Obgpx zGv%_ZxBv5GJyw$+3PBoYmNux>2)u0Gp0s-5S&QY-C*^M%-3*Vs7rCVD^`$x?r|C8x z(VKV5pXyIL-LIy@$$wzB^3_$}0*hp3Y@BhkUPXe{kMsJRV~xt0zt5J4%vdn}!-pqt zSNwRja?$(Wi?`oU1h`cju`~7w9%}B2)YeZ@VEUc}q zzpKjSFv;!N_2A#{%a0y?QtM(m89C{MMZ_BBgTm8PD+SWKKI(9Zt$yJAqbT}K&eikJ zw0aL`e9Qc3Y}*|%Ybn$Gj|p-Fr3Pn)+z3#DwImvi@O zX?v60fv`5I_kZo`^z)PIlA049C~b1wUS`&R@LO8>bsp1$@|9;E?%Dsl(eCJH+m|n| zetI3QS|A+$e6FU%b4|@p&%>r?a71WKHqqg+x_sf_%x;FAQVTC$<#_+=TxGWDlxa^m z3ZI;gLRu)FH&p|(>-GpD?-J7Hso`=n2r{3rA`rXNiE>~X4K1m2^6H7(kLB}t8hmNdQulQmv{Cw8w;Nok(4d?)9RebPD^DhArFFD%QgS4;oxKkc=kkw^89 zTfL*%RBaia_aQH1FN*uJe$72#TBvha`mS{M)>+9FbITYe&C>iX$v5MuPH^J$l6SLy zdUutS`%iD5#U$%~mA7z)6@$mwZPKqq55{t@vtRsVAJbByhY2xtnlE4TDH?64SLxdI z!dx`=MVWboiLOvhkJX~T-vgHQH9p^cr1`n4Cf|wc4>YpdQXP*kpJ@2pWWLmCcXK9( zgNzG4ss=HZ*QeL;FxsqG9~7`Z>-hEMS;}Q0(urKc4EomM+#$C$FZ3OmFmY>JkL}_w zSInkMcre#mwV$(TpA>S)e5Les=Do5}0dlL|PF^%IUB<<*y6aJJdGdFaKgvnF4+@vQ z{XWe>V|Ue)Yhijv!%Lce6^nddYkr^mP=%7omeSNShUHo}0)KbT3^qJBk@e~i7m=Ec zQn883c{iM+`6aHryLe;OK@C>}zp{0=A~?VDHR?6&}UJry&@+aZA|L?U?=SVJNwin4en>ci`sJ& zPrl_kwuxa=^8Ve=p0caDnjBiC=3;nbU1O70Z9&1lphwJ8x7BsbE_AzIy7kxn&!HPb z=Jj27+WumP{@ggr=NDT#`{Mns#tWYmEEe3XBCZ~4BDwSJ1)bG#HuL8_xw`Y#ZTpwn z%&I$VbQTyF6g~@GwGAUfggqSm0{<8Z3ueMe?;)z@ssBk=&q9w zQ$AZ>ZM;HJMW?HOXBF2=-oH=(&NhD$a?0yS&Ev}bf8V~leqI0Hzpmr1Itm|;&8$85 z@Pb>y!{DDM4VuqhS{HaV{d#SGEl29hi@rO`=9P*}S=ZqHaQidKo6CewqE&kwr^$bv zUYIYgmEP3-|CN5kz)%$607XKa))wtF$A;9^?hEvOI&kG^}Hg-ZqXy0N(YS| zn*T44W$yDW_;)5IxYdkDd&+0)q}fat`%4ZioYy{Y-+DX#UB^AA9as>@R~OG>%J<1- z%0?aE<6APis(X~qy=Z)PV`be1??m^{PpiuHsror#N;U|p8oofD=<{ZaGl{uw z6jv2|tn@97`+ayk+hp_2@8{d_A1z2f5GhkEko)h=83{gGdP zPQCL>diwfv=l%NBJDEN`<-W7{&tviX7oMHI9)4UrU4P$E<36V45;9^ue6yRZ93T0* z@&r%vtNC;^MXKw9d8D_??sGB|O_wTu>Q>hfbMdoG&y*0#-no-)-RqdH`%MNv*1S43 zdrhT}j8aeHB>TS^b`K>g6`sf~pP=*f_pWKN7oW|3^f&C`Cq>iGs%sx5{>V0B{$uie zs_>4TY%`g2cU(?eF2nWA@s!X^i;sex?=1r|{|G)-_xsepeqH>(f-D`Sv&3iSt;-FNZ&@b0Z-;T>C^kA=k1kR z9?`Xdg`@rNw#}-di_7LpukxS0EY5V-lFZ9zpGR&pFgX={E9u%Ujf_?AZuwsSW@Ho< zf6X<}-{sMLCas%swY%4!d;4;k$M$}h|V^j+@uaHj2J*CrH{sDm_^r~LaFv%T`|v$c~yX1|+0WBdHsh8&YFYm2w8n^jQH$M!pyFXZjB&s^FTOrJP22TUibS-h*A5w_SwWcqRcxM|4bTw8>Csh#^V zQ(jHsP@@wr*3lwn@eOfirJm8p6xOPw8wt$oSoz~mv4=LNoZni7o42`M+&);j>e2!G z&6=LSo}AlOGx24Ujat$Pox9MHl8pUe7zU<5joAp^tn!KKJyR&dHp$Nx|#gHrbcA&gD#UYF*3m z)G#JiO^B=beh00Y?HLJ&&qa- z_4AkcI<4%cQ1cP~T^HBB%roKj=FxvGp7r5eawgAvrZp!W z9Iczvo?Q`1E)6~^aOtjGmDvK;DrRxDy}It#EbiVj{JdmahwJ+&x#$~>I~tXu9U2Oc zY@eswt36l7kLCCGIUKAEr#w`Y|If&J-f@)kiQa$yJImzCqK&>p{g2>ctA1d&yIP~Z zQp5RxZ_?`aE|D|xTG|TL4N{-$a%?MCSnrwk@#6RY1r0wU*jqZAHoq@)sOV>&wXWzY z3tMhn+Of0gwJ&FF|0&-wg(v=g*>$VUAxyLHm0F6OIK!wX#IU2_|5lsz+RS%XUNqNm zD10hD)6nJaq6fPwyE}Z8{_oT^B1*|H&XQ)S+o8X38H*%=STyk|e1 z_i%r~F)nqzYrMJa%^z&4pLOKzWviGim(lS3O(1W9eCCGl3ygFbV$I*3vs zbNe;T4R!vfe@Z23CR{ZOzmZnN(qX;K=-Zq#ohMcrD`&o5x!YSV>-_~8wtrFY_0&v~ zvwlrl{d~u!Wi$WrHM6gKX(+;0`;>3z)L)g4k3_^PFy4FnAnfJ2+qSQp-fr%D&&n=l zwd>)tqc6PK@_gzUPnoFsW2<{Dk;WzAXZjiwJ?_{W=AHl8Okm&daE`qpZpv;VU*G6T z=ZNKP_qG|uiJH?V&3bmfyv~!tch)*~7 zd?LEWWAT;f_cn6Nbo{yX&jue`d?q@7@A|qkEYWO{(|*6!-@f{`|7iz~hxhN-#yvaq z|M9nX)307le^k4pD#BLa=WU}?e|GD?zWVlf`_t`T{imD%?3AC75E;Y3_1dvOB(jBX zx_HlX$0?0{3M;3lPWktD_5$i4e@tKQvr6T5fF{Q742gvsFfzw#sYddwl~ zOmDrg?odCsqrO>iOPfpGG`DYeH%#18yY6?_ihV)nrrtWauyEd~u;$4X_6=coUvc*^ zTwtHGS;>>*E8&KMA#kcLJ`lZJ64! zaDMBScLIJwMNQ3fM4yJ59@*dTIM;bnx5dZnQ%io8mNUBO{F#_osPM2L;^}0o2NTbV z3tfN9IG3TGZJlk?tt-cu>E$|Fy*g~)&S$KcRNuw6*=AP<&AhVho=Mj?-LUBwW_g{|E!0iAvU;x6mh*0T8y}+u{y>x%hqNeQR&e>j*OIz4foWc)^=EOVt-w*Im8zjnUC7DBi5O zNMLzbDW{M`xB;u!`K7;HPWy&G)@#r#GE=&zWR9qkh%R-nVPcw`4Z2UmV6bt>Sgbm)UHt6Wz|L&JouU{3$W% z)#=k4L&fB;ckdUI>2vC@Rub3gSJH3n_f}L|Z=t)G=-hLs+The5?Ws34(vRERnCjd9o^6}tUV#IzWuJ3=zU#A}QQOx$`M7r17VAfI z_=KNau1+Z2T^ab=R(5Lh!ps{x+Z&%xxcR~+?|b#3_Ni}g_80G!-5ld%dFS=R8wVfy@HLY`EUHlzA&wOj$Sf==lzUvg`q@R<;k=GiAF2QIdszt=3kq}sEvA20T|EVx=dcaBnG(M{YHGMQ zX!2>_`}G$B^|adjJzc83W{c=v5X-H(&B7SIEO+6yB>_cdxBva*vz(&yR%`Z?q>0Yw z3hv#Xq1N7_w*StBAGJI8R(^~+)e=1Ed5r4q+Cv$Br()DsiMSZe%_%>b`|I+>lIGIc zJ|bG7v&(PapWr)bkVJb2rvc&FF7#`Sh$6x7lW%b`hTY*=CcL zo7chhd-ljwRw@Ru?~$GsHoIr3BTGPK)c1;8mMJT8BAmwr~r-FeI_;#9GJ%8Tjl zMyZ}9nr`!6t@QC^dHmQia^i$+rHqLw6Dp?kp6mPmmuCkP$=q#qFx z)2d;0EY(%wJm>ZJ4LxU5SX-AF`Q#ZNoB61FPDIQJi7AUGERAo-W##%MJSlvN(c2#B zS6X7yZ(bj3XW+W_ZDHDkSDO#jYk$AM`}W|>cM`^Tf_pdbm{GL$d-c?N&T6+qCv$T& z)f{V7O)Tkhy1V#CaP7MG30f;A`Jd>?_R2Untx|GRc)&cX%QA;1EiF;KaluCA%ew3> zPs3fLwRZT_AMx)ApZLT@d=bwvN9U$vY94$(jjiidJ9I)Ooz?qV8tl4sy`iP;f_K%I z`7bWWw*0-;QZ_1_|9Ek~xVA9=JEwiFjo%AWH}G2d7#}*F^m2Xe>kSMS3zObuFJRMe zTjVuEMe0`h13k&2{}=fhyP0=?taAF#=X-H-&GaM6-Ri%;J$e*qen9*GBW<11jn11& zHU-#hy6`@BO0u4Fwb=uWVyi^$v(HZTE(^5_?9a{LyC>#13xE6-cCpjbUTS^|e!lp1 zZpYs{F0~IX%yBrlB1q&yYg6^sy*~>cb5B(hsAc42oG&9Jd1;Z={X6>>pX58Ypj~L; z=_ht~Y}94`yg2=T%ATD+xdTh*X*e;MWbsboTI6~pB%ol1mDdGEt=ud5f68PvUft4} z)+rG1=c1|MQ!DniNS=>Zxu?r%E_|gRTvoP0bP3bU4bpdXQqCzeR3B8XaAt0jFj{xX zyxI8c!ySS*oEeVQx4GS~=Q~<^@yW$q@due+7G7mt@zwi&y-LE$TJM<*xf8M;xjufE zRdLStL78NL|4dQe3D2D0i~s&sl2zOCp7{oQ=J%~XvfDK2>F>Y%{;^hJP4!cczs#uS zQA{mV+wj+GeK0FelJKn=TaW3Sdim$o%QDw#0WMh|b-cPbfB0;6zWZw-?+xYxxoi`S zJMn(ZLa)=dx^o|TYR^qgh?nXRPMZti#Y3?GfN zGIO>n$27Jl{)&8Z*;ZwazL2DDo2x^72z%M;S0W6rE$ff%pY%a#{>(L>l6;sZSe`D4 zpSNsPj(Jb|$Gf{;>K&f7duqcUt$AmK*Qz)0OEe@szQVxYcR}XG?jLbA@@)@Z=y5)X zezA17*bNc)mmA_*D@5Do=QmbtZuqfVwBz{_7PtO;uQm(lceeCRJFB<0?1B&Xp(%BD z+$-NK*6%GYli2rcet?9{g#V|Gb{##z5S_!cbo-@z{%srAtt&8gf3kee=N?8z!8eC( zf0zrd-q!FgY`wxQ5qrDeZkn0U$8+bx#N31KeCIeTX7YMM z)7l&VTk2>2^E)z6d%C=q(w`%j>SK4?$<5k&@2Ev$)jYGG!Sl17)(6-9F)r;a)l-m) zS-q6~T-;Lc3h{=oe7XmDEqMPLKP!F1`FW+9X0Pq)w9!2HJM z#VmP&zCaPzdktDMQpA4emdRhZ;9tye=v4n#=U?4Q5(nP++O7{TQ#-wOeoKx+8&_-M z>t{#a-Pp2HU~%H+xVve5Igw^RJYOwab^A(Hz_Rkvuw~}9&p0M_aNm4Tdm!Z9tR8{5 z{GI$QUmjP!-B8_}Ak;d=O#M-;OXG?hLB-#5IREQ#%#5FM?Yjm4icj{prbo^WV7Rn1 z%!8Bhrn*Mca>kd-rUySNTI}v>_dmmZd*SAY8_$o-@p|hWq%*CQwX$gWq!3}|rac)4 zA79dQGJCz`RM(xkJ$DuKw=Cz6EqH7CZrAQD-cPq^h~HX}cE>sF?yZSyWgh?AGUL2% z(zNpd?VZ_fTze))=Ca>gv3c^-Py>OGAKg!H{FqaBfa$RJ?gA0{?bg>OPu_Qu<=mv{ zyRWLqEIB$iF_X7n$C#D<`txF2A+yX({&*2*FSqI+LQ0}rYfct%@0oMlGpoHjfq}Jo zj#liFMfX{bKa7iQ-C_FBi}A!Zky}wSne4aBO?9Yoo-AjX*mLbwjgN2BMLSc+wqI9S zO2TzBHg%s6Y-V0NtE!3Ja+2*!)^)8NpL0DkA6;F2DyT4N)9Z>%uMKKipHExN-)Z_r z=E2-O40=zcJ0I@7>D+W;>-+?RFZ;LhhZ|;m)d z2VHE~z@e!oCmcNIX_WhS*RsW?7ll7gySMzE*P*%EoF_YSp5A%c%c1(mZDy~;WVb0_ zPy6{#lzwNZWWbRddVY18a4N@}8Mf-~VoIksYjr=rIe%qsf4_R!0_nwd_m*fEr_PvO zefGlDH189$e6Acn#${5nO|)zC6bt5^hohE;rY|(~5OCr@H@khu$&$^lqBbA?HP`ZW zEA!khUvDfHu8z03?<2PDl7aVa3p1tCx9^tlo6Noy8e8{w^U7_->$gR{l}K7Uz3TeH zbCbV@d_G!mY){?Ob1{45jy#Gy;IMbFz=hy#ywa#Q| zUP$$fny{4%A9@`9K3&TB%7=+RT7qWB%*b#5U)=lj{`DQvkM>k-VE*ozc&uLK{+3+F zdX^pMKJa(myt3`(fp%YSw#52*3pis+v+AerZ20}wv&l^E-|f(8@eU{NYUv+XoU?NO zU3=G4Z+?ohAC3;Ho44#?{GyH{|FVLAbR63=`}O|~w;pwe|DJ4;%d}nf-p^^$eSH6z zICB1*Vk^naF~>uU3`~eV?(1ws?)ux?L_w#(utq4d8!C5Aaas7f-DJ1sCexDzj~8f9 zd+W3&*Uh(ktL~MbuC2JF zy!!L=@A}u)-`f}YulVoubp5L?vjv)t8a3|ikrP~WLizqXzUbe=52rrp`nfP_O_Ky0 z>)MmwPKQdg++(-@@-h7NveVI0zuV-FzFc>0ci!s4f2-dHOa0Bd{9n^*#)BV=8|`nD zuK!>5{oDHU^(Ml{O7zs9u?VIs_E+Eju41&^VuE7uhx((I-iIcr_?L!ltKRbTqi<}u zX>OX%nN!RxlMYY$e*D?T;E1E!Zy?=ky{k=8+Uj6>Q-8|mULpZYYXZF}avx1Y9LElaiwm0-~c+_b)HipwL{BaFJvcBu|OlX07!&Dfx2ianrCs++Zm+#&?WU#ZBcQ9exPfU+&9sJlQyboi*Dx??#P{tDp6Y#Y@3#QaUHjN; z3t!w#>RkNKTiWn4WA}ocy>cu7cLa<=Z1?rSE?w%X#gv znaX_mRaV*ktb5;Wd>Ei(8hz*T3f}j9_kLxRSF*jG@#D^KyWgBkOXH_q-t^0C?LrgA zq7;?%+3qPiJ@c~u-rlC=7d!h~@ulpjS|!cLvm*Z#ProYhajMWMF(tnX!dG$wz2}*_ z?=7DBiSy5rJ6n(2Ef1X+p7C3qSuePzmLc6xeA34g+n5`!GAwoty*1~K>4jc(7g-58 zmw8M4*>A>{o%r?ek%_{k=fB@S4dUeAtm1Oxw_s)a8|74nOL3R(%rFs|p>p=>^oZU2 ztX`j9smZlV_r>$}T*czeM;_idp33oba(P(G1tyozC9BI*qQZ9NbR>!K&W)NQ^RU5y zhbe&7h-U%U7T2PA8yFTmhNFddf$>M z7r;~UxT8YCnDs`9?#m>eim*v`lRbV}i-kT7kZ12Xy>J`91x=@I{kHlXN1I`d0a&|c(&;N@o_nHQMF)Sc9c|M`O}&+ zueR7^NPU()Uc%xYW5e>HS>9v%b-NF1GE5{D;w$SH9e?(zrnT6mv3>Gk;~iguj3m$V zMYzQ=uI5eU@H@EhRr|Zc9x5l-ycKfIWj|k=)wgt7U&yeAgP*h|Y>9e;tlm=zZKf z_ule0>&I2i?@jV}KP&F_ojom@x0d^&q`1`Huq6wh7MK^v1}r-t$a2PMfwoeW!y-~ZHlvBTnHU46T*ZSF8E>?!UnwQPXb7arE=-BU1w71Uk zU$%W!k5})i!V_PXNX%ER{GfQQH8ya&OG=c~db8ejoX$FzKWJ+HSn~EoyuF#K&WByf z2QHUgW0`t{=V#dk|EUJ`d)O=mRYMN{5f_eRpOtjt!P7P0%wu0O@h-Ta9JFkEn2S#X z)1g@m$}<`cu;2f#�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 P%q>g|xl~nM{oS|#IMbe+ literal 0 HcmV?d00001 diff --git a/lib/hcrypto/libtommath/bn.tex b/lib/hcrypto/libtommath/doc/bn.tex similarity index 56% rename from lib/hcrypto/libtommath/bn.tex rename to lib/hcrypto/libtommath/doc/bn.tex index 9017860e7..5937feef1 100644 --- a/lib/hcrypto/libtommath/bn.tex +++ b/lib/hcrypto/libtommath/doc/bn.tex @@ -6,6 +6,7 @@ \usepackage{alltt} \usepackage{graphicx} \usepackage{layout} +\usepackage{appendix} \def\union{\cup} \def\intersect{\cap} \def\getsrandom{\stackrel{\rm R}{\gets}} @@ -49,10 +50,10 @@ \begin{document} \frontmatter \pagestyle{empty} -\title{LibTomMath User Manual \\ v0.41} -\author{Tom St Denis \\ tomstdenis@gmail.com} +\title{LibTomMath User Manual \\ v1.2.0} +\author{LibTom Projects \\ www.libtom.net} \maketitle -This text, the library and the accompanying textbook are all hereby placed in the public domain. This book has been +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} @@ -60,6 +61,9 @@ formatted for B5 [176x250] paper using the \LaTeX{} {\em book} macro package. \begin{flushright}Open Source. Open Academia. Open Minds. \mbox{ } +LibTom Projects + +\& originally Tom St Denis, @@ -74,12 +78,12 @@ Ontario, Canada \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. +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 +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. +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 @@ -87,14 +91,27 @@ release the textbook ``Implementing Multiple Precision Arithmetic'' has been pla 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 +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. +developer. Please consider to commit such a makefile to the LibTomMath developers, currently residing at +\url{http://github.com/libtom/libtommath}, if successfully done so. + +Intel's C-compiler (ICC) is sufficiently compatible with GCC, at least the newer versions, to replace GCC for building the static and the shared library. Editing the makefiles is not needed, just set the shell variable \texttt{CC} as shown below. +\begin{alltt} +CC=/home/czurnieden/intel/bin/icc make +\end{alltt} + +ICC does not know all options available for GCC and LibTomMath uses two diagnostics \texttt{-Wbad-function-cast} and \texttt{-Wcast-align} that are not supported by ICC resulting in the warnings: +\begin{alltt} +icc: command line warning #10148: option '-Wbad-function-cast' not supported +icc: command line warning #10148: option '-Wcast-align' not supported +\end{alltt} +It is possible to mute this ICC warning with the compiler flag \texttt{-diag-disable=10148}\footnote{It is not recommended to suppress warnings without a very good reason but there is no harm in doing so in this very special case.}. \subsection{Static Libraries} To build as a static library for GCC issue the following @@ -102,28 +119,102 @@ To build as a static library for GCC issue the following make \end{alltt} -command. This will build the library and archive the object files in ``libtommath.a''. Now you link against +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. +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. + +To run a program to adapt the Toom-Cook cut-off values to your architecture type +\begin{alltt} +make tune +\end{alltt} +This will take some time. \subsection{Shared Libraries} +\subsubsection{GNU based Operating Systems} 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. +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 +To run a program to adapt the Toom-Cook cut-off values to your architecture type +\begin{alltt} +make -f makefile.shared tune +\end{alltt} +This will take some time. + +\subsubsection{Microsoft Windows based Operating Systems} +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. +\subsubsection{OpenBSD} +OpenBSD replaced some of their GNU-tools, especially \texttt{libtool} with their own, slightly different versions. To ease the workload of LibTomMath's developer team, only a static library can be build with the included \texttt{makefile.unix}. + +The wrong \texttt{make} will result in errors like: +\begin{alltt} +*** Parse error in /home/user/GITHUB/libtommath: Need an operator in 'LIBNAME' ) +*** Parse error: Need an operator in 'endif' (makefile.shared:8) +*** Parse error: Need an operator in 'CROSS_COMPILE' (makefile_include.mk:16) +*** Parse error: Need an operator in 'endif' (makefile_include.mk:18) +*** Parse error: Missing dependency operator (makefile_include.mk:22) +*** Parse error: Missing dependency operator (makefile_include.mk:23) +... +\end{alltt} +The wrong \texttt{libtool} will build it all fine but when it comes to the final linking fails with +\begin{alltt} +... +cc -I./ -Wall -Wsign-compare -Wextra -Wshadow -Wsystem-headers -Wdeclaration-afo... +cc -I./ -Wall -Wsign-compare -Wextra -Wshadow -Wsystem-headers -Wdeclaration-afo... +cc -I./ -Wall -Wsign-compare -Wextra -Wshadow -Wsystem-headers -Wdeclaration-afo... +libtool --mode=link --tag=CC cc bn_error.lo bn_s_mp_invmod_fast.lo bn_fast_mp_mo +libtool: link: cc bn_error.lo bn_s_mp_invmod_fast.lo bn_s_mp_montgomery_reduce_fast0 +bn_error.lo: file not recognized: File format not recognized +cc: error: linker command failed with exit code 1 (use -v to see invocation) +Error while executing cc bn_error.lo bn_s_mp_invmod_fast.lo bn_fast_mp_montgomery0 +gmake: *** [makefile.shared:64: libtommath.la] Error 1 +\end{alltt} + +To build a shared library with OpenBSD\footnote{Tested with OpenBSD version 6.4} the GNU versions of \texttt{make} and \texttt{libtool} are needed. +\begin{alltt} +$ sudo pkg_add gmake libtool +\end{alltt} +At this time two versions of \texttt{libtool} are installed and both are named \texttt{libtool}, unfortunately but GNU \texttt{libtool} has been placed in \texttt{/usr/local/bin/} and the native version in \texttt{/usr/bin/}. The path might be different in other versions of OpenBSD but both programms differ in the output of \texttt{libtool --version} +\begin{alltt} +$ /usr/local/bin/libtool --version +libtool (GNU libtool) 2.4.2 +Written by Gordon Matzigkeit , 1996 + +Copyright (C) 2011 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +$ libtool --version +libtool (not (GNU libtool)) 1.5.26 +\end{alltt} + +The shared library should build now with +\begin{alltt} +LIBTOOL="/usr/local/bin/libtool" gmake -f makefile.shared +\end{alltt} +You might need to run a \texttt{gmake -f makefile.shared clean} first. + +\subsubsection{NetBSD} +NetBSD is not as strict as OpenBSD but still needs \texttt{gmake} to build the shared library. \texttt{libtool} may also not exist in a fresh install. +\begin{alltt} +pkg_add gmake libtool +\end{alltt} +Please check with \texttt{libtool --version} that installed libtool is indeed a GNU libtool. +Build the shared library by typing: +\begin{alltt} +gmake -f makefile.shared +\end{alltt} \subsection{Testing} To build the library and the test harness type @@ -140,7 +231,7 @@ is included in the package}. Simply pipe mtest into test using 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 +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} @@ -149,20 +240,20 @@ myprng | mtest/mtest | test 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. +will exit with a dump of the relevant 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. +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 +``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 +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} @@ -172,8 +263,8 @@ file. For instance, BN\_MP\_ADD\_C represents the file ``bn\_mp\_add.c''. When 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. +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} @@ -193,7 +284,7 @@ They can be enabled at any pass of the configuration phase. \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. +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. @@ -232,7 +323,7 @@ only if LTM\_LAST has been defined. & 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\_MUL\_C \\ & BN\_MP\_TOOM\_SQR\_C \\ \hline @@ -242,11 +333,11 @@ only if LTM\_LAST has been defined. \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 +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. +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 @@ -258,7 +349,7 @@ 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] +\newpage\begin{figure}[h] \begin{small} \begin{center} \begin{tabular}{|l|c|c|l|} @@ -277,9 +368,9 @@ are the pros and cons of LibTomMath by comparing it to the math routines from Gn \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. +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. +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 @@ -288,19 +379,19 @@ exponentiations. It depends largely on the processor, compiler and the moduli b 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). +that is very flexible, complete and performs well in resource constrained 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 +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{figure}[h!] \begin{center} \begin{small} \begin{tabular}{|l|l|} @@ -327,8 +418,8 @@ to a string use the following function. 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. +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 @@ -345,7 +436,7 @@ typedef struct \{ 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. +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 @@ -374,7 +465,7 @@ 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. +A single mp\_int can be initialized with the ``mp\_init'' function. \index{mp\_init} \begin{alltt} @@ -392,11 +483,11 @@ int main(void) int result; if ((result = mp_init(&number)) != MP_OKAY) \{ - printf("Error initializing the number. \%s", + printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} - + /* use the number */ return EXIT_SUCCESS; @@ -404,7 +495,7 @@ int main(void) \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 +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} @@ -412,9 +503,9 @@ provides this functionality. 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. +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) @@ -423,11 +514,11 @@ int main(void) int result; if ((result = mp_init(&number)) != MP_OKAY) \{ - printf("Error initializing the number. \%s", + printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} - + /* use the number */ /* We're done with it. */ @@ -451,8 +542,8 @@ int mp_init_multi(mp_int *mp, ...); 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. +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) @@ -460,14 +551,14 @@ int main(void) mp_int num1, num2, num3; int result; - if ((result = mp_init_multi(&num1, + if ((result = mp_init_multi(&num1, &num2, - &num3, NULL)) != MP\_OKAY) \{ - printf("Error initializing the numbers. \%s", + &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. */ @@ -478,7 +569,7 @@ int main(void) \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. +To initialized and make a copy of an mp\_int the mp\_init\_copy() function has been provided. \index{mp\_init\_copy} \begin{alltt} @@ -497,11 +588,11 @@ int main(void) /* We want a copy of num1 in num2 now */ if ((result = mp_init_copy(&num2, &num1)) != MP_OKAY) \{ - printf("Error initializing the copy. \%s", + 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. */ @@ -521,7 +612,7 @@ 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). +to have $size$ digits (which are all initially zero). \begin{small} \begin{alltt} int main(void) @@ -531,11 +622,11 @@ int main(void) /* we need a 60-digit number */ if ((result = mp_init_size(&number, 60)) != MP_OKAY) \{ - printf("Error initializing the number. \%s", + printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} - + /* use the number */ return EXIT_SUCCESS; @@ -543,6 +634,25 @@ int main(void) \end{alltt} \end{small} \section{Maintenance Functions} +\subsection{Clear Leading Zeros} + +This is used to ensure that leading zero digits are trimed and the leading "used" digit will be non-zero. +It also fixes the sign if there are no more leading digits. + +\index{mp\_clamp} +\begin{alltt} +void mp_clamp(mp_int *a); +\end{alltt} + +\subsection{Zero Out} + +This function will set the ``bigint'' to zeros without changing the amount of allocated memory. + +\index{mp\_zero} +\begin{alltt} +void mp_zero(mp_int *a); +\end{alltt} + \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 @@ -556,7 +666,7 @@ int mp_shrink (mp_int * a); 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). +modify in the system (unless you are seriously low on memory). \begin{small} \begin{alltt} int main(void) @@ -565,16 +675,16 @@ int main(void) int result; if ((result = mp_init(&number)) != MP_OKAY) \{ - printf("Error initializing the number. \%s", + 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", + printf("Error shrinking the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} @@ -582,7 +692,7 @@ int main(void) /* use it .... */ - /* we're done with it. */ + /* we're done with it. */ mp_clear(&number); return EXIT_SUCCESS; @@ -595,7 +705,7 @@ Within the mp\_int structure are two parameters which control the limitations of 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. +your desired size. \index{mp\_grow} \begin{alltt} @@ -612,16 +722,16 @@ int main(void) int result; if ((result = mp_init(&number)) != MP_OKAY) \{ - printf("Error initializing the number. \%s", + 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", + printf("Error growing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} @@ -629,7 +739,7 @@ int main(void) /* use the number */ - /* we're done with it. */ + /* we're done with it. */ mp_clear(&number); return EXIT_SUCCESS; @@ -637,11 +747,44 @@ int main(void) \end{alltt} \end{small} \chapter{Basic Operations} +\section{Copying} + +A so called ``deep copy'', where new memory is allocated and all contents of $a$ are copied verbatim into $b$ such that $b = a$ at the end. + +\index{mp\_copy} +\begin{alltt} +int mp_copy (mp_int * a, mp_int *b); +\end{alltt} + +You can also just swap $a$ and $b$. It does the normal pointer changing with a temporary pointer variable, just that you do not have to. + +\index{mp\_exch} +\begin{alltt} +void mp_exch (mp_int * a, mp_int *b); +\end{alltt} + +\section{Bit Counting} + +To get the position of the lowest bit set (LSB, the Lowest Significant Bit; the number of bits which are zero before the first zero bit ) + +\index{mp\_cnt\_lsb} +\begin{alltt} +int mp_cnt_lsb(const mp_int *a); +\end{alltt} + +To get the position of the highest bit set (MSB, the Most Significant Bit; the number of bits in teh ``bignum'') + +\index{mp\_count\_bits} +\begin{alltt} +int mp_count_bits(const mp_int *a); +\end{alltt} + + \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$). +Setting mp\_ints to small constants is a relatively common operation. To accommodate these instances there is a +small constant assignment function. This function is used to set a single digit constant. +The reason for this function 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} @@ -663,43 +806,50 @@ int main(void) int result; if ((result = mp_init(&number)) != MP_OKAY) \{ - printf("Error initializing the number. \%s", + 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. */ + /* we're done with it. */ mp_clear(&number); return EXIT_SUCCESS; \} \end{alltt} \end{small} -\subsection{Long Constants} +\subsection{Int32 and Int64 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. +These functions can be used to set a constant with 32 or 64 bits. -\index{mp\_set\_int} +\index{mp\_set\_i32} \index{mp\_set\_u32} +\index{mp\_set\_i64} \index{mp\_set\_u64} \begin{alltt} -int mp_set_int (mp_int * a, unsigned long b); +void mp_set_i32 (mp_int * a, int32_t b); +void mp_set_u32 (mp_int * a, uint32_t b); +void mp_set_i64 (mp_int * a, int64_t b); +void mp_set_u64 (mp_int * a, uint64_t 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. +These functions assign the sign and value of the input \texttt{b} to \texttt{mp\_int a}. +The value can be obtained again by calling the following functions. -To get the ``unsigned long'' copy of an mp\_int the following function can be used. - -\index{mp\_get\_int} +\index{mp\_get\_i32} \index{mp\_get\_u32} \index{mp\_get\_mag\_u32} +\index{mp\_get\_i64} \index{mp\_get\_u64} \index{mp\_get\_mag\_u64} \begin{alltt} -unsigned long mp_get_int (mp_int * a); +int32_t mp_get_i32 (mp_int * a); +uint32_t mp_get_u32 (mp_int * a); +uint32_t mp_get_mag_u32 (mp_int * a); +int64_t mp_get_i64 (mp_int * a); +uint64_t mp_get_u64 (mp_int * a); +uint64_t mp_get_mag_u64 (mp_int * a); \end{alltt} -This will return the 32 least significant bits of the mp\_int $a$. +These functions return the 32 or 64 least significant bits of $a$ respectively. The unsigned functions +return negative values in a twos complement representation. The absolute value or magnitude can be obtained using the mp\_get\_mag functions. \begin{small} \begin{alltt} int main(void) @@ -708,21 +858,17 @@ int main(void) int result; if ((result = mp_init(&number)) != MP_OKAY) \{ - printf("Error initializing the number. \%s", + 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; - \} + mp_set_u32(&number, 654321); - printf("number == \%lu", mp_get_int(&number)); + printf("number == \%" PRIi32, mp_get_i32(&number)); - /* we're done with it. */ + /* we're done with it. */ mp_clear(&number); return EXIT_SUCCESS; @@ -735,15 +881,66 @@ This should output the following if the program succeeds. number == 654321 \end{alltt} +\subsection{Long Constants - platform dependant} + +\index{mp\_set\_l} \index{mp\_set\_ul} +\begin{alltt} +void mp_set_l (mp_int * a, long b); +void mp_set_ul (mp_int * a, unsigned long b); +\end{alltt} + +This will assign the value of the platform-dependent sized variable $b$ to the mp\_int $a$. + +To retrieve the value, the following functions can be used. + +\index{mp\_get\_l} \index{mp\_get\_ul} \index{mp\_get\_mag\_ul} +\begin{alltt} +long mp_get_l (mp_int * a); +unsigned long mp_get_ul (mp_int * a); +unsigned long mp_get_mag_ul (mp_int * a); +\end{alltt} + +This will return the least significant bits of the mp\_int $a$ that fit into a ``long''. + +\subsection{Long Long Constants - platform dependant} + +\index{mp\_set\_ll} \index{mp\_set\_ull} +\begin{alltt} +void mp_set_ll (mp_int * a, long long b); +void mp_set_ull (mp_int * a, unsigned long long b); +\end{alltt} + +This will assign the value of the platform-dependent sized variable $b$ to the mp\_int $a$. + +To retrieve the value, the following functions can be used. + +\index{mp\_get\_ll} +\index{mp\_get\_ull} +\index{mp\_get\_mag\_ull} +\begin{alltt} +long long mp_get_ll (mp_int * a); +unsigned long long mp_get_ull (mp_int * a); +unsigned long long mp_get_mag_ull (mp_int * a); +\end{alltt} + +This will return the least significant bits of the mp\_int $a$ that fit into a ``long long''. + \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); +int mp_init_i32 (mp_int * a, int32_t b); +int mp_init_u32 (mp_int * a, uint32_t b); +int mp_init_i64 (mp_int * a, int64_t b); +int mp_init_u64 (mp_int * a, uint64_t b); +int mp_init_l (mp_int * a, long b); +int mp_init_ul (mp_int * a, unsigned long b); +int mp_init_ll (mp_int * a, long long b); +int mp_init_ull (mp_int * a, unsigned long long b); \end{alltt} -Both functions work like the previous counterparts except they first mp\_init $a$ before setting the values. +Both functions work like the previous counterparts except they first mp\_init $a$ before setting the values. \begin{alltt} int main(void) @@ -753,21 +950,21 @@ int main(void) /* initialize and set a single digit */ if ((result = mp_init_set(&number1, 100)) != MP_OKAY) \{ - printf("Error setting number1: \%s", + 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", + if ((result = mp_init_l(&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)); + printf("Number1, Number2 == \%" PRIi32 ", \%" PRIi32, + mp_get_i32(&number1), mp_get_i32(&number2)); /* clear */ mp_clear_multi(&number1, &number2, NULL); @@ -787,7 +984,7 @@ Comparisons in LibTomMath are always performed in a ``left to right'' fashion. for any comparison. \index{MP\_GT} \index{MP\_EQ} \index{MP\_LT} -\begin{figure}[here] +\begin{figure}[h] \begin{center} \begin{tabular}{|c|c|} \hline \textbf{Result Code} & \textbf{Meaning} \\ @@ -801,14 +998,14 @@ for any comparison. \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$. +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 +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. +mp\_int variables based on their digits only. \index{mp\_cmp\_mag} \begin{alltt} @@ -824,18 +1021,18 @@ int main(void) int result; if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{ - printf("Error initializing the numbers. \%s", + 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", + printf("Error negating number2. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} @@ -846,14 +1043,14 @@ int main(void) case MP_LT: printf("|number1| < |number2|"); break; \} - /* we're done with it. */ + /* 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 +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} @@ -882,18 +1079,18 @@ int main(void) int result; if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{ - printf("Error initializing the numbers. \%s", + 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", + printf("Error negating number2. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} @@ -904,14 +1101,14 @@ int main(void) case MP_LT: printf("number1 < number2"); break; \} - /* we're done with it. */ + /* 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 +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} @@ -927,7 +1124,7 @@ To compare a single digit against an mp\_int the following function has been pro 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 +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}. @@ -940,11 +1137,11 @@ int main(void) int result; if ((result = mp_init(&number)) != MP_OKAY) \{ - printf("Error initializing the number. \%s", + printf("Error initializing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} - + /* set the number to 5 */ mp_set(&number, 5); @@ -954,7 +1151,7 @@ int main(void) case MP_LT: printf("number < 7"); break; \} - /* we're done with it. */ + /* we're done with it. */ mp_clear(&number); return EXIT_SUCCESS; @@ -975,7 +1172,7 @@ 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. +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} @@ -994,17 +1191,17 @@ int main(void) int result; if ((result = mp_init(&number)) != MP_OKAY) \{ - printf("Error initializing the number. \%s", + 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", + printf("Error multiplying the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} @@ -1016,7 +1213,7 @@ int main(void) /* now divide by two */ if ((result = mp\_div\_2(&number, &number)) != MP_OKAY) \{ - printf("Error dividing the number. \%s", + printf("Error dividing the number. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} @@ -1026,7 +1223,7 @@ int main(void) case MP_LT: printf("2*number/2 < 7"); break; \} - /* we're done with it. */ + /* we're done with it. */ mp_clear(&number); return EXIT_SUCCESS; @@ -1040,15 +1237,18 @@ If this program is successful it will print out the following text. 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. +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. +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. The multiplication itself +is implemented as a right-shift operation of $a$ by $b$ bits. To divide by a power of two use the following. @@ -1058,14 +1258,23 @@ 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. +value to signal that the remainder is not desired. The division itself is implemented as a left-shift +operation of $a$ by $b$ bits. + +It is also not very uncommon to need just the power of two $2^b$; for example the startvalue for the Newton method. + +\index{mp\_2expt} +\begin{alltt} +int mp_2expt(mp_int *a, int b); +\end{alltt} +It is faster than doing it by shifting $1$ with \texttt{mp\_mul\_2d}. \subsection{Polynomial Basis Operations} -Strictly speaking the organization of the integers within the mp\_int structures is what is known as a +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$. +$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. @@ -1085,19 +1294,31 @@ void mp_rshd (mp_int * a, int b) 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} +\subsection{AND, OR, XOR and COMPLEMENT 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. +While AND, OR and XOR operations compute arbitrary-precision bitwise operations. Negative numbers +are treated as if they are in two-complement representation, while internally they are sign-magnitude however. -\index{mp\_or} \index{mp\_and} \index{mp\_xor} +\index{mp\_or} \index{mp\_and} \index{mp\_xor} \index{mp\_complement} \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); +int mp_complement(const mp_int *a, mp_int *b); +int mp_signed_rsh(mp_int * a, int b, mp_int * c, mp_int * d); \end{alltt} -Which compute $c = a \odot b$ where $\odot$ is one of OR, AND or XOR. +The function \texttt{mp\_complement} computes a two-complement $b = \sim a$. The function \texttt{mp\_signed\_rsh} performs +sign extending right shift. For positive numbers it is equivalent to \texttt{mp\_div\_2d}. + +\subsection{Bit Picking} +\index{mp\_get\_bit} +\begin{alltt} +int mp_get_bit(mp_int *a, int b) +\end{alltt} + +Pick a bit: returns \texttt{MP\_YES} if the bit at position $b$ (0-index) is set, that is if it is 1 (one), \texttt{MP\_NO} +if the bit is 0 (zero) and \texttt{MP\_VAL} if $b < 0$. \section{Addition and Subtraction} @@ -1122,17 +1343,17 @@ Simple integer negation can be performed with the following. int mp_neg (mp_int * a, mp_int * b); \end{alltt} -Which assigns $-a$ to $b$. +Which assigns $-a$ to $b$. \subsection{Absolute} Simple integer absolutes can be performed with the following. -\index{mp\_neg} +\index{mp\_abs} \begin{alltt} int mp_abs (mp_int * a, mp_int * b); \end{alltt} -Which assigns $\vert a \vert$ to $b$. +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. @@ -1141,10 +1362,10 @@ To perform a complete and general integer division with remainder use the follow \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}. + +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} @@ -1154,13 +1375,13 @@ A full signed integer multiplication can be performed with the following. \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 +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. +will determine on its own\footnote{Some tweaking may be required but \texttt{make tune} will put some reasonable values in \texttt{bncore.c}} what routine to use automatically when it is called. \begin{alltt} int main(void) @@ -1169,43 +1390,34 @@ int main(void) int result; /* Initialize the numbers */ - if ((result = mp_init_multi(&number1, + if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{ - printf("Error initializing the numbers. \%s", + 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; - \} + mp_set_i32(&number, 257); + mp_set_i32(&number2, 1023); /* multiply them */ if ((result = mp_mul(&number1, &number2, &number1)) != MP_OKAY) \{ - printf("Error multiplying terms. \%s", + printf("Error multiplying terms. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} /* display */ - printf("number1 * number2 == \%lu", mp_get_int(&number1)); + printf("number1 * number2 == \%" PRIi32, mp_get_i32(&number1)); /* free terms and return */ mp_clear_multi(&number1, &number2, NULL); return EXIT_SUCCESS; \} -\end{alltt} +\end{alltt} If this program succeeds it shall output the following. @@ -1224,68 +1436,51 @@ int mp_sqr (mp_int * a, mp_int * b); 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. +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 +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 +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 +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 +To get reasonable values for the cut-off points for your architecture, type \begin{alltt} -make XXX +make tune \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} +This will run a benchmark, computes the medians, rewrites \texttt{bncore.c}, and recompiles \texttt{bncore.c} and relinks the library. -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. +The benchmark itself can be fine-tuned in the file \texttt{etc/tune\_it.sh}. + +The program \texttt{etc/tune} is also able to print a list of values for printing curves with e.g.: \texttt{gnuplot}. type \texttt{./etc/tune -h} to get a list of all available options. \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$. +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. +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. +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. @@ -1295,7 +1490,7 @@ In order to effect an arbitrary modular reduction the following algorithm is pro 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 +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} @@ -1325,52 +1520,52 @@ 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 + /* 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", + 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", + 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", + 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", + 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", + printf("Error reducing. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} - + /* c now equals a^3 mod b */ return EXIT_SUCCESS; \} -\end{alltt} +\end{alltt} -This program will calculate $a^3 \mbox{ mod }b$ if all the functions succeed. +This program will calculate $a^3 \mbox{ mod }b$ if all the functions succeed. \section{Montgomery Reduction} @@ -1382,7 +1577,7 @@ step is required. This is accomplished with the following. 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 +For the given odd moduli $a$ the precomputation value is placed in $mp$. The reduction is computed with the following. \index{mp\_montgomery\_reduce} @@ -1394,10 +1589,10 @@ $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. +$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}$). +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. @@ -1405,7 +1600,7 @@ To quickly calculate $R$ the following function was provided. \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. +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 @@ -1418,62 +1613,62 @@ int main(void) mp_digit mp; int result; - /* initialize a,b to desired values, - * mp_init R, c and set c to 1.... + /* 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", + 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", + 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", + 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", + 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", + 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", + 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", + 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", + printf("Error reducing. \%s", mp_error_to_string(result)); return EXIT_FAILURE; \} @@ -1482,19 +1677,19 @@ int main(void) return EXIT_SUCCESS; \} -\end{alltt} +\end{alltt} -This particular example does not look too efficient but it demonstrates the point of the algorithm. By +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} +\section{Restricted Diminished Radix} -``Dimminished Radix'' reduction refers to reduction with respect to moduli that are ameniable to simple +``Diminished Radix'' reduction refers to reduction with respect to moduli that are amenable 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}$). +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. @@ -1513,36 +1708,63 @@ 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. +diminished radix form and $a$ must be in the range $0 \le a < b^2$. Diminished radix reductions are +much faster than both Barrett and Montgomery reductions as they have a much lower asymptotic 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. +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} +\section{Unrestricted Diminished 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. +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$. +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. +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. + +\section{Combined Modular Reduction} + +Some of the combinations of an arithmetic operations followed by a modular reduction can be done in a faster way. The ones implemented are: + +Addition $d = (a + b) \mod c$ +\index{mp\_addmod} +\begin{alltt} +int mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); +\end{alltt} + +Subtraction $d = (a - b) \mod c$ +\begin{alltt} +int mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); +\end{alltt} + +Multiplication $d = (ab) \mod c$ +\begin{alltt} +int mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); +\end{alltt} + +Squaring $d = (a^2) \mod c$ +\begin{alltt} +int mp_sqrmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); +\end{alltt} + + \chapter{Exponentiation} \section{Single Digit Exponentiation} @@ -1550,8 +1772,7 @@ slower than mp\_dr\_reduce but faster for most moduli sizes than the Montgomery \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. +This function computes $c = a^b$. \section{Modular Exponentiation} \index{mp\_exptmod} @@ -1559,31 +1780,105 @@ $a$ for all values of $b$ greater than three. 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 +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 +detect when Barrett, Montgomery, Restricted and Unrestricted Diminished Radix based exponentiation can be used. Generally +moduli of the a ``restricted diminished radix'' form lead to the fastest modular exponentiations. Followed by Montgomery and the other two algorithms. +\section{Modulus a Power of Two} +\index{mp\_mod\_2d} +\begin{alltt} +int mp_mod_2d(const mp_int *a, int b, mp_int *c) +\end{alltt} +It calculates $c = a \mod 2^b$. + \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 computes $c = a^{1/b}$ such that $c^b \le a$ and $(c+1)^b > a$. 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. + +The square root $c = a^{1/2}$ (with the same conditions $c^2 \le a$ and $(c+1)^2 > a$) is implemented with a faster algorithm. + +\index{mp\_sqrt} +\begin{alltt} +int mp_sqrt (mp_int * a, mp_digit b, mp_int * c) +\end{alltt} + + +\chapter{Logarithm} +\section{Integer Logarithm} +A logarithm function for positive integer input \texttt{a, base} computing $\floor{\log_bx}$ such that $(\log_b x)^b \le x$. +\index{mp\_ilogb} +\begin{alltt} +int mp_ilogb(mp_int *a, mp_digit base, mp_int *c) +\end{alltt} +\subsection{Example} +\begin{alltt} +#include +#include +#include + +#include + +int main(int argc, char **argv) +{ + mp_int x, output; + mp_digit base; + int e; + + if (argc != 3) { + fprintf(stderr,"Usage %s base x\textbackslash{}n", argv[0]); + exit(EXIT_FAILURE); + } + if ((e = mp_init_multi(&x, &output, NULL)) != MP_OKAY) { + fprintf(stderr,"mp_init failed: \textbackslash{}"%s\textbackslash{}"\textbackslash{}n", + mp_error_to_string(e)); + exit(EXIT_FAILURE); + } + errno = 0; +#ifdef MP_64BIT + base = (mp_digit)strtoull(argv[1], NULL, 10); +#else + base = (mp_digit)strtoul(argv[1], NULL, 10); +#endif + if ((errno == ERANGE) || (base > (base & MP_MASK))) { + fprintf(stderr,"strtoul(l) failed: input out of range\textbackslash{}n"); + exit(EXIT_FAILURE); + } + if ((e = mp_read_radix(&x, argv[2], 10)) != MP_OKAY) { + fprintf(stderr,"mp_read_radix failed: \textbackslash{}"%s\textbackslash{}"\textbackslash{}n", + mp_error_to_string(e)); + exit(EXIT_FAILURE); + } + if ((e = mp_ilogb(&x, base, &output)) != MP_OKAY) { + fprintf(stderr,"mp_ilogb failed: \textbackslash{}"%s\textbackslash{}"\textbackslash{}n", + mp_error_to_string(e)); + exit(EXIT_FAILURE); + } + + if ((e = mp_fwrite(&output, 10, stdout)) != MP_OKAY) { + fprintf(stderr,"mp_fwrite failed: \textbackslash{}"%s\textbackslash{}"\textbackslash{}n", + mp_error_to_string(e)); + exit(EXIT_FAILURE); + } + putchar('\textbackslash{}n'); + + mp_clear_multi(&x, &output, NULL); + exit(EXIT_SUCCESS); +} +\end{alltt} + -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} @@ -1591,8 +1886,8 @@ $\left ( \left ( \left ( a^{1/2} \right )^{1/2} \right )^{1/2} \right )^{1/2}$ \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 +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.}. @@ -1611,10 +1906,10 @@ is set to zero. 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. +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 +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} @@ -1626,63 +1921,181 @@ This is why a simple function has been provided to help out. \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. +This returns the number of trials required for a low 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 18 tests for a probability of $2^{-160}$ whereas a 1024-bit number would only require 12 tests for a probability of $2^{-192}$. The exact values as implemented are listed in table \ref{table:millerrabinrunsimpl}. + +\begin{table}[h] +\begin{center} +\begin{tabular}{c c c} +\textbf{bits} & \textbf{Rounds} & \textbf{Error}\\ + 80 & -1 & Use deterministic algorithm for size <= 80 bits \\ + 81 & 37 & $2^{-96}$ \\ + 96 & 32 & $2^{-96}$ \\ + 128 & 40 & $2^{-112}$ \\ + 160 & 35 & $2^{-112}$ \\ + 256 & 27 & $2^{-128}$ \\ + 384 & 16 & $2^{-128}$ \\ + 512 & 18 & $2^{-160}$ \\ + 768 & 11 & $2^{-160}$ \\ + 896 & 10 & $2^{-160}$ \\ + 1024 & 12 & $2^{-192}$ \\ + 1536 & 8 & $2^{-192}$ \\ + 2048 & 6 & $2^{-192}$ \\ + 3072 & 4 & $2^{-192}$ \\ + 4096 & 5 & $2^{-256}$ \\ + 5120 & 4 & $2^{-256}$ \\ + 6144 & 4 & $2^{-256}$ \\ + 8192 & 3 & $2^{-256}$ \\ + 9216 & 3 & $2^{-256}$ \\ + 10240 & 2 & $2^{-256}$ +\end{tabular} +\caption{ Number of Miller-Rabin rounds as implemented } \label{table:millerrabinrunsimpl} +\end{center} +\end{table} You should always still perform a trial division before a Miller-Rabin test though. +A small table, broke in two for typographical reasons, with the number of rounds of Miller-Rabin tests is shown below. The numbers have been compute with a PARI/GP script listed in appendix \ref{app:numberofmrcomp}. +The first column is the number of bits $b$ in the prime $p = 2^b$, the numbers in the first row represent the +probability that the number that all of the Miller-Rabin tests deemed a pseudoprime is actually a composite. There is a deterministic test for numbers smaller than $2^{80}$. + +\begin{table}[h] +\begin{center} +\begin{tabular}{c c c c c c c} +\textbf{bits} & $\mathbf{2^{-80}}$ & $\mathbf{2^{-96}}$ & $\mathbf{2^{-112}}$ & $\mathbf{2^{-128}}$ & $\mathbf{2^{-160}}$ & $\mathbf{2^{-192}}$ \\ +80 & 31 & 39 & 47 & 55 & 71 & 87 \\ +96 & 29 & 37 & 45 & 53 & 69 & 85 \\ +128 & 24 & 32 & 40 & 48 & 64 & 80 \\ +160 & 19 & 27 & 35 & 43 & 59 & 75 \\ +192 & 15 & 21 & 29 & 37 & 53 & 69 \\ +256 & 10 & 15 & 20 & 27 & 43 & 59 \\ +384 & 7 & 9 & 12 & 16 & 25 & 38 \\ +512 & 5 & 7 & 9 & 12 & 18 & 26 \\ +768 & 4 & 5 & 6 & 8 & 11 & 16 \\ +1024 & 3 & 4 & 5 & 6 & 9 & 12 \\ +1536 & 2 & 3 & 3 & 4 & 6 & 8 \\ +2048 & 2 & 2 & 3 & 3 & 4 & 6 \\ +3072 & 1 & 2 & 2 & 2 & 3 & 4 \\ +4096 & 1 & 1 & 2 & 2 & 2 & 3 \\ +6144 & 1 & 1 & 1 & 1 & 2 & 2 \\ +8192 & 1 & 1 & 1 & 1 & 2 & 2 \\ +12288 & 1 & 1 & 1 & 1 & 1 & 1 \\ +16384 & 1 & 1 & 1 & 1 & 1 & 1 \\ +24576 & 1 & 1 & 1 & 1 & 1 & 1 \\ +32768 & 1 & 1 & 1 & 1 & 1 & 1 +\end{tabular} +\caption{ Number of Miller-Rabin rounds. Part I } \label{table:millerrabinrunsp1} +\end{center} +\end{table} +\newpage +\begin{table}[h] +\begin{center} +\begin{tabular}{c c c c c c c c} +\textbf{bits} &$\mathbf{2^{-224}}$ & $\mathbf{2^{-256}}$ & $\mathbf{2^{-288}}$ & $\mathbf{2^{-320}}$ & $\mathbf{2^{-352}}$ & $\mathbf{2^{-384}}$ & $\mathbf{2^{-416}}$\\ +80 & 103 & 119 & 135 & 151 & 167 & 183 & 199 \\ +96 & 101 & 117 & 133 & 149 & 165 & 181 & 197 \\ +128 & 96 & 112 & 128 & 144 & 160 & 176 & 192 \\ +160 & 91 & 107 & 123 & 139 & 155 & 171 & 187 \\ +192 & 85 & 101 & 117 & 133 & 149 & 165 & 181 \\ +256 & 75 & 91 & 107 & 123 & 139 & 155 & 171 \\ +384 & 54 & 70 & 86 & 102 & 118 & 134 & 150 \\ +512 & 36 & 49 & 65 & 81 & 97 & 113 & 129 \\ +768 & 22 & 29 & 37 & 47 & 58 & 70 & 86 \\ +1024 & 16 & 21 & 26 & 33 & 40 & 48 & 58 \\ +1536 & 10 & 13 & 17 & 21 & 25 & 30 & 35 \\ +2048 & 8 & 10 & 13 & 15 & 18 & 22 & 26 \\ +3072 & 5 & 7 & 8 & 10 & 12 & 14 & 17 \\ +4096 & 4 & 5 & 6 & 8 & 9 & 11 & 12 \\ +6144 & 3 & 4 & 4 & 5 & 6 & 7 & 8 \\ +8192 & 2 & 3 & 3 & 4 & 5 & 6 & 6 \\ +12288 & 2 & 2 & 2 & 3 & 3 & 4 & 4 \\ +16384 & 1 & 2 & 2 & 2 & 3 & 3 & 3 \\ +24576 & 1 & 1 & 2 & 2 & 2 & 2 & 2 \\ +32768 & 1 & 1 & 1 & 1 & 2 & 2 & 2 +\end{tabular} +\caption{ Number of Miller-Rabin rounds. Part II } \label{table:millerrabinrunsp2} +\end{center} +\end{table} + +Determining the probability needed to pick the right column is a bit harder. Fips 186.4, for example has $2^{-80}$ for $512$ bit large numbers, $2^{-112}$ for $1024$ bits, and $2^{128}$ for $1536$ bits. It can be seen in table \ref{table:millerrabinrunsp1} that those combinations follow the diagonal from $(512,2^{-80})$ downwards and to the right to gain a lower probabilty of getting a composite declared a pseudoprime for the same amount of work or less. + +If this version of the library has the strong Lucas-Selfridge and/or the Frobenius-Underwood test implemented only one or two rounds of the Miller-Rabin test with a random base is necesssary for numbers larger than or equal to $1024$ bits. + +This function is meant for RSA. The number of rounds for DSA is $\lceil -log_2(p)/2\rceil$ with $p$ the probability which is just the half of the absolute value of $p$ if given as a power of two. E.g.: with $p = 2^{-128}$, $\lceil -log_2(p)/2\rceil = 64$. + +This function can be used to test a DSA prime directly if these rounds are followed by a Lucas test. + +See also table C.1 in FIPS 186-4. + +\section{Strong Lucas-Selfridge Test} +\index{mp\_prime\_strong\_lucas\_selfridge} +\begin{alltt} +int mp_prime_strong_lucas_selfridge(const mp_int *a, int *result) +\end{alltt} +Performs a strong Lucas-Selfridge test. The strong Lucas-Selfridge test together with the Rabin-Miler test with bases $2$ and $3$ resemble the BPSW test. The single internal use is a compile-time option in \texttt{mp\_prime\_is\_prime} and can be excluded +from the Libtommath build if not needed. + +\section{Frobenius (Underwood) Test} +\index{mp\_prime\_frobenius\_underwood} +\begin{alltt} +int mp_prime_frobenius_underwood(const mp_int *N, int *result) +\end{alltt} +Performs the variant of the Frobenius test as described by Paul Underwood. The single internal use is in +\texttt{mp\_prime\_is\_prime} for \texttt{MP\_8BIT} only but can be included at build-time for all other sizes +if the preprocessor macro \texttt{LTM\_USE\_FROBENIUS\_TEST} is defined. + +It returns \texttt{MP\_ITER} if the number of iterations is exhausted, assumes a composite as the input and sets \texttt{result} accordingly. This will reduce the set of available pseudoprimes by a very small amount: test with large datasets (more than $10^{10}$ numbers, both randomly chosen and sequences of odd numbers with a random start point) found only 31 (thirty-one) numbers with $a > 120$ and none at all with just an additional simple check for divisors $d < 2^8$. + \section{Primality Testing} +Testing if a number is a square can be done a bit faster than just by calculating the square root. It is used by the primality testing function described below. +\index{mp\_is\_square} +\begin{alltt} +int mp_is_square(const mp_int *arg, int *ret); +\end{alltt} + + \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$). +This will perform a trial division followed by two rounds of Miller-Rabin with bases 2 and 3 and a Lucas-Selfridge test. The Lucas-Selfridge test is replaced with a Frobenius-Underwood for \texttt{MP\_8BIT}. The Frobenius-Underwood test for all other sizes is available as a compile-time option with the preprocessor macro \texttt{LTM\_USE\_FROBENIUS\_TEST}. See file +\texttt{bn\_mp\_prime\_is\_prime.c} for the necessary details. It shall be noted that both functions are much slower than +the Miller-Rabin test and if speed is an essential issue, the macro \texttt{LTM\_USE\_ONLY\_MR} switches both functions, the Frobenius-Underwood test and the Lucas-Selfridge test off and their code will not even be compiled into the library. + +If $t$ is set to a positive value $t$ additional rounds of the Miller-Rabin test with random bases will be performed to allow for Fips 186.4 (vid.~p.~126ff) compliance. The function \texttt{mp\_prime\_rabin\_miller\_trials} can be used to determine the number of rounds. It is vital that the function \texttt{mp\_rand()} has a cryptographically strong random number generator available. + +One Miller-Rabin tests with a random base will be run automatically, so by setting $t$ to a positive value this function will run $t + 1$ Miller-Rabin tests with random bases. + +If $t$ is set to a negative value the test will run the deterministic Miller-Rabin test for the primes up to $3317044064679887385961981$. That limit has to be checked by the caller. + +If $a$ passes all of the tests $result$ is set to one, otherwise it is set to zero. \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. +This finds the next prime after $a$ that passes mp\_prime\_is\_prime() with $t$ tests but see the documentation for +mp\_prime\_is\_prime for details regarding the use of the argument $t$. 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} +\index{mp\_prime\_rand} \begin{alltt} -int mp_prime_random(mp_int *a, int t, int size, int bbs, - ltm_prime_callback cb, void *dat) +int mp_prime_rand(mp_int *a, int t, + int size, int flags); \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 +This will generate a prime in $a$ using $t$ tests of the primality testing algorithms. +See the documentation for mp\_prime\_is\_prime for details regarding the use of the argument $t$. +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. -\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 +The function mp\_prime\_rand() is 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. +\textit{Note:} This function replaces the deprecated mp\_prime\_random and mp\_prime\_random\_ex functions. -\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{figure}[h] \begin{center} \begin{small} \begin{tabular}{|r|l|} @@ -1702,23 +2115,55 @@ mp\_prime\_random(). \label{fig:primeopts} \end{figure} +\chapter{Random Number Generation} +\section{PRNG} +\index{mp\_rand\_digit} +\begin{alltt} +int mp_rand_digit(mp_digit *r) +\end{alltt} +This function generates a random number in \texttt{r} of the size given in \texttt{r} (that is, the variable is used for in- and output) but not more than \texttt{MP\_MASK} bits. + +\index{mp\_rand} +\begin{alltt} +int mp_rand(mp_int *a, int digits) +\end{alltt} +This function generates a random number of \texttt{digits} bits. + +The random number generated with these two functions is cryptographically secure if the source of random numbers the operating systems offers is cryptographically secure. It will use \texttt{arc4random()} if the OS is a BSD flavor, Wincrypt on Windows, or \texttt{/dev/urandom} on all operating systems that have it. + + \chapter{Input and Output} \section{ASCII Conversions} \subsection{To ASCII} -\index{mp\_toradix} +\index{mp\_to\_radix} \begin{alltt} -int mp_toradix (mp_int * a, char *str, int radix); +int mp_to_radix (mp_int *a, char *str, size_t maxlen, size_t *written, 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. +This stores $a$ in \texttt{str} of maximum length \texttt{maxlen} as a base-\texttt{radix} string of ASCII chars and appends a \texttt{NUL} character to terminate the string. + +Valid values of \texttt{radix} line in the range $[2, 64]$. + +The exact number of characters in \texttt{str} plus the \texttt{NUL} will be put in \texttt{written} if that variable is not set to \texttt{NULL}. + +If \texttt{str} is not big enough to hold $a$, \texttt{str} will be filled with the least-significant digits +of length \texttt{maxlen-1}, then \texttt{str} will be \texttt{NUL} terminated and the error \texttt{MP\_VAL} is returned. + +Please be aware that this function cannot evaluate the actual size of the buffer, it relies on the correctness of \texttt{maxlen}! + \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. +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. + +If \texttt{LTM\_NO\_FILE} is not defined a function to write to a file is also available. +\index{mp\_fwrite} +\begin{alltt} +int mp_fwrite(const mp_int *a, int radix, FILE *stream); +\end{alltt} + \subsection{From ASCII} \index{mp\_read\_radix} @@ -1729,48 +2174,81 @@ This will read the base-``radix'' NUL terminated string from ``str'' into $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. +If \texttt{LTM\_NO\_FILE} is not defined a function to read from a file is also available. +\index{mp\_fread} +\begin{alltt} +int mp_fread(mp_int *a, int radix, FILE *stream); +\end{alltt} + + \section{Binary Conversions} Converting an mp\_int to and from binary is another keen idea. -\index{mp\_unsigned\_bin\_size} +\index{mp\_ubin\_size} \begin{alltt} -int mp_unsigned_bin_size(mp_int *a); +size_t mp_ubin_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} +\index{mp\_to\_ubin} \begin{alltt} -int mp_to_unsigned_bin(mp_int *a, unsigned char *b); +int mp_to_unsigned_bin(mp_int *a, unsigned char *b, size_t maxlen, size_t *len); \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. +This will store $a$ into the buffer $b$ of size \texttt{maxlen} in big--endian format storing the number of bytes written in \texttt{len}. 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} +\index{mp\_from\_ubin} \begin{alltt} -int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c); +int mp_from_ubin(mp_int *a, unsigned char *b, size_t size); \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. +This will read in an unsigned big--endian array of bytes (octets) from $b$ of length \texttt{size} into $a$. The resulting big-integer $a$ will always be positive. For those who acknowledge the existence of negative numbers (heretic!) there are ``signed'' versions of the previous functions. - +\index{mp\_signed\_bin\_size} \index{mp\_to\_signed\_bin} \index{mp\_read\_signed\_bin} \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); +int mp_sbin_size(mp_int *a); +int mp_from_sbin(mp_int *a, unsigned char *b, size_t size); +int mp_to_sbin(mp_int *a, unsigned char *b, size_t maxsize, size_t *len); \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. +is non--zero. + +The two functions \texttt{mp\_unpack} (get your gifts out of the box, import binary data) and \texttt{mp\_pack} (put your gifts into the box, export binary data) implement the similarly working GMP functions as described at \url{http://gmplib.org/manual/Integer-Import-and-Export.html} with the exception that \texttt{mp\_pack} will not allocate memory if \texttt{rop} is \texttt{NULL}. +\index{mp\_unpack} \index{mp\_pack} +\begin{alltt} +int mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size, + mp_endian endian, size_t nails, const void *op, size_t maxsize); +int mp_pack(void *rop, size_t *countp, mp_order order, size_t size, + mp_endian endian, size_t nails, const mp_int *op); +\end{alltt} +The function \texttt{mp\_pack} has the additional variable \texttt{maxsize} which must hold the size of the buffer \texttt{rop} in bytes. Use +\begin{alltt} +/* Parameters "nails" and "size" are the same as in mp_pack */ +size_t mp_pack_size(mp_int *a, size_t nails, size_t size); +\end{alltt} +To get the size in bytes necessary to be put in \texttt{maxsize}). + +To enhance the readability of your code, the following enums have been wrought for your convenience. +\begin{alltt} +typedef enum { + MP_LSB_FIRST = -1, + MP_MSB_FIRST = 1 +} mp_order; +typedef enum { + MP_LITTLE_ENDIAN = -1, + MP_NATIVE_ENDIAN = 0, + MP_BIG_ENDIAN = 1 +} mp_endian; +\end{alltt} \chapter{Algebraic Functions} \section{Extended Euclidean Algorithm} \index{mp\_exteuclid} \begin{alltt} -int mp_exteuclid(mp_int *a, mp_int *b, +int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3); \end{alltt} @@ -1780,7 +2258,7 @@ This finds the triple U1/U2/U3 using the Extended Euclidean algorithm such that 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. +Any of the U1/U2/U3 parameters can be set to \textbf{NULL} if they are not desired. \section{Greatest Common Divisor} \index{mp\_gcd} @@ -1804,7 +2282,36 @@ int mp_jacobi (mp_int * a, mp_int * p, int *c) 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$. +and the result will be $1$ if $a$ is a quadratic residue modulo $p$. + +\section{Kronecker Symbol} +\index{mp\_kronecker} +\begin{alltt} +int mp_kronecker (mp_int * a, mp_int * p, int *c) +\end{alltt} +Extension of the Jacoby symbol to all $\lbrace a, p \rbrace \in \mathbb{Z}$ . + + +\section{Modular square root} +\index{mp\_sqrtmod\_prime} +\begin{alltt} +int mp_sqrtmod_prime(mp_int *n, mp_int *p, mp_int *r) +\end{alltt} + +This will solve the modular equatioon $r^2 = n \mod p$ where $p$ is a prime number greater than 2 (odd prime). +The result is returned in the third argument $r$, the function returns \textbf{MP\_OKAY} on success, +other return values indicate failure. + +The implementation is split for two different cases: + +1. if $p \mod 4 == 3$ we apply \href{http://cacr.uwaterloo.ca/hac/}{Handbook of Applied Cryptography algorithm 3.36} and compute $r$ directly as +$r = n^{(p+1)/4} \mod p$ + +2. otherwise we use \href{https://en.wikipedia.org/wiki/Tonelli-Shanks_algorithm}{Tonelli-Shanks algorithm} + +The function does not check the primality of parameter $p$ thus it is up to the caller to assure that this parameter +is a prime number. When $p$ is a composite the function behaviour is undefined, it may even return a false-positive +\textbf{MP\_OKAY}. \section{Modular Inverse} \index{mp\_invmod} @@ -1830,6 +2337,171 @@ These work like the full mp\_int capable variants except the second parameter $b 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$. +The functions \texttt{mp\_incr} and \texttt{mp\_decr} mimic the postfix operators \texttt{++} and \texttt{--} respectively, to increment the input by one. They call the full single-digit functions if the addition would carry. Both functions need to be included in a minimized library because they call each other in case of a negative input, These functions change the inputs! +\begin{alltt} +int mp_incr(mp_int *a); +int mp_decr(mp_int *a); +\end{alltt} + + +The division by three can be made faster by replacing the division with a multiplication by the multiplicative inverse of three. + +\index{mp\_div\_3} +\begin{alltt} +int mp_div_3(const mp_int *a, mp_int *c, mp_digit *d); +\end{alltt} + +\chapter{Little Helpers} +It is never wrong to have some useful little shortcuts at hand. +\section{Function Macros} +To make this overview simpler the macros are given as function prototypes. The return of logic macros is \texttt{MP\_NO} or \texttt{MP\_YES} respectively. + +\index{mp\_iseven} +\begin{alltt} +int mp_iseven(mp_int *a) +\end{alltt} +Checks if $a = 0 mod 2$ + +\index{mp\_isodd} +\begin{alltt} +int mp_isodd(mp_int *a) +\end{alltt} +Checks if $a = 1 mod 2$ + +\index{mp\_isneg} +\begin{alltt} +int mp_isneg(mp_int *a) +\end{alltt} +Checks if $a < 0$ + + +\index{mp\_iszero} +\begin{alltt} +int mp_iszero(mp_int *a) +\end{alltt} +Checks if $a = 0$. It does not check if the amount of memory allocated for $a$ is also minimal. + + +Other macros which are either shortcuts to normal functions or just other names for them do have their place in a programmer's life, too! + +\subsection{Renamings} +\index{mp\_mag\_size} +\begin{alltt} +#define mp_mag_size(mp) mp_unsigned_bin_size(mp) +\end{alltt} + + +\index{mp\_raw\_size} +\begin{alltt} +#define mp_raw_size(mp) mp_signed_bin_size(mp) +\end{alltt} + + +\index{mp\_read\_mag} +\begin{alltt} +#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) +\end{alltt} + + +\index{mp\_read\_raw} +\begin{alltt} + #define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) +\end{alltt} + + +\index{mp\_tomag} +\begin{alltt} +#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) +\end{alltt} + + +\index{mp\_toraw} +\begin{alltt} +#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) +\end{alltt} + + + +\subsection{Shortcuts} + +\index{mp\_to\_binary} +\begin{alltt} +#define mp_to_binary(M, S, N) mp_to_radix((M), (S), (N), 2) +\end{alltt} + + +\index{mp\_to\_octal} +\begin{alltt} +#define mp_to_octal(M, S, N) mp_to_radix((M), (S), (N), 8) +\end{alltt} + + +\index{mp\_to\_decimal} +\begin{alltt} +#define mp_to_decimal(M, S, N) mp_to_radix((M), (S), (N), 10) +\end{alltt} + + +\index{mp\_to\_hex} +\begin{alltt} +#define mp_to_hex(M, S, N) mp_to_radix((M), (S), (N), 16) +\end{alltt} + +\begin{appendices} +\appendixpage +%\noappendicestocpagenum +\addappheadtotoc +\chapter{Computing Number of Miller-Rabin Trials}\label{app:numberofmrcomp} +The number of Miller-Rabin rounds in the tables \ref{millerrabinrunsimpl}, \ref{millerrabinrunsp1}, and \ref{millerrabinrunsp2} have been calculated with the formula in FIPS 186-4 appendix F.1 (page 117) implemented as a PARI/GP script. +\begin{alltt} +log2(x) = log(x)/log(2) + +fips_f1_sums(k, M, t) = { + local(s = 0); + s = sum(m=3,M, + 2^(m-t*(m-1)) * + sum(j=2,m, + 1/ ( 2^( j + (k-1)/j ) ) + ) + ); + return(s); +} + +fips_f1_2(k, t, M) = { + local(common_factor, t1, t2, f1, f2, ds, res); + + common_factor = 2.00743 * log(2) * k * 2^(-k); + t1 = 2^(k - 2 - M*t); + f1 = (8 * ((Pi^2) - 6))/3; + f2 = 2^(k - 2); + ds = t1 + f1 * f2 * fips_f1_sums(k, M, t); + res = common_factor * ds; + return(res); +} + +fips_f1_1(prime_length, ptarget)={ + local(t, t_end, M, M_end, pkt); + + t_end = ceil(-log2(ptarget)/2); + M_end = floor(2 * sqrt(prime_length-1) - 1); + + for(t = 1, t_end, + for(M = 3, M_end, + pkt = fips_f1_2(prime_length, t, M); + if(pkt <= ptarget, + return(t); + ); + ); + ); +} +\end{alltt} + +To get the number of rounds for a $1024$ bit large prime with a probability of $2^{-160}$: +\begin{alltt} +? fips_f1_1(1024,2^(-160)) +%1 = 9 +\end{alltt} +\end{appendices} \input{bn.ind} \end{document} diff --git a/lib/hcrypto/libtommath/etc/2kprime.c b/lib/hcrypto/libtommath/etc/2kprime.c index 0d2bf21e7..95ed2de42 100644 --- a/lib/hcrypto/libtommath/etc/2kprime.c +++ b/lib/hcrypto/libtommath/etc/2kprime.c @@ -2,12 +2,13 @@ #include #include -int sizes[] = {256, 512, 768, 1024, 1536, 2048, 3072, 4096}; +static int sizes[] = {256, 512, 768, 1024, 1536, 2048, 3072, 4096}; int main(void) { char buf[2000]; - int x, y; + size_t x; + mp_bool y; mp_int q, p; FILE *out; clock_t t1; @@ -16,69 +17,65 @@ int main(void) 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; + if (out != NULL) { + for (x = 0; x < (sizeof(sizes) / sizeof(sizes[0])); x++) { +top: + mp_2expt(&q, sizes[x]); + mp_add_d(&q, 3uL, &q); + z = -3; - t1 = clock(); - for(;;) { - mp_sub_d(&q, 4, &q); - z += 4; + t1 = clock(); + for (;;) { + mp_sub_d(&q, 4uL, &q); + z += 4uL; + + 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 == MP_NO) { + continue; + } + + /* find (q-1)/2 */ + mp_sub_d(&q, 1uL, &p); + mp_div_2(&p, &p); + mp_prime_is_prime(&p, 3, &y); + if (y == MP_NO) { + continue; + } + + /* test on q */ + mp_prime_is_prime(&q, 3, &y); + if (y == MP_NO) { + continue; + } - 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(); + if (y == MP_NO) { + ++sizes[x]; + goto top; } - /* 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); + mp_to_decimal(&q, buf, sizeof(buf)); + 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); + } + fclose(out); } return 0; } - - - - - - -/* $Source: /cvs/libtom/libtommath/etc/2kprime.c,v $ */ -/* $Revision: 1.2 $ */ -/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/etc/drprime.c b/lib/hcrypto/libtommath/etc/drprime.c index d92059327..64e31ef10 100644 --- a/lib/hcrypto/libtommath/etc/drprime.c +++ b/lib/hcrypto/libtommath/etc/drprime.c @@ -1,10 +1,12 @@ /* 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 }; +static int sizes[] = { 1+256/MP_DIGIT_BIT, 1+512/MP_DIGIT_BIT, 1+768/MP_DIGIT_BIT, 1+1024/MP_DIGIT_BIT, 1+2048/MP_DIGIT_BIT, 1+4096/MP_DIGIT_BIT }; + int main(void) { - int res, x, y; + mp_bool res; + int x, y; char buf[4096]; FILE *out; mp_int a, b; @@ -13,52 +15,53 @@ int main(void) 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; - } + if (out != NULL) { + for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) { +top: + printf("Seeking a %d-bit safe prime\n", sizes[x] * MP_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]; + /* 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; - } + /* now loop */ + res = MP_NO; + for (;;) { + a.dp[0] += 4uL; + if (a.dp[0] >= MP_MASK) break; + mp_prime_is_prime(&a, 1, &res); + if (res == MP_NO) continue; + printf("."); + fflush(stdout); + mp_sub_d(&a, 1uL, &b); + mp_div_2(&b, &b); + mp_prime_is_prime(&b, 3, &res); + if (res == MP_NO) continue; + mp_prime_is_prime(&a, 3, &res); + if (res == MP_YES) 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); - } + if (res != MP_YES) { + printf("Error not DR modulus\n"); + sizes[x] += 1; + goto top; + } else { + mp_to_decimal(&a, buf, sizeof(buf)); + 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); } - fclose(out); mp_clear(&a); mp_clear(&b); return 0; } - - -/* $Source: /cvs/libtom/libtommath/etc/drprime.c,v $ */ -/* $Revision: 1.2 $ */ -/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/etc/makefile b/lib/hcrypto/libtommath/etc/makefile index 99154d864..85bb09efc 100644 --- a/lib/hcrypto/libtommath/etc/makefile +++ b/lib/hcrypto/libtommath/etc/makefile @@ -1,4 +1,5 @@ -CFLAGS += -Wall -W -Wshadow -O3 -fomit-frame-pointer -funroll-loops -I../ +LTM_CFLAGS += -Wall -W -Wextra -Wshadow -O3 -I../ +LTM_CFLAGS += $(CFLAGS) # default lib name (requires install with root) # LIBNAME=-ltommath @@ -8,43 +9,36 @@ LIBNAME=../libtommath.a #provable primes pprime: pprime.o - $(CC) pprime.o $(LIBNAME) -o pprime + $(CC) $(LTM_CFLAGS) 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 + $(CC) $(LTM_CFLAGS) tune.o $(LIBNAME) -o tune + ./tune_it.sh + +test_standalone: tune.o + # The benchmark program works as a testtool, too + $(CC) $(LTM_CFLAGS) tune.o $(LIBNAME) -o test -#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 + $(CC) $(LTM_CFLAGS) mersenne.o $(LIBNAME) -o mersenne -# fines DR safe primes for the given config +# finds DR safe primes for the given config drprime: drprime.o - $(CC) drprime.o $(LIBNAME) -o drprime - -# fines 2k safe primes for the given config + $(CC) $(LTM_CFLAGS) drprime.o $(LIBNAME) -o drprime + +# finds 2k safe primes for the given config 2kprime: 2kprime.o - $(CC) 2kprime.o $(LIBNAME) -o 2kprime + $(CC) $(LTM_CFLAGS) 2kprime.o $(LIBNAME) -o 2kprime mont: mont.o - $(CC) mont.o $(LIBNAME) -o mont + $(CC) $(LTM_CFLAGS) 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 *~ + rm -f *.log *.o *.obj *.exe pprime tune mersenne drprime mont 2kprime pprime.dat \ + tuning_list multiplying squaring test *.da *.dyn *.dpi *~ + rm -rf .libs + +.PHONY: tune diff --git a/lib/hcrypto/libtommath/etc/makefile.icc b/lib/hcrypto/libtommath/etc/makefile.icc index 8a1ffffd2..9217f7b1d 100644 --- a/lib/hcrypto/libtommath/etc/makefile.icc +++ b/lib/hcrypto/libtommath/etc/makefile.icc @@ -8,7 +8,7 @@ CFLAGS += -I../ # -ax? specifies make code specifically for ? but compatible with IA-32 # -x? specifies compile solely for ? [not specifically IA-32 compatible] # -# where ? is +# where ? is # K - PIII # W - first P4 [Williamette] # N - P4 Northwood @@ -28,15 +28,15 @@ LIBNAME=../libtommath.a pprime: pprime.o $(CC) pprime.o $(LIBNAME) -o pprime -# portable [well requires clock()] tuning app tune: tune.o - $(CC) tune.o $(LIBNAME) -o tune - + $(CC) $(CFLAGS) tune.o $(LIBNAME) -o tune + ./tune_it.sh + # 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 @@ -46,7 +46,7 @@ tune86c: tune.c 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 @@ -54,7 +54,7 @@ mersenne: mersenne.o # 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 @@ -62,6 +62,6 @@ drprime: drprime.o 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 + rm -f *.log *.o *.obj *.exe pprime tune mersenne drprime tune86 tune86l mont 2kprime pprime.dat *.il tuning_list diff --git a/lib/hcrypto/libtommath/etc/makefile.msvc b/lib/hcrypto/libtommath/etc/makefile.msvc index 2833372e0..592a43715 100644 --- a/lib/hcrypto/libtommath/etc/makefile.msvc +++ b/lib/hcrypto/libtommath/etc/makefile.msvc @@ -9,10 +9,11 @@ pprime: pprime.obj mersenne: mersenne.obj cl mersenne.obj ../tommath.lib - + tune: tune.obj cl tune.obj ../tommath.lib + mont: mont.obj cl mont.obj ../tommath.lib diff --git a/lib/hcrypto/libtommath/etc/mersenne.c b/lib/hcrypto/libtommath/etc/mersenne.c index 78eb0ea27..0c9f52fcf 100644 --- a/lib/hcrypto/libtommath/etc/mersenne.c +++ b/lib/hcrypto/libtommath/etc/mersenne.c @@ -5,140 +5,134 @@ #include #include -int -is_mersenne (long s, int *pp) +static mp_err is_mersenne(long s, mp_bool *pp) { - mp_int n, u; - int res, k; + mp_int n, u; + mp_err res; + int k; - *pp = 0; + *pp = MP_NO; - if ((res = mp_init (&n)) != MP_OKAY) { - return res; - } + if ((res = mp_init(&n)) != MP_OKAY) { + return res; + } - if ((res = mp_init (&u)) != MP_OKAY) { - goto LBL_N; - } + 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) { + /* n = 2^s - 1 */ + if ((res = mp_2expt(&n, (int)s)) != MP_OKAY) { goto LBL_MU; - } - if ((res = mp_sub_d (&u, 2, &u)) != MP_OKAY) { + } + if ((res = mp_sub_d(&n, 1uL, &n)) != MP_OKAY) { goto LBL_MU; - } + } - /* make sure u is positive */ - while (u.sign == MP_NEG) { - if ((res = mp_add (&u, &n, &u)) != MP_OKAY) { + /* set u=4 */ + mp_set(&u, 4uL); + + /* 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, 2uL, &u)) != MP_OKAY) { goto LBL_MU; } - } - /* reduce */ - if ((res = mp_reduce_2k (&u, &n, 1)) != 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; + } + } - /* if u == 0 then its prime */ - if (mp_iszero (&u) == 1) { - mp_prime_is_prime(&n, 8, pp); - if (*pp != 1) printf("FAILURE\n"); - } + /* reduce */ + if ((res = mp_reduce_2k(&u, &n, 1uL)) != MP_OKAY) { + goto LBL_MU; + } + } - res = MP_OKAY; -LBL_MU:mp_clear (&u); -LBL_N:mp_clear (&n); - return res; + /* if u == 0 then its prime */ + if (mp_iszero(&u) == MP_YES) { + mp_prime_is_prime(&n, 8, pp); + if (*pp != MP_YES) 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) +static long i_sqrt(long x) { - long x1, x2; + long x1, x2; - x2 = 16; - do { - x1 = x2; - x2 = x1 - ((x1 * x1) - x) / (2 * x1); - } while (x1 != x2); + x2 = 16; + do { + x1 = x2; + x2 = x1 - ((x1 * x1) - x) / (2 * x1); + } while (x1 != x2); - if (x1 * x1 > x) { - --x1; - } + if ((x1 * x1) > x) { + --x1; + } - return x1; + return x1; } /* is the long prime by brute force */ -int -isprime (long k) +static int isprime(long k) { - long y, z; + long y, z; - y = i_sqrt (k); - for (z = 2; z <= y; z++) { - if ((k % z) == 0) - return 0; - } - return 1; + y = i_sqrt(k); + for (z = 2; z <= y; z++) { + if ((k % z) == 0) + return 0; + } + return 1; } -int -main (void) +int main(void) { - int pp; - long k; - clock_t tt; + mp_bool pp; + long k; + clock_t tt; - k = 3; + k = 3; - for (;;) { - /* start time */ - tt = clock (); + 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; - } + /* 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; + if (pp == MP_YES) { + /* count time */ + tt = clock() - tt; - /* display if prime */ - printf ("2^%-5ld - 1 is prime, test took %ld ticks\n", k, tt); - } + /* display if prime */ + printf("2^%-5ld - 1 is prime, test took %ld ticks\n", k, (long)tt); + } - /* goto next odd exponent */ - k += 2; - - /* but make sure its prime */ - while (isprime (k) == 0) { + /* goto next odd exponent */ k += 2; - } - } - return 0; -} -/* $Source: /cvs/libtom/libtommath/etc/mersenne.c,v $ */ -/* $Revision: 1.3 $ */ -/* $Date: 2006/03/31 14:18:47 $ */ + /* but make sure its prime */ + while (isprime(k) == 0) { + k += 2; + } + } +} diff --git a/lib/hcrypto/libtommath/etc/mont.c b/lib/hcrypto/libtommath/etc/mont.c index 7c5501fc0..4652410d0 100644 --- a/lib/hcrypto/libtommath/etc/mont.c +++ b/lib/hcrypto/libtommath/etc/mont.c @@ -1,50 +1,44 @@ /* tests the montgomery routines */ #include +#include +#include int main(void) { mp_int modulus, R, p, pp; mp_digit mp; - long x, y; + int 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); + printf("DIGITS == %3d...", x); + fflush(stdout); - /* make up the odd modulus */ - mp_rand(&modulus, x); - modulus.dp[0] |= 1; + /* make up the odd modulus */ + mp_rand(&modulus, x); + modulus.dp[0] |= 1uL; - /* now find the R value */ - mp_montgomery_calc_normalization(&R, &modulus); - mp_montgomery_setup(&modulus, &mp); + /* 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); + /* 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"); - } + /* should be equal to p */ + if (mp_cmp(&pp, &p) != MP_EQ) { + printf("FAILURE!\n"); + exit(-1); + } + } + printf("PASSED\n"); + } - return 0; + return 0; } - - - - - - -/* $Source: /cvs/libtom/libtommath/etc/mont.c,v $ */ -/* $Revision: 1.2 $ */ -/* $Date: 2005/05/05 14:38:47 $ */ diff --git a/lib/hcrypto/libtommath/etc/pprime.c b/lib/hcrypto/libtommath/etc/pprime.c index 317e2a0fc..009a18cb9 100644 --- a/lib/hcrypto/libtommath/etc/pprime.c +++ b/lib/hcrypto/libtommath/etc/pprime.c @@ -4,397 +4,408 @@ * * Tom St Denis, tomstdenis@gmail.com, http://tom.gmail.com */ +#include #include #include "tommath.h" -int n_prime; -FILE *primes; +static int n_prime; +static FILE *primes; /* fast square root */ -static mp_digit -i_sqrt (mp_word x) +static mp_digit i_sqrt(mp_word x) { - mp_word x1, x2; + mp_word x1, x2; - x2 = x; - do { - x1 = x2; - x2 = x1 - ((x1 * x1) - x) / (2 * x1); - } while (x1 != x2); + x2 = x; + do { + x1 = x2; + x2 = x1 - ((x1 * x1) - x) / (2u * x1); + } while (x1 != x2); - if (x1 * x1 > x) { - --x1; - } + if ((x1 * x1) > x) { + --x1; + } - return x1; + return x1; } /* generates a prime digit */ -static void gen_prime (void) +static void gen_prime(void) { - mp_digit r, x, y, next; - FILE *out; + mp_digit r, x, y, next; + FILE *out; - out = fopen("pprime.dat", "wb"); + out = fopen("pprime.dat", "wb"); + if (out != NULL) { - /* 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); + /* write first set of primes */ + /* *INDENT-OFF* */ + r = 3uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 5uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 7uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 11uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 13uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 17uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 19uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 23uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 29uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 31uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + /* *INDENT-ON* */ - /* get square root, since if 'r' is composite its factors must be < than this */ - y = i_sqrt (r); - next = (y + 1) * (y + 1); + /* get square root, since if 'r' is composite its factors must be < than this */ + y = i_sqrt(r); + next = (y + 1uL) * (y + 1uL); - for (;;) { - do { - r += 2; /* next candidate */ - r &= MP_MASK; - if (r < 31) break; + for (;;) { + do { + r += 2uL; /* next candidate */ + r &= MP_MASK; + if (r < 31uL) break; - /* update sqrt ? */ - if (next <= r) { - ++y; - next = (y + 1) * (y + 1); - } + /* update sqrt ? */ + if (next <= r) { + ++y; + next = (y + 1uL) * (y + 1uL); + } - /* 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; - } + /* loop if divisible by 3,5,7,11,13,17,19,23,29 */ + if ((r % 3uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 5uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 7uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 11uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 13uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 17uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 19uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 23uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 29uL) == 0uL) { + x = 0uL; + 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; + /* now check if r is divisible by x + k={1,7,11,13,17,19,23,29} */ + for (x = 30uL; x <= y; x += 30uL) { + if ((r % (x + 1uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 7uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 11uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 13uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 17uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 19uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 23uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 29uL)) == 0uL) { + x = 0uL; + break; + } + } + } while (x == 0uL); + if (r > 31uL) { + fwrite(&r, 1uL, sizeof(mp_digit), out); + printf("%9lu\r", r); + fflush(stdout); + } + if (r < 31uL) 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); + fclose(out); + } } -void load_tab(void) +static void load_tab(void) { primes = fopen("pprime.dat", "rb"); if (primes == NULL) { gen_prime(); primes = fopen("pprime.dat", "rb"); } - fseek(primes, 0, SEEK_END); + fseek(primes, 0L, SEEK_END); n_prime = ftell(primes) / sizeof(mp_digit); } -mp_digit prime_digit(void) +static 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); + fread(&d, 1uL, 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) +static mp_err 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 }; + mp_int a, b, c, n, x, y, z, v; + mp_err res; + int 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; - } + /* single digit ? */ + if (k <= (int) MP_DIGIT_BIT) { + mp_set(p, prime_digit()); + return MP_OKAY; + } - if ((res = mp_init (&c)) != MP_OKAY) { - return res; - } + if ((res = mp_init(&c)) != MP_OKAY) { + return res; + } - if ((res = mp_init (&v)) != MP_OKAY) { - goto LBL_C; - } + 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; - } + /* 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; - } + if ((res = mp_init(&a)) != MP_OKAY) { + goto LBL_V; + } - /* set the prime */ - mp_set (&a, prime_digit ()); + /* set the prime */ + mp_set(&a, prime_digit()); - if ((res = mp_init (&b)) != MP_OKAY) { - goto LBL_A; - } + if ((res = mp_init(&b)) != MP_OKAY) { + goto LBL_A; + } - if ((res = mp_init (&n)) != MP_OKAY) { - goto LBL_B; - } + if ((res = mp_init(&n)) != MP_OKAY) { + goto LBL_B; + } - if ((res = mp_init (&x)) != MP_OKAY) { - goto LBL_N; - } + if ((res = mp_init(&x)) != MP_OKAY) { + goto LBL_N; + } - if ((res = mp_init (&y)) != MP_OKAY) { - goto LBL_X; - } + if ((res = mp_init(&y)) != MP_OKAY) { + goto LBL_X; + } - if ((res = mp_init (&z)) != MP_OKAY) { - goto LBL_Y; - } + 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 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; + /* now compute z = a * b * 2 */ + if ((res = mp_mul(&a, &b, &z)) != MP_OKAY) { /* z = a * b */ + 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 ((res = mp_copy(&z, &c)) != MP_OKAY) { /* c = a * b */ + 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 ((res = mp_mul_2(&z, &z)) != MP_OKAY) { /* z = 2 * a * b */ + 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; + /* n = z + 1 */ + if ((res = mp_add_d(&z, 1uL, &n)) != MP_OKAY) { /* n = z + 1 */ + 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; + /* check (n, v) == 1 */ + if ((res = mp_gcd(&n, &v, &y)) != MP_OKAY) { /* y = (n, v) */ + goto LBL_Z; } - /* if y == 1 loop */ - if (mp_cmp_d (&y, 1) == MP_EQ) - continue; + if (mp_cmp_d(&y, 1uL) != MP_EQ) + goto top; - /* now compute (x^c mod n)^2 */ - if ((res = mp_sqrmod (&y, &n, &y)) != MP_OKAY) { /* y = x^2ab mod n */ - goto LBL_Z; + /* 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, 1uL) == 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, 1uL) == 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, 1uL) == 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, 1uL) == 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, 1uL) == 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, 1uL) != MP_EQ) + continue; + break; } - /* y should be 1 */ - if (mp_cmp_d (&y, 1) != MP_EQ) - continue; - break; - } + /* no bases worked? */ + if (ii == li) + goto top; - /* no bases worked? */ - if (ii == li) - goto top; + { + char buf[4096]; -{ - char buf[4096]; + mp_to_decimal(&n, buf, sizeof(buf)); + printf("Certificate of primality for:\n%s\n\n", buf); + mp_to_decimal(&a, buf, sizeof(buf)); + printf("A == \n%s\n\n", buf); + mp_to_decimal(&b, buf, sizeof(buf)); + printf("B == \n%s\n\nG == %lu\n", buf, bases[ii]); + printf("----------------------------------------------------------------\n"); + } - 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); + } - /* a = n */ - mp_copy (&n, &a); - } + /* get q to be the order of the large prime subgroup */ + mp_sub_d(&n, 1uL, q); + mp_div_2(q, q); + mp_div(q, &b, q, NULL); - /* 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); - 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; + 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) +int main(void) { - mp_int p, q; - char buf[4096]; - int k, li; - clock_t t1; + mp_int p, q; + char buf[4096]; + int k, li; + clock_t t1; - srand (time (NULL)); - load_tab(); + srand(time(NULL)); + load_tab(); - printf ("Enter # of bits: \n"); - fgets (buf, sizeof (buf), stdin); - sscanf (buf, "%d", &k); + 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); + 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); + mp_init(&p); + mp_init(&q); - t1 = clock (); - pprime (k, li, &p, &q); - t1 = clock () - t1; + t1 = clock(); + pprime(k, li, &p, &q); + t1 = clock() - t1; - printf ("\n\nTook %ld ticks, %d bits\n", t1, mp_count_bits (&p)); + printf("\n\nTook %d 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); + mp_to_decimal(&p, buf, sizeof(buf)); + printf("P == %s\n", buf); + mp_to_decimal(&q, buf, sizeof(buf)); + printf("Q == %s\n", buf); - return 0; + return 0; } - -/* $Source: /cvs/libtom/libtommath/etc/pprime.c,v $ */ -/* $Revision: 1.3 $ */ -/* $Date: 2006/03/31 14:18:47 $ */ diff --git a/lib/hcrypto/libtommath/etc/timer.asm b/lib/hcrypto/libtommath/etc/timer.asm index f1f84bdb4..35890d985 100644 --- a/lib/hcrypto/libtommath/etc/timer.asm +++ b/lib/hcrypto/libtommath/etc/timer.asm @@ -34,4 +34,4 @@ _t_read: sub eax,[time+4] sbb edx,[time+0] ret - + \ No newline at end of file diff --git a/lib/hcrypto/libtommath/etc/tune.c b/lib/hcrypto/libtommath/etc/tune.c index e09e8ef77..bc2cdfe6e 100644 --- a/lib/hcrypto/libtommath/etc/tune.c +++ b/lib/hcrypto/libtommath/etc/tune.c @@ -1,142 +1,542 @@ /* Tune the Karatsuba parameters * - * Tom St Denis, tomstdenis@gmail.com + * Tom St Denis, tstdenis82@gmail.com */ -#include +#include "../tommath.h" +#include "../tommath_private.h" #include +#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) +/* + Please take in mind that both multiplicands are of the same size. The balancing + mechanism in mp_balance works well but has some overhead itself. You can test + the behaviour of it with the option "-o" followed by a (small) positive number 'x' + to generate ratios of the form 1:x. +*/ -/* 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 +static uint64_t s_timer_function(void); +static void s_timer_start(void); +static uint64_t s_timer_stop(void); +static uint64_t s_time_mul(int size); +static uint64_t s_time_sqr(int size); +static void s_usage(char *s); - // 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 +static uint64_t s_timer_function(void) +{ +#if _POSIX_C_SOURCE >= 199309L +#define LTM_BILLION 1000000000 + struct timespec ts; + + /* TODO: Sets errno in case of error. Use? */ + clock_gettime(CLOCK_MONOTONIC, &ts); + return (((uint64_t)ts.tv_sec) * LTM_BILLION + (uint64_t)ts.tv_nsec); +#else + clock_t t; + t = clock(); + if (t < (clock_t)(0)) { + return (uint64_t)(0); } - - -#ifndef X86_TIMER + return (uint64_t)(t); +#endif +} /* 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) +static uint64_t s_timer_tmp; +static void s_timer_start(void) { - 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; + s_timer_tmp = s_timer_function(); +} +static uint64_t s_timer_stop(void) +{ + return s_timer_function() - s_timer_tmp; } -ulong64 time_sqr(int size, int s) + +static int s_check_result; +static int s_number_of_test_loops; +static int s_stabilization_extra; +static int s_offset = 1; + +#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) +static uint64_t s_time_mul(int size) { - unsigned long x; - mp_int a, b; - ulong64 t1; + int x; + mp_err e; + mp_int a, b, c, d; + uint64_t t1; - mp_init (&a); - mp_init (&b); + if ((e = mp_init_multi(&a, &b, &c, &d, NULL)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LTM_ERR; + } - mp_rand (&a, size); + if ((e = mp_rand(&a, size * s_offset)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LTM_ERR; + } + if ((e = mp_rand(&b, size)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LTM_ERR; + } - if (s == 1) { - KARATSUBA_SQR_CUTOFF = size; - } else { - KARATSUBA_SQR_CUTOFF = 100000; - } + s_timer_start(); + for (x = 0; x < s_number_of_test_loops; x++) { + if ((e = mp_mul(&a,&b,&c)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LTM_ERR; + } + if (s_check_result == 1) { + if ((e = s_mp_mul(&a,&b,&d)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LTM_ERR; + } + if (mp_cmp(&c, &d) != MP_EQ) { + /* Time of 0 cannot happen (famous last words?) */ + t1 = 0uLL; + goto LTM_ERR; + } + } + } - t_start(); - for (x = 0; x < TIMES; x++) { - mp_sqr(&a,&b); - } - t1 = t_read(); - mp_clear (&a); - mp_clear (&b); - return t1; + t1 = s_timer_stop(); +LTM_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return t1; } -int -main (void) +static uint64_t s_time_sqr(int size) { - ulong64 t1, t2; - int x, y; + int x; + mp_err e; + mp_int a, b, c; + uint64_t t1; - 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; + if ((e = mp_init_multi(&a, &b, &c, NULL)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LTM_ERR; + } - 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); + if ((e = mp_rand(&a, size)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LTM_ERR; + } - return 0; + s_timer_start(); + for (x = 0; x < s_number_of_test_loops; x++) { + if ((e = mp_sqr(&a,&b)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LTM_ERR; + } + if (s_check_result == 1) { + if ((e = s_mp_sqr(&a,&c)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LTM_ERR; + } + if (mp_cmp(&c, &b) != MP_EQ) { + t1 = 0uLL; + goto LTM_ERR; + } + } + } + + t1 = s_timer_stop(); +LTM_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return t1; } -/* $Source: /cvs/libtom/libtommath/etc/tune.c,v $ */ -/* $Revision: 1.3 $ */ -/* $Date: 2006/03/31 14:18:47 $ */ +struct tune_args { + int testmode; + int verbose; + int print; + int bncore; + int terse; + int upper_limit_print; + int increment_print; +} args; + +static void s_run(const char *name, uint64_t (*op)(int), int *cutoff) +{ + int x, count = 0; + uint64_t t1, t2; + if ((args.verbose == 1) || (args.testmode == 1)) { + printf("# %s.\n", name); + } + for (x = 8; x < args.upper_limit_print; x += args.increment_print) { + *cutoff = INT_MAX; + t1 = op(x); + if ((t1 == 0uLL) || (t1 == UINT64_MAX)) { + fprintf(stderr,"%s failed at x = INT_MAX (%s)\n", name, + (t1 == 0uLL)?"wrong result":"internal error"); + exit(EXIT_FAILURE); + } + *cutoff = x; + t2 = op(x); + if ((t2 == 0uLL) || (t2 == UINT64_MAX)) { + fprintf(stderr,"%s failed (%s)\n", name, + (t2 == 0uLL)?"wrong result":"internal error"); + exit(EXIT_FAILURE); + } + if (args.verbose == 1) { + printf("%d: %9"PRIu64" %9"PRIu64", %9"PRIi64"\n", x, t1, t2, (int64_t)t2 - (int64_t)t1); + } + if (t2 < t1) { + if (count == s_stabilization_extra) { + count = 0; + break; + } else if (count < s_stabilization_extra) { + count++; + } + } else if (count > 0) { + count--; + } + } + *cutoff = x - s_stabilization_extra * args.increment_print; +} + +static long s_strtol(const char *str, char **endptr, const char *err) +{ + const int base = 10; + char *_endptr; + long val; + errno = 0; + val = strtol(str, &_endptr, base); + if ((val > INT_MAX || val < 0) || (errno != 0)) { + fprintf(stderr, "Value %s not usable\n", str); + exit(EXIT_FAILURE); + } + if (_endptr == str) { + fprintf(stderr, "%s\n", err); + exit(EXIT_FAILURE); + } + if (endptr) *endptr = _endptr; + return val; +} + +static int s_exit_code = EXIT_FAILURE; +static void s_usage(char *s) +{ + fprintf(stderr,"Usage: %s [TvcpGbtrSLFfMmosh]\n",s); + fprintf(stderr," -T testmode, for use with testme.sh\n"); + fprintf(stderr," -v verbose, print all timings\n"); + fprintf(stderr," -c check results\n"); + fprintf(stderr," -p print benchmark of final cutoffs in files \"multiplying\"\n"); + fprintf(stderr," and \"squaring\"\n"); + fprintf(stderr," -G [string] suffix for the filenames listed above\n"); + fprintf(stderr," Implies '-p'\n"); + fprintf(stderr," -b print benchmark of bncore.c\n"); + fprintf(stderr," -t prints space (0x20) separated results\n"); + fprintf(stderr," -r [64] number of rounds\n"); + fprintf(stderr," -S [0xdeadbeef] seed for PRNG\n"); + fprintf(stderr," -L [3] number of negative values accumulated until the result is accepted\n"); + fprintf(stderr," -M [3000] upper limit of T-C tests/prints\n"); + fprintf(stderr," -m [1] increment of T-C tests/prints\n"); + fprintf(stderr," -o [1] multiplier for the second multiplicand\n"); + fprintf(stderr," (Not for computing the cut-offs!)\n"); + fprintf(stderr," -s 'preset' use values in 'preset' for printing.\n"); + fprintf(stderr," 'preset' is a comma separated string with cut-offs for\n"); + fprintf(stderr," ksm, kss, tc3m, tc3s in that order\n"); + fprintf(stderr," ksm = karatsuba multiplication\n"); + fprintf(stderr," kss = karatsuba squaring\n"); + fprintf(stderr," tc3m = Toom-Cook 3-way multiplication\n"); + fprintf(stderr," tc3s = Toom-Cook 3-way squaring\n"); + fprintf(stderr," Implies '-p'\n"); + fprintf(stderr," -h this message\n"); + exit(s_exit_code); +} + +struct cutoffs { + int KARATSUBA_MUL, KARATSUBA_SQR; + int TOOM_MUL, TOOM_SQR; +}; + +const struct cutoffs max_cutoffs = +{ INT_MAX, INT_MAX, INT_MAX, INT_MAX }; + +static void set_cutoffs(const struct cutoffs *c) +{ + KARATSUBA_MUL_CUTOFF = c->KARATSUBA_MUL; + KARATSUBA_SQR_CUTOFF = c->KARATSUBA_SQR; + TOOM_MUL_CUTOFF = c->TOOM_MUL; + TOOM_SQR_CUTOFF = c->TOOM_SQR; +} + +static void get_cutoffs(struct cutoffs *c) +{ + c->KARATSUBA_MUL = KARATSUBA_MUL_CUTOFF; + c->KARATSUBA_SQR = KARATSUBA_SQR_CUTOFF; + c->TOOM_MUL = TOOM_MUL_CUTOFF; + c->TOOM_SQR = TOOM_SQR_CUTOFF; + +} + +int main(int argc, char **argv) +{ + uint64_t t1, t2; + int x, i, j; + size_t n; + + int printpreset = 0; + /*int preset[8];*/ + char *endptr, *str; + + uint64_t seed = 0xdeadbeef; + + int opt; + struct cutoffs orig, updated; + + FILE *squaring, *multiplying; + char mullog[256] = "multiplying"; + char sqrlog[256] = "squaring"; + s_number_of_test_loops = 64; + s_stabilization_extra = 3; + + MP_ZERO_BUFFER(&args, sizeof(args)); + + args.testmode = 0; + args.verbose = 0; + args.print = 0; + args.bncore = 0; + args.terse = 0; + + args.upper_limit_print = 3000; + args.increment_print = 1; + + /* Very simple option parser, please treat it nicely. */ + if (argc != 1) { + for (opt = 1; (opt < argc) && (argv[opt][0] == '-'); opt++) { + switch (argv[opt][1]) { + case 'T': + args.testmode = 1; + s_check_result = 1; + args.upper_limit_print = 1000; + args.increment_print = 11; + s_number_of_test_loops = 1; + s_stabilization_extra = 1; + s_offset = 1; + break; + case 'v': + args.verbose = 1; + break; + case 'c': + s_check_result = 1; + break; + case 'p': + args.print = 1; + break; + case 'G': + args.print = 1; + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + /* manual strcat() */ + for (i = 0; i < 255; i++) { + if (mullog[i] == '\0') { + break; + } + } + for (j = 0; i < 255; j++, i++) { + mullog[i] = argv[opt][j]; + if (argv[opt][j] == '\0') { + break; + } + } + for (i = 0; i < 255; i++) { + if (sqrlog[i] == '\0') { + break; + } + } + for (j = 0; i < 255; j++, i++) { + sqrlog[i] = argv[opt][j]; + if (argv[opt][j] == '\0') { + break; + } + } + break; + case 'b': + args.bncore = 1; + break; + case 't': + args.terse = 1; + break; + case 'S': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + str = argv[opt]; + errno = 0; + seed = (uint64_t)s_strtol(argv[opt], NULL, "No seed given?\n"); + break; + case 'L': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + s_stabilization_extra = (int)s_strtol(argv[opt], NULL, "No value for option \"-L\"given"); + break; + case 'o': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + s_offset = (int)s_strtol(argv[opt], NULL, "No value for the offset given"); + break; + case 'r': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + s_number_of_test_loops = (int)s_strtol(argv[opt], NULL, "No value for the number of rounds given"); + break; + + case 'M': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + args.upper_limit_print = (int)s_strtol(argv[opt], NULL, "No value for the upper limit of T-C tests given"); + break; + case 'm': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + args.increment_print = (int)s_strtol(argv[opt], NULL, "No value for the increment for the T-C tests given"); + break; + case 's': + printpreset = 1; + args.print = 1; + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + str = argv[opt]; + KARATSUBA_MUL_CUTOFF = (int)s_strtol(str, &endptr, "[1/4] No value for KARATSUBA_MUL_CUTOFF given"); + str = endptr + 1; + KARATSUBA_SQR_CUTOFF = (int)s_strtol(str, &endptr, "[2/4] No value for KARATSUBA_SQR_CUTOFF given"); + str = endptr + 1; + TOOM_MUL_CUTOFF = (int)s_strtol(str, &endptr, "[3/4] No value for TOOM_MUL_CUTOFF given"); + str = endptr + 1; + TOOM_SQR_CUTOFF = (int)s_strtol(str, &endptr, "[4/4] No value for TOOM_SQR_CUTOFF given"); + break; + case 'h': + s_exit_code = EXIT_SUCCESS; + /* FALLTHROUGH */ + default: + s_usage(argv[0]); + } + } + } + + /* + mp_rand uses the cryptographically secure + source of the OS by default. That is too expensive, too slow and + most important for a benchmark: it is not repeatable. + */ + s_mp_rand_jenkins_init(seed); + mp_rand_source(s_mp_rand_jenkins); + + get_cutoffs(&orig); + + updated = max_cutoffs; + if ((args.bncore == 0) && (printpreset == 0)) { + struct { + const char *name; + int *cutoff, *update; + uint64_t (*fn)(int); + } test[] = { +#define T_MUL_SQR(n, o, f) { #n, &o##_CUTOFF, &(updated.o), MP_HAS(S_MP_##o) ? f : NULL } + /* + The influence of the Comba multiplication cannot be + eradicated programmatically. It depends on the size + of the macro MP_WPARRAY in tommath.h which needs to + be changed manually (to 0 (zero)). + */ + T_MUL_SQR("Karatsuba multiplication", KARATSUBA_MUL, s_time_mul), + T_MUL_SQR("Karatsuba squaring", KARATSUBA_SQR, s_time_sqr), + T_MUL_SQR("Toom-Cook 3-way multiplying", TOOM_MUL, s_time_mul), + T_MUL_SQR("Toom-Cook 3-way squaring", TOOM_SQR, s_time_sqr), +#undef T_MUL_SQR + }; + /* Turn all limits from bncore.c to the max */ + set_cutoffs(&max_cutoffs); + for (n = 0; n < sizeof(test)/sizeof(test[0]); ++n) { + if (test[n].fn) { + s_run(test[n].name, test[n].fn, test[n].cutoff); + *test[n].update = *test[n].cutoff; + *test[n].cutoff = INT_MAX; + } + } + } + if (args.terse == 1) { + printf("%d %d %d %d\n", + updated.KARATSUBA_MUL, + updated.KARATSUBA_SQR, + updated.TOOM_MUL, + updated.TOOM_SQR); + } else { + printf("KARATSUBA_MUL_CUTOFF = %d\n", updated.KARATSUBA_MUL); + printf("KARATSUBA_SQR_CUTOFF = %d\n", updated.KARATSUBA_SQR); + printf("TOOM_MUL_CUTOFF = %d\n", updated.TOOM_MUL); + printf("TOOM_SQR_CUTOFF = %d\n", updated.TOOM_SQR); + } + + if (args.print == 1) { + printf("Printing data for graphing to \"%s\" and \"%s\"\n",mullog, sqrlog); + + multiplying = fopen(mullog, "w+"); + if (multiplying == NULL) { + fprintf(stderr, "Opening file \"%s\" failed\n", mullog); + exit(EXIT_FAILURE); + } + + squaring = fopen(sqrlog, "w+"); + if (squaring == NULL) { + fprintf(stderr, "Opening file \"%s\" failed\n",sqrlog); + exit(EXIT_FAILURE); + } + + for (x = 8; x < args.upper_limit_print; x += args.increment_print) { + set_cutoffs(&max_cutoffs); + t1 = s_time_mul(x); + set_cutoffs(&orig); + t2 = s_time_mul(x); + fprintf(multiplying, "%d: %9"PRIu64" %9"PRIu64", %9"PRIi64"\n", x, t1, t2, (int64_t)t2 - (int64_t)t1); + fflush(multiplying); + if (args.verbose == 1) { + printf("MUL %d: %9"PRIu64" %9"PRIu64", %9"PRIi64"\n", x, t1, t2, (int64_t)t2 - (int64_t)t1); + fflush(stdout); + } + set_cutoffs(&max_cutoffs); + t1 = s_time_sqr(x); + set_cutoffs(&orig); + t2 = s_time_sqr(x); + fprintf(squaring,"%d: %9"PRIu64" %9"PRIu64", %9"PRIi64"\n", x, t1, t2, (int64_t)t2 - (int64_t)t1); + fflush(squaring); + if (args.verbose == 1) { + printf("SQR %d: %9"PRIu64" %9"PRIu64", %9"PRIi64"\n", x, t1, t2, (int64_t)t2 - (int64_t)t1); + fflush(stdout); + } + } + printf("Finished. Data for graphing in \"%s\" and \"%s\"\n",mullog, sqrlog); + if (args.verbose == 1) { + set_cutoffs(&orig); + if (args.terse == 1) { + printf("%d %d %d %d\n", + KARATSUBA_MUL_CUTOFF, + KARATSUBA_SQR_CUTOFF, + TOOM_MUL_CUTOFF, + TOOM_SQR_CUTOFF); + } else { + printf("KARATSUBA_MUL_CUTOFF = %d\n", KARATSUBA_MUL_CUTOFF); + printf("KARATSUBA_SQR_CUTOFF = %d\n", KARATSUBA_SQR_CUTOFF); + printf("TOOM_MUL_CUTOFF = %d\n", TOOM_MUL_CUTOFF); + printf("TOOM_SQR_CUTOFF = %d\n", TOOM_SQR_CUTOFF); + } + } + } + exit(EXIT_SUCCESS); +} diff --git a/lib/hcrypto/libtommath/etc/tune_it.sh b/lib/hcrypto/libtommath/etc/tune_it.sh new file mode 100755 index 000000000..5e0fe7c3e --- /dev/null +++ b/lib/hcrypto/libtommath/etc/tune_it.sh @@ -0,0 +1,107 @@ +#!/bin/sh + +die() { + echo "$1 failed" + echo "Exiting" + exit $2 +} +# A linear congruential generator is sufficient for the purpose. +SEED=3735928559 +LCG() { + SEED=$(((1103515245 * $SEED + 12345) % 2147483648)) + echo $SEED +} +median() { +# read everything besides the header from file $1 +# | cut-out the required column $2 +# | sort all the entries numerically +# | show only the first $3 entries +# | show only the last entry + tail -n +2 $1 | cut -d' ' -f$2 | sort -n | head -n $3 | tail -n 1 +} + +MPWD=$(dirname $(readlink -f "$0")) +FILE_NAME="tuning_list" +TOMMATH_CUTOFFS_H="$MPWD/../tommath_cutoffs.h" +BACKUP_SUFFIX=".orig" +RNUM=0 + +############################################################################# +# It would be a good idea to isolate these processes (with e.g.: cpuset) # +# # +# It is not a good idea to e.g: watch high resolution videos while this # +# test are running if you do not have enough memory to avoid page faults. # +############################################################################# + +# Number of rounds overall. +LIMIT=100 +# Number of loops for each input. +RLOOPS=10 +# Offset ( > 0 ) . Runs tests with asymmetric input of the form 1:OFFSET +# Please use another destination for TOMMATH_CUTOFFS_H if you change OFFSET, because the numbers +# with an offset different from 1 (one) are not usable as the general cut-off values +# in "tommath_cutoffs.h". +OFFSET=1 +# Number ( >= 3 ) of positive results (TC-is-faster) accumulated until it is accepted. +# Due to the algorithm used to compute the median in this Posix compliant shell script +# the value needs to be 3 (three), not less, to keep the variation small. +LAG=3 +# Keep the temporary file $FILE_NAME. Set to 0 (zero) to remove it at the end. +# The file is in a format fit to feed into R directly. If you do it and find the median +# of this program to be off by more than a couple: please contact the authors and report +# the numbers from this program and R and the standard deviation. This program is known +# to get larger errors if the standard deviation is larger than ~50. +KEEP_TEMP=1 + +echo "You might like to watch the numbers go up to $LIMIT but it will take a long time!" + +# Might not have sufficient rights or disc full. +echo "km ks tc3m tc3s" > $FILE_NAME || die "Writing header to $FILE_NAME" $? +i=1 +while [ $i -le $LIMIT ]; do + RNUM=$(LCG) + printf "\r%d" $i + "$MPWD"/tune -t -r $RLOOPS -L $LAG -S "$RNUM" -o $OFFSET >> $FILE_NAME || die "tune" $? + i=$((i + 1)) +done + +if [ $KEEP_TEMP -eq 0 ]; then + rm -v $FILE_NAME || die "Removing $KEEP_TEMP" $? +fi + +echo "Writing cut-off values to \"$TOMMATH_CUTOFFS_H\"." +echo "In case of failure: a copy of \"$TOMMATH_CUTOFFS_H\" is in \"$TOMMATH_CUTOFFS_H$BACKUP_SUFFIX\"" + +cp -v $TOMMATH_CUTOFFS_H $TOMMATH_CUTOFFS_H$BACKUP_SUFFIX || die "Making backup copy of $TOMMATH_CUTOFFS_H" $? + +cat << END_OF_INPUT > $TOMMATH_CUTOFFS_H || die "Writing header to $TOMMATH_CUTOFFS_H" $? +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* + Current values evaluated on an AMD A8-6600K (64-bit). + Type "make tune" to optimize them for your machine but + be aware that it may take a long time. It took 2:30 minutes + on the aforementioned machine for example. + */ +END_OF_INPUT + +# The Posix shell does not offer an array data type so we create +# the median with 'standard tools'^TM + +# read the file (without the first line) and count the lines +i=$(tail -n +2 $FILE_NAME | wc -l) +# our median point will be at $i entries +i=$(( (i / 2) + 1 )) +TMP=$(median $FILE_NAME 1 $i) +echo "#define MP_DEFAULT_KARATSUBA_MUL_CUTOFF $TMP" +echo "#define MP_DEFAULT_KARATSUBA_MUL_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(km) Appending to $TOMMATH_CUTOFFS_H" $? +TMP=$(median $FILE_NAME 2 $i) +echo "#define MP_DEFAULT_KARATSUBA_SQR_CUTOFF $TMP" +echo "#define MP_DEFAULT_KARATSUBA_SQR_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(ks) Appending to $TOMMATH_CUTOFFS_H" $? +TMP=$(median $FILE_NAME 3 $i) +echo "#define MP_DEFAULT_TOOM_MUL_CUTOFF $TMP" +echo "#define MP_DEFAULT_TOOM_MUL_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(tc3m) Appending to $TOMMATH_CUTOFFS_H" $? +TMP=$(median $FILE_NAME 4 $i) +echo "#define MP_DEFAULT_TOOM_SQR_CUTOFF $TMP" +echo "#define MP_DEFAULT_TOOM_SQR_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(tc3s) Appending to $TOMMATH_CUTOFFS_H" $? + diff --git a/lib/hcrypto/libtommath/gen.pl b/lib/hcrypto/libtommath/gen.pl index 28c78bc29..332994d5c 100644 --- a/lib/hcrypto/libtommath/gen.pl +++ b/lib/hcrypto/libtommath/gen.pl @@ -4,14 +4,17 @@ # add the whole source without any makefile troubles # use strict; +use warnings; -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: $!"; +open(my $out, '>', 'mpi.c') or die "Couldn't open mpi.c for writing: $!"; +foreach my $filename (glob 'bn*.c') { + open(my $src, '<', $filename) or die "Couldn't open $filename for reading: $!"; + print {$out} "/* Start: $filename */\n"; + print {$out} $_ while <$src>; + 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: $!"; +print {$out} "\n/* EOF */\n"; +close $out or die "Error closing mpi.c after writing: $!"; + +system('perl -pli -e "s/\s*$//" mpi.c'); diff --git a/lib/hcrypto/libtommath/helper.pl b/lib/hcrypto/libtommath/helper.pl new file mode 100755 index 000000000..e60c1a775 --- /dev/null +++ b/lib/hcrypto/libtommath/helper.pl @@ -0,0 +1,482 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Getopt::Long; +use File::Find 'find'; +use File::Basename 'basename'; +use File::Glob 'bsd_glob'; + +sub read_file { + my $f = shift; + open my $fh, "<", $f or die "FATAL: read_rawfile() cannot open file '$f': $!"; + binmode $fh; + return do { local $/; <$fh> }; +} + +sub write_file { + my ($f, $data) = @_; + die "FATAL: write_file() no data" unless defined $data; + open my $fh, ">", $f or die "FATAL: write_file() cannot open file '$f': $!"; + binmode $fh; + print $fh $data or die "FATAL: write_file() cannot write to '$f': $!"; + close $fh or die "FATAL: write_file() cannot close '$f': $!"; + return; +} + +sub sanitize_comments { + my($content) = @_; + $content =~ s{/\*(.*?)\*/}{my $x=$1; $x =~ s/\w/x/g; "/*$x*/";}egs; + return $content; +} + +sub check_source { + my @all_files = ( + bsd_glob("makefile*"), + bsd_glob("*.{h,c,sh,pl}"), + bsd_glob("*/*.{h,c,sh,pl}"), + ); + + my $fails = 0; + for my $file (sort @all_files) { + my $troubles = {}; + my $lineno = 1; + my $content = read_file($file); + $content = sanitize_comments $content; + push @{$troubles->{crlf_line_end}}, '?' if $content =~ /\r/; + for my $l (split /\n/, $content) { + push @{$troubles->{merge_conflict}}, $lineno if $l =~ /^(<<<<<<<|=======|>>>>>>>)([^<=>]|$)/; + push @{$troubles->{trailing_space}}, $lineno if $l =~ / $/; + push @{$troubles->{tab}}, $lineno if $l =~ /\t/ && basename($file) !~ /^makefile/i; + push @{$troubles->{non_ascii_char}}, $lineno if $l =~ /[^[:ascii:]]/; + push @{$troubles->{cpp_comment}}, $lineno if $file =~ /\.(c|h)$/ && ($l =~ /\s\/\// || $l =~ /\/\/\s/); + # we prefer using XMALLOC, XFREE, XREALLOC, XCALLOC ... + push @{$troubles->{unwanted_malloc}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmalloc\s*\(/; + push @{$troubles->{unwanted_realloc}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\brealloc\s*\(/; + push @{$troubles->{unwanted_calloc}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bcalloc\s*\(/; + push @{$troubles->{unwanted_free}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bfree\s*\(/; + # and we probably want to also avoid the following + push @{$troubles->{unwanted_memcpy}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmemcpy\s*\(/; + push @{$troubles->{unwanted_memset}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmemset\s*\(/; + push @{$troubles->{unwanted_memcpy}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmemcpy\s*\(/; + push @{$troubles->{unwanted_memmove}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmemmove\s*\(/; + push @{$troubles->{unwanted_memcmp}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmemcmp\s*\(/; + push @{$troubles->{unwanted_strcmp}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bstrcmp\s*\(/; + push @{$troubles->{unwanted_strcpy}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bstrcpy\s*\(/; + push @{$troubles->{unwanted_strncpy}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bstrncpy\s*\(/; + push @{$troubles->{unwanted_clock}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bclock\s*\(/; + push @{$troubles->{unwanted_qsort}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bqsort\s*\(/; + push @{$troubles->{sizeof_no_brackets}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bsizeof\s*[^\(]/; + if ($file =~ m|^[^\/]+\.c$| && $l =~ /^static(\s+[a-zA-Z0-9_]+)+\s+([a-zA-Z0-9_]+)\s*\(/) { + my $funcname = $2; + # static functions should start with s_ + push @{$troubles->{staticfunc_name}}, "$lineno($funcname)" if $funcname !~ /^s_/; + } + $lineno++; + } + for my $k (sort keys %$troubles) { + warn "[$k] $file line:" . join(",", @{$troubles->{$k}}) . "\n"; + $fails++; + } + } + + warn( $fails > 0 ? "check-source: FAIL $fails\n" : "check-source: PASS\n" ); + return $fails; +} + +sub check_comments { + my $fails = 0; + my $first_comment = <<'MARKER'; +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +MARKER + #my @all_files = (bsd_glob("*.{h,c}"), bsd_glob("*/*.{h,c}")); + my @all_files = (bsd_glob("*.{h,c}")); + for my $f (@all_files) { + my $txt = read_file($f); + if ($txt !~ /\Q$first_comment\E/s) { + warn "[first_comment] $f\n"; + $fails++; + } + } + warn( $fails > 0 ? "check-comments: FAIL $fails\n" : "check-comments: PASS\n" ); + return $fails; +} + +sub check_doc { + my $fails = 0; + my $tex = read_file('doc/bn.tex'); + my $tmh = read_file('tommath.h'); + my @functions = $tmh =~ /\n\s*[a-zA-Z0-9_* ]+?(mp_[a-z0-9_]+)\s*\([^\)]+\)\s*;/sg; + my @macros = $tmh =~ /\n\s*#define\s+([a-z0-9_]+)\s*\([^\)]+\)/sg; + for my $n (sort @functions) { + (my $nn = $n) =~ s/_/\\_/g; # mp_sub_d >> mp\_sub\_d + if ($tex !~ /index\Q{$nn}\E/) { + warn "[missing_doc_for_function] $n\n"; + $fails++ + } + } + for my $n (sort @macros) { + (my $nn = $n) =~ s/_/\\_/g; # mp_iszero >> mp\_iszero + if ($tex !~ /index\Q{$nn}\E/) { + warn "[missing_doc_for_macro] $n\n"; + $fails++ + } + } + warn( $fails > 0 ? "check_doc: FAIL $fails\n" : "check-doc: PASS\n" ); + return $fails; +} + +sub prepare_variable { + my ($varname, @list) = @_; + my $output = "$varname="; + my $len = length($output); + foreach my $obj (sort @list) { + $len = $len + length $obj; + $obj =~ s/\*/\$/; + if ($len > 100) { + $output .= "\\\n"; + $len = length $obj; + } + $output .= $obj . ' '; + } + $output =~ s/ $//; + return $output; +} + +sub prepare_msvc_files_xml { + my ($all, $exclude_re, $targets) = @_; + my $last = []; + my $depth = 2; + + # sort files in the same order as visual studio (ugly, I know) + my @parts = (); + for my $orig (@$all) { + my $p = $orig; + $p =~ s|/|/~|g; + $p =~ s|/~([^/]+)$|/$1|g; + my @l = map { sprintf "% -99s", $_ } split /\//, $p; + push @parts, [ $orig, join(':', @l) ]; + } + my @sorted = map { $_->[0] } sort { $a->[1] cmp $b->[1] } @parts; + + my $files = "\r\n"; + for my $full (@sorted) { + my @items = split /\//, $full; # split by '/' + $full =~ s|/|\\|g; # replace '/' bt '\' + shift @items; # drop first one (src) + pop @items; # drop last one (filename.ext) + my $current = \@items; + if (join(':', @$current) ne join(':', @$last)) { + my $common = 0; + $common++ while ($last->[$common] && $current->[$common] && $last->[$common] eq $current->[$common]); + my $back = @$last - $common; + if ($back > 0) { + $files .= ("\t" x --$depth) . "\r\n" for (1..$back); + } + my $fwd = [ @$current ]; splice(@$fwd, 0, $common); + for my $i (0..scalar(@$fwd) - 1) { + $files .= ("\t" x $depth) . "[$i]\"\r\n"; + $files .= ("\t" x $depth) . "\t>\r\n"; + $depth++; + } + $last = $current; + } + $files .= ("\t" x $depth) . "\r\n"; + if ($full =~ $exclude_re) { + for (@$targets) { + $files .= ("\t" x $depth) . "\t\r\n"; + $files .= ("\t" x $depth) . "\t\t\r\n"; + $files .= ("\t" x $depth) . "\t\r\n"; + } + } + $files .= ("\t" x $depth) . "\r\n"; + } + $files .= ("\t" x --$depth) . "\r\n" for (@$last); + $files .= "\t"; + return $files; +} + +sub patch_file { + my ($content, @variables) = @_; + for my $v (@variables) { + if ($v =~ /^([A-Z0-9_]+)\s*=.*$/si) { + my $name = $1; + $content =~ s/\n\Q$name\E\b.*?[^\\]\n/\n$v\n/s; + } + else { + die "patch_file failed: " . substr($v, 0, 30) . ".."; + } + } + return $content; +} + +sub process_makefiles { + my $write = shift; + my $changed_count = 0; + my @o = map { my $x = $_; $x =~ s/\.c$/.o/; $x } bsd_glob("*.c"); + my @all = bsd_glob("*.{c,h}"); + + my $var_o = prepare_variable("OBJECTS", @o); + (my $var_obj = $var_o) =~ s/\.o\b/.obj/sg; + + # update MSVC project files + my $msvc_files = prepare_msvc_files_xml(\@all, qr/NOT_USED_HERE/, ['Debug|Win32', 'Release|Win32', 'Debug|x64', 'Release|x64']); + for my $m (qw/libtommath_VS2008.vcproj/) { + my $old = read_file($m); + my $new = $old; + $new =~ s|.*|$msvc_files|s; + if ($old ne $new) { + write_file($m, $new) if $write; + warn "changed: $m\n"; + $changed_count++; + } + } + + # update OBJECTS + HEADERS in makefile* + for my $m (qw/ makefile makefile.shared makefile_include.mk makefile.msvc makefile.unix makefile.mingw /) { + my $old = read_file($m); + my $new = $m eq 'makefile.msvc' ? patch_file($old, $var_obj) + : patch_file($old, $var_o); + if ($old ne $new) { + write_file($m, $new) if $write; + warn "changed: $m\n"; + $changed_count++; + } + } + + if ($write) { + return 0; # no failures + } + else { + warn( $changed_count > 0 ? "check-makefiles: FAIL $changed_count\n" : "check-makefiles: PASS\n" ); + return $changed_count; + } +} + +sub draw_func +{ + my ($deplist, $depmap, $out, $indent, $funcslist) = @_; + my @funcs = split ',', $funcslist; + # try this if you want to have a look at a minimized version of the callgraph without all the trivial functions + #if ($deplist =~ /$funcs[0]/ || $funcs[0] =~ /BN_MP_(ADD|SUB|CLEAR|CLEAR_\S+|DIV|MUL|COPY|ZERO|GROW|CLAMP|INIT|INIT_\S+|SET|ABS|CMP|CMP_D|EXCH)_C/) { + if ($deplist =~ /$funcs[0]/) { + return $deplist; + } else { + $deplist = $deplist . $funcs[0]; + } + if ($indent == 0) { + } elsif ($indent >= 1) { + print {$out} '| ' x ($indent - 1) . '+--->'; + } + print {$out} $funcs[0] . "\n"; + shift @funcs; + my $olddeplist = $deplist; + foreach my $i (@funcs) { + $deplist = draw_func($deplist, $depmap, $out, $indent + 1, ${$depmap}{$i}) if exists ${$depmap}{$i}; + } + return $olddeplist; +} + +sub update_dep +{ + #open class file and write preamble + open(my $class, '>', 'tommath_class.h') or die "Couldn't open tommath_class.h for writing\n"; + print {$class} << 'EOS'; +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) +#define LTM_INSIDE +#if defined(LTM2) +# define LTM3 +#endif +#if defined(LTM1) +# define LTM2 +#endif +#define LTM1 +#if defined(LTM_ALL) +EOS + + 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(my $src, '<', $filename); + open(my $out, '>', 'tmp'); + + # first line will be the #ifdef + my $line = <$src>; + if ($line =~ /include/) { + print {$out} $line; + } else { + print {$out} << "EOS"; +#include "tommath_private.h" +#ifdef $define +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +$line +EOS + $apply = 1; + } + while (<$src>) { + 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#endif\n"; + + # now do classes + my %depmap; + foreach my $filename (glob 'bn*.c') { + my $content; + if ($filename =~ "bn_deprecated.c") { + open(my $src, '<', $filename) or die "Can't open source file!\n"; + read $src, $content, -s $src; + close $src; + } else { + my $cc = $ENV{'CC'} || 'gcc'; + $content = `$cc -E -x c -DLTM_ALL $filename`; + $content =~ s/^# 1 "$filename".*?^# 2 "$filename"//ms; + } + + # 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; + + # strip comments + $content =~ s{/\*.*?\*/}{}gs; + + # scan for mp_* and make classes + my @deps = (); + foreach my $line (split /\n/, $content) { + while ($line =~ /(fast_)?(s_)?mp\_[a-z_0-9]*((?=\;)|(?=\())|(?<=\()mp\_[a-z_0-9]*(?=\()/g) { + my $a = $&; + next if $a eq "mp_err"; + $a =~ tr/[a-z]/[A-Z]/; + $a = 'BN_' . $a . '_C'; + push @deps, $a; + } + } + @deps = sort(@deps); + foreach my $a (@deps) { + if ($list !~ /$a/) { + print {$class} "# define $a\n"; + } + $list = $list . ',' . $a; + } + $depmap{$filename} = $list; + + print {$class} "#endif\n\n"; + } + + print {$class} << 'EOS'; +#ifdef LTM_INSIDE +#undef LTM_INSIDE +#ifdef LTM3 +# define LTM_LAST +#endif + +#include "tommath_superclass.h" +#include "tommath_class.h" +#else +# define LTM_LAST +#endif +EOS + close $class; + + #now let's make a cool call graph... + + open(my $out, '>', 'callgraph.txt'); + foreach (sort keys %depmap) { + draw_func("", \%depmap, $out, 0, $depmap{$_}); + print {$out} "\n\n"; + } + close $out; + + return 0; +} + +sub generate_def { + my @files = split /\n/, `git ls-files`; + @files = grep(/\.c/, @files); + @files = map { my $x = $_; $x =~ s/^bn_|\.c$//g; $x; } @files; + @files = grep(!/mp_radix_smap/, @files); + + push(@files, qw(mp_set_int mp_set_long mp_set_long_long mp_get_int mp_get_long mp_get_long_long mp_init_set_int)); + + my $files = join("\n ", sort(grep(/^mp_/, @files))); + write_file "tommath.def", "; libtommath +; +; Use this command to produce a 32-bit .lib file, for use in any MSVC version +; lib -machine:X86 -name:libtommath.dll -def:tommath.def -out:tommath.lib +; Use this command to produce a 64-bit .lib file, for use in any MSVC version +; lib -machine:X64 -name:libtommath.dll -def:tommath.def -out:tommath.lib +; +EXPORTS + $files +"; + return 0; +} + +sub die_usage { + die <<"MARKER"; +usage: $0 -s OR $0 --check-source + $0 -o OR $0 --check-comments + $0 -m OR $0 --check-makefiles + $0 -a OR $0 --check-all + $0 -u OR $0 --update-files +MARKER +} + +GetOptions( "s|check-source" => \my $check_source, + "o|check-comments" => \my $check_comments, + "m|check-makefiles" => \my $check_makefiles, + "d|check-doc" => \my $check_doc, + "a|check-all" => \my $check_all, + "u|update-files" => \my $update_files, + "h|help" => \my $help + ) or die_usage; + +my $failure; +$failure ||= check_source() if $check_all || $check_source; +$failure ||= check_comments() if $check_all || $check_comments; +$failure ||= check_doc() if $check_doc; # temporarily excluded from --check-all +$failure ||= process_makefiles(0) if $check_all || $check_makefiles; +$failure ||= process_makefiles(1) if $update_files; +$failure ||= update_dep() if $update_files; +$failure ||= generate_def() if $update_files; + +die_usage unless defined $failure; +exit $failure ? 1 : 0; diff --git a/lib/hcrypto/libtommath/libtommath.dsp b/lib/hcrypto/libtommath/libtommath.dsp deleted file mode 100644 index 6b8908f07..000000000 --- a/lib/hcrypto/libtommath/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/lib/hcrypto/libtommath/libtommath.pc.in b/lib/hcrypto/libtommath/libtommath.pc.in new file mode 100644 index 000000000..099b1cd74 --- /dev/null +++ b/lib/hcrypto/libtommath/libtommath.pc.in @@ -0,0 +1,10 @@ +prefix=@to-be-replaced@ +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: LibTomMath +Description: public domain library for manipulating large integer numbers +Version: @to-be-replaced@ +Libs: -L${libdir} -ltommath +Cflags: -I${includedir} diff --git a/lib/hcrypto/libtommath/libtommath_VS2008.sln b/lib/hcrypto/libtommath/libtommath_VS2008.sln new file mode 100644 index 000000000..6bfc159b7 --- /dev/null +++ b/lib/hcrypto/libtommath/libtommath_VS2008.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tommath", "libtommath_VS2008.vcproj", "{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + 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}.Debug|x64.ActiveCfg = Debug|x64 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|x64.Build.0 = Debug|x64 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|Win32.ActiveCfg = Release|Win32 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|Win32.Build.0 = Release|Win32 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|x64.ActiveCfg = Release|x64 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {83B84178-7B4F-4B78-9C5D-17B8201D5B61} + EndGlobalSection +EndGlobal diff --git a/lib/hcrypto/libtommath/libtommath_VS2008.vcproj b/lib/hcrypto/libtommath/libtommath_VS2008.vcproj new file mode 100644 index 000000000..67cc89bf7 --- /dev/null +++ b/lib/hcrypto/libtommath/libtommath_VS2008.vcproj @@ -0,0 +1,966 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/hcrypto/libtommath/logs/README b/lib/hcrypto/libtommath/logs/README index 4c4e5f3aa..ea20c8137 100644 --- a/lib/hcrypto/libtommath/logs/README +++ b/lib/hcrypto/libtommath/logs/README @@ -1,13 +1,13 @@ -To use the pretty graphs you have to first build/run the ltmtest from the root directory of the package. -Todo this type - -make timing ; ltmtest - -in the root. It will run for a while [about ten minutes on most PCs] and produce a series of .log files in logs/. - -After doing that run "gnuplot graphs.dem" to make the PNGs. If you managed todo that all so far just open index.html to view -them all :-) - -Have fun - -Tom +To use the pretty graphs you have to first build/run the ltmtest from the root directory of the package. +Todo this type + +make timing ; ltmtest + +in the root. It will run for a while [about ten minutes on most PCs] and produce a series of .log files in logs/. + +After doing that run "gnuplot graphs.dem" to make the PNGs. If you managed todo that all so far just open index.html to view +them all :-) + +Have fun + +Tom \ No newline at end of file diff --git a/lib/hcrypto/libtommath/logs/add.log b/lib/hcrypto/libtommath/logs/add.log index 43503ac13..0ed7b70d9 100644 --- a/lib/hcrypto/libtommath/logs/add.log +++ b/lib/hcrypto/libtommath/logs/add.log @@ -1,16 +1,16 @@ -480 87 -960 111 -1440 135 -1920 159 -2400 200 -2880 224 -3360 248 -3840 272 -4320 296 -4800 320 -5280 344 -5760 368 -6240 392 -6720 416 -7200 440 -7680 464 + 480 48 + 960 61 + 1440 82 + 1920 97 + 2400 106 + 2880 112 + 3360 127 + 3840 130 + 4320 146 + 4800 157 + 5280 174 + 5760 185 + 6240 200 + 6720 214 + 7200 230 + 7680 244 diff --git a/lib/hcrypto/libtommath/logs/addsub.png b/lib/hcrypto/libtommath/logs/addsub.png index a5679ac563e6cf347bccc70fb4694ef684375ffc..b8ffef74b32056352e53c3e0fa25585fbf9cb658 100644 GIT binary patch literal 5921 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 I=akR{0J-&MHUIzs literal 6254 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 VShh6eoxKL~m#3?r%Q~loCIB}}tf2q^ diff --git a/lib/hcrypto/libtommath/logs/expt.log b/lib/hcrypto/libtommath/logs/expt.log index 70932abc4..2e5ee308f 100644 --- a/lib/hcrypto/libtommath/logs/expt.log +++ b/lib/hcrypto/libtommath/logs/expt.log @@ -1,7 +1,7 @@ -513 1435869 -769 3544970 -1025 7791638 -2049 46902238 -2561 85334899 -3073 141451412 -4097 308770310 + 513 446633 + 769 1110301 + 1025 2414927 + 2049 14870787 + 2561 26299761 + 3073 44323310 + 4097 98934292 diff --git a/lib/hcrypto/libtommath/logs/expt.png b/lib/hcrypto/libtommath/logs/expt.png index 9ee8bb769feaa56ee7cffbbd5c7d39ebdb4799d3..27c53eecf1afe22f40ccdb638942365ef595df77 100644 GIT binary patch literal 7290 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 E091w#RR910 literal 6605 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 literal 4918 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 U$&a5fFfcH9y85}Sb4q9e02Qlr#Q*>R diff --git a/lib/hcrypto/libtommath/logs/mult.log b/lib/hcrypto/libtommath/logs/mult.log index 33563fc67..841b40b96 100644 --- a/lib/hcrypto/libtommath/logs/mult.log +++ b/lib/hcrypto/libtommath/logs/mult.log @@ -1,84 +1,84 @@ -271 555 -390 855 -508 1161 -631 1605 -749 2117 -871 2687 -991 3329 -1108 4084 -1231 4786 -1351 5624 -1470 6392 -1586 7364 -1710 8218 -1830 9255 -1951 10217 -2067 11461 -2191 12463 -2308 13677 -2430 14800 -2551 16232 -2671 17460 -2791 18899 -2902 20247 -3028 21902 -3151 23240 -3267 24927 -3391 26441 -3511 28277 -3631 29838 -3749 31751 -3869 33673 -3989 35431 -4111 37518 -4231 39426 -4349 41504 -4471 43567 -4591 45786 -4711 47876 -4831 50299 -4951 52427 -5071 54785 -5189 57241 -5307 59730 -5431 62194 -5551 64761 -5670 67322 -5789 70073 -5907 72663 -6030 75437 -6151 78242 -6268 81202 -6389 83948 -6509 86985 -6631 89903 -6747 93184 -6869 96044 -6991 99286 -7109 102395 -7229 105917 -7351 108940 -7470 112490 -7589 115702 -7711 119508 -7831 122632 -7951 126410 -8071 129808 -8190 133895 -8311 137146 -8431 141218 -8549 144732 -8667 149131 -8790 152462 -8911 156754 -9030 160479 -9149 165138 -9271 168601 -9391 173185 -9511 176988 -9627 181976 -9751 185539 -9870 190388 -9991 194335 -10110 199605 -10228 203298 + 240 114 + 360 182 + 480 273 + 600 364 + 717 471 + 840 597 + 960 737 + 1080 881 + 1196 1041 + 1318 1215 + 1438 1405 + 1559 1600 + 1679 1812 + 1800 2045 + 1918 2289 + 2040 2534 + 2160 2800 + 2280 3067 + 2397 3375 + 2520 3678 + 2640 4007 + 2759 4325 + 2880 4851 + 3000 5200 + 3117 5557 + 3239 5938 + 3356 6332 + 3480 6741 + 3600 7168 + 3720 7597 + 3840 8054 + 3960 8514 + 4079 8956 + 4198 9451 + 4320 9976 + 4440 10457 + 4560 10973 + 4679 11535 + 4797 12085 + 4920 12639 + 5040 13235 + 5160 13832 + 5279 14454 + 5400 15063 + 5519 15657 + 5640 16339 + 5760 16992 + 5879 17676 + 6000 18380 + 6120 18022 + 6237 18567 + 6360 19259 + 6479 19929 + 6599 20686 + 6719 21180 + 6840 22121 + 6960 22741 + 7080 23664 + 7200 24315 + 7320 25107 + 7439 25945 + 7560 26557 + 7680 27527 + 7799 28341 + 7920 30761 + 8040 31648 + 8159 32628 + 8280 33498 + 8400 34508 + 8520 33657 + 8640 34566 + 8758 35203 + 8878 36356 + 9000 37379 + 9119 38072 + 9240 39390 + 9360 48931 + 9475 66682 + 9600 72564 + 9719 51493 + 9840 52637 + 9960 48247 + 10080 49030 + 10195 50592 diff --git a/lib/hcrypto/libtommath/logs/mult.png b/lib/hcrypto/libtommath/logs/mult.png index 4f7a4eed7b7f12e3713b6b3f7a2191305be31612..9681183a2168453f502f8f3de4cf759a5feca53d 100644 GIT binary patch literal 8308 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 diff --git a/lib/hcrypto/libtommath/logs/mult_kara.log b/lib/hcrypto/libtommath/logs/mult_kara.log index 7136c7931..91b59cbfd 100644 --- a/lib/hcrypto/libtommath/logs/mult_kara.log +++ b/lib/hcrypto/libtommath/logs/mult_kara.log @@ -1,84 +1,84 @@ -271 560 -391 870 -511 1159 -631 1605 -750 2111 -871 2737 -991 3361 -1111 4054 -1231 4778 -1351 5600 -1471 6404 -1591 7323 -1710 8255 -1831 9239 -1948 10257 -2070 11397 -2190 12531 -2308 13665 -2429 14870 -2550 16175 -2671 17539 -2787 18879 -2911 20350 -3031 21807 -3150 23415 -3270 24897 -3388 26567 -3511 28205 -3627 30076 -3751 31744 -3869 33657 -3991 35425 -4111 37522 -4229 39363 -4351 41503 -4470 43491 -4590 45827 -4711 47795 -4828 50166 -4951 52318 -5070 54911 -5191 57036 -5308 58237 -5431 60248 -5551 62678 -5671 64786 -5791 67294 -5908 69343 -6031 71607 -6151 74166 -6271 76590 -6391 78734 -6511 81175 -6631 83742 -6750 86403 -6868 88873 -6990 91150 -7110 94211 -7228 96922 -7351 99445 -7469 102216 -7589 104968 -7711 108113 -7827 110758 -7950 113714 -8071 116511 -8186 119643 -8310 122679 -8425 125581 -8551 128715 -8669 131778 -8788 135116 -8910 138138 -9031 141628 -9148 144754 -9268 148367 -9391 151551 -9511 155033 -9631 158652 -9751 162125 -9871 165248 -9988 168627 -10111 172427 -10231 176412 + 240 133 + 360 250 + 474 396 + 599 585 + 720 637 + 840 1045 + 960 1212 + 1080 1543 + 1196 1780 + 1320 2005 + 1436 2274 + 1560 2446 + 1680 1985 + 1800 2368 + 1920 2791 + 2038 3620 + 2160 3763 + 2278 3444 + 2400 4158 + 2516 5869 + 2640 6368 + 2753 5384 + 2876 7449 + 3000 6471 + 3114 8540 + 3240 7217 + 3360 9685 + 3476 6759 + 3599 8518 + 3714 8911 + 3840 12345 + 3960 9787 + 4079 11018 + 4196 12033 + 4319 12740 + 4440 12471 + 4558 15251 + 4678 13353 + 4798 15998 + 4920 13395 + 5040 13699 + 5160 14552 + 5280 14972 + 5400 15825 + 5520 16512 + 5639 17379 + 5757 17596 + 5879 18350 + 6000 18976 + 6115 19601 + 6240 20076 + 6354 20515 + 6480 21670 + 6600 22312 + 6716 22647 + 6839 23437 + 6960 24164 + 7080 24723 + 7199 25454 + 7320 26092 + 7440 26912 + 7557 27521 + 7677 28015 + 7800 28885 + 7919 29483 + 8040 30115 + 8160 31236 + 8280 31975 + 8400 30835 + 8520 31565 + 8639 32380 + 8760 32760 + 8879 33590 + 8996 34553 + 9119 35185 + 9239 36146 + 9358 36815 + 9480 39630 + 9596 43022 + 9720 41219 + 9840 41596 + 9960 42354 + 10080 43352 + 10200 43915 diff --git a/lib/hcrypto/libtommath/logs/sqr.log b/lib/hcrypto/libtommath/logs/sqr.log index cd29fc5c1..93234a145 100644 --- a/lib/hcrypto/libtommath/logs/sqr.log +++ b/lib/hcrypto/libtommath/logs/sqr.log @@ -1,84 +1,84 @@ -265 562 -389 882 -509 1207 -631 1572 -750 1990 -859 2433 -991 2894 -1109 3555 -1230 4228 -1350 5018 -1471 5805 -1591 6579 -1709 7415 -1829 8329 -1949 9225 -2071 10139 -2188 11239 -2309 12178 -2431 13212 -2551 14294 -2671 15551 -2791 16512 -2911 17718 -3030 18876 -3150 20259 -3270 21374 -3391 22650 -3511 23948 -3631 25493 -3750 26756 -3870 28225 -3989 29705 -4110 31409 -4230 32834 -4351 34327 -4471 35818 -4591 37636 -4711 39228 -4830 40868 -4949 42393 -5070 44541 -5191 46269 -5310 48162 -5429 49728 -5548 51985 -5671 53948 -5791 55885 -5910 57584 -6031 60082 -6150 62239 -6270 64309 -6390 66014 -6511 68766 -6631 71012 -6750 73172 -6871 74952 -6991 77909 -7111 80371 -7231 82666 -7351 84531 -7469 87698 -7589 90318 -7711 225384 -7830 232428 -7950 240009 -8070 246522 -8190 253662 -8310 260961 -8431 269253 -8549 275743 -8671 283769 -8789 290811 -8911 300034 -9030 306873 -9149 315085 -9270 323944 -9390 332390 -9508 337519 -9631 348986 -9749 356904 -9871 367013 -9989 373831 -10108 381033 -10230 393475 + 240 114 + 359 174 + 478 241 + 600 311 + 720 399 + 840 494 + 960 599 + 1080 799 + 1200 931 + 1320 911 + 1440 1016 + 1560 1143 + 1680 1281 + 1800 1459 + 1918 1617 + 2039 1763 + 2159 1913 + 2279 2071 + 2399 2240 + 2518 2412 + 2640 2600 + 2760 2792 + 2877 3008 + 2999 3220 + 3119 3405 + 3239 3637 + 3359 3859 + 3480 4094 + 3600 4328 + 3717 4571 + 3838 4840 + 3960 5098 + 4080 5349 + 4200 5617 + 4320 5891 + 4440 6147 + 4560 6444 + 4680 6745 + 4800 7057 + 4918 7317 + 5039 7637 + 5160 12833 + 5280 10098 + 5397 8666 + 5520 8999 + 5639 9376 + 5758 9727 + 5880 9996 + 6000 10427 + 6118 10868 + 6240 12218 + 6359 14010 + 6478 14838 + 6593 16135 + 6719 16503 + 6840 13267 + 6960 13648 + 7080 14118 + 7199 14525 + 7320 14803 + 7439 15378 + 7558 15871 + 7680 57530 + 7800 59550 + 7916 61091 + 8039 63004 + 8160 61136 + 8279 62803 + 8398 68671 + 8520 71001 + 8638 71537 + 8759 74757 + 8880 77164 + 9000 78963 + 9119 80982 + 9239 83142 + 9357 85292 + 9480 88190 + 9600 90343 + 9718 86710 + 9840 88818 + 9954 91034 + 10079 93350 + 10197 95592 diff --git a/lib/hcrypto/libtommath/logs/sqr_kara.log b/lib/hcrypto/libtommath/logs/sqr_kara.log index 06355a76d..da108973f 100644 --- a/lib/hcrypto/libtommath/logs/sqr_kara.log +++ b/lib/hcrypto/libtommath/logs/sqr_kara.log @@ -1,84 +1,84 @@ -271 560 -388 878 -511 1179 -629 1625 -751 1988 -871 2423 -989 2896 -1111 3561 -1231 4209 -1350 5015 -1470 5804 -1591 6556 -1709 7420 -1831 8263 -1951 9173 -2070 10153 -2191 11229 -2310 12167 -2431 13211 -2550 14309 -2671 15524 -2788 16525 -2910 17712 -3028 18822 -3148 20220 -3271 21343 -3391 22652 -3511 23944 -3630 25485 -3750 26778 -3868 28201 -3990 29653 -4111 31393 -4225 32841 -4350 34328 -4471 35786 -4590 37652 -4711 39245 -4830 40876 -4951 42433 -5068 44547 -5191 46321 -5311 48140 -5430 49727 -5550 52034 -5671 53954 -5791 55921 -5908 57597 -6031 60084 -6148 62226 -6270 64295 -6390 66045 -6511 68779 -6629 71003 -6751 73169 -6871 74992 -6991 77895 -7110 80376 -7231 82628 -7351 84468 -7470 87664 -7591 90284 -7711 91352 -7828 93995 -7950 96276 -8071 98691 -8190 101256 -8308 103631 -8431 105222 -8550 108343 -8671 110281 -8787 112764 -8911 115397 -9031 117690 -9151 120266 -9271 122715 -9391 124624 -9510 127937 -9630 130313 -9750 132914 -9871 136129 -9991 138517 -10108 141525 -10231 144225 + 240 115 + 360 175 + 480 241 + 600 312 + 719 397 + 839 494 + 960 597 + 1080 696 + 1200 794 + 1320 908 + 1439 1022 + 1560 1141 + 1678 1284 + 1797 1461 + 1918 1590 + 2040 1764 + 2160 1911 + 2278 2072 + 2399 2263 + 2516 2425 + 2640 2627 + 2756 2809 + 2880 3017 + 3000 3220 + 3119 3413 + 3239 3627 + 3359 3864 + 3479 4087 + 3600 4327 + 3720 4603 + 3840 4867 + 3957 5095 + 4079 5079 + 4200 5623 + 4319 5878 + 4439 6177 + 4560 6467 + 4679 6749 + 4800 7056 + 4920 7384 + 5039 7681 + 5159 8004 + 5280 8332 + 5399 8664 + 5520 8929 + 5638 9340 + 5760 9631 + 5879 10109 + 5999 10458 + 6118 10816 + 6240 11215 + 6359 11550 + 6478 11958 + 6600 12390 + 6718 12801 + 6838 13197 + 6959 13609 + 7079 14033 + 7199 16182 + 7320 16539 + 7440 16952 + 7559 16255 + 7679 17593 + 7800 17107 + 7920 17362 + 8037 17723 + 8159 18072 + 8280 19804 + 8399 18966 + 8519 19510 + 8640 19958 + 8760 20364 + 8878 20674 + 9000 21682 + 9120 21665 + 9237 21945 + 9359 22394 + 9480 23105 + 9598 23334 + 9718 25301 + 9840 26053 + 9960 26565 + 10079 26812 + 10200 27300 diff --git a/lib/hcrypto/libtommath/logs/sub.log b/lib/hcrypto/libtommath/logs/sub.log index 9f84fa2ef..87c0160f8 100644 --- a/lib/hcrypto/libtommath/logs/sub.log +++ b/lib/hcrypto/libtommath/logs/sub.log @@ -1,16 +1,16 @@ -480 94 -960 116 -1440 140 -1920 164 -2400 205 -2880 229 -3360 253 -3840 277 -4320 299 -4800 321 -5280 345 -5760 371 -6240 395 -6720 419 -7200 441 -7680 465 + 480 36 + 960 51 + 1440 64 + 1920 78 + 2400 90 + 2880 105 + 3360 118 + 3840 133 + 4320 146 + 4800 161 + 5280 182 + 5760 201 + 6240 201 + 6720 214 + 7200 228 + 7680 243 diff --git a/lib/hcrypto/libtommath/makefile b/lib/hcrypto/libtommath/makefile index 3e254d475..be9fac657 100644 --- a/lib/hcrypto/libtommath/makefile +++ b/lib/hcrypto/libtommath/makefile @@ -2,42 +2,10 @@ # #Tom St Denis -#version of library -VERSION=0.41 - -CFLAGS += -I./ -Wall -W -Wshadow -Wsign-compare - -ifndef MAKE - MAKE=make -endif - -ifndef IGNORE_SPEED - -#for speed -CFLAGS += -O3 -funroll-loops - -#for size -#CFLAGS += -Os - -#x86 optimizations [should be valid for any GCC install though] -CFLAGS += -fomit-frame-pointer - -#debug -#CFLAGS += -g3 - -endif - -#install as this user -ifndef INSTALL_GROUP - GROUP=wheel +ifeq ($V,1) +silent= else - GROUP=$(INSTALL_GROUP) -endif - -ifndef INSTALL_USER - USER=root -else - USER=$(INSTALL_USER) +silent=@ endif #default files to install @@ -45,142 +13,153 @@ ifndef LIBNAME LIBNAME=libtommath.a endif -default: ${LIBNAME} +coverage: LIBNAME:=-Wl,--whole-archive $(LIBNAME) -Wl,--no-whole-archive -HEADERS=tommath.h tommath_class.h tommath_superclass.h +include makefile_include.mk -#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 +%.o: %.c $(HEADERS) +ifneq ($V,1) + @echo " * ${CC} $@" +endif + ${silent} ${CC} -c ${LTM_CFLAGS} $< -o $@ -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 +LCOV_ARGS=--directory . + +#START_INS +OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ +bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ +bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ +bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ +bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ +bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ +bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \ +bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \ +bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \ +bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \ +bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \ +bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \ +bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \ +bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \ +bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \ +bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \ +bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \ +bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \ +bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \ +bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \ +bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \ +bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \ +bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \ +bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ +bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ +bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ +bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ +bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ +bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o + +#END_INS $(LIBNAME): $(OBJECTS) $(AR) $(ARFLAGS) $@ $(OBJECTS) - ranlib $@ + $(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 + ./timing + rm -f *.a *.o timing make CFLAGS="$(CFLAGS) -fbranch-probabilities" -#make a single object profiled library +#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 + $(CC) $(LTM_CFLAGS) -fprofile-arcs -DTESTING -c mpi.c -o mpi.o + $(CC) $(LTM_CFLAGS) -DTESTING -DTIMER demo/timing.c mpi.o -lgcov -o timing + ./timing + rm -f *.o timing + $(CC) $(LTM_CFLAGS) -fbranch-probabilities -DTESTING -c mpi.c -o mpi.o $(AR) $(ARFLAGS) $(LIBNAME) mpi.o - ranlib $(LIBNAME) + 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) + install -d $(DESTDIR)$(LIBPATH) + install -d $(DESTDIR)$(INCPATH) + install -m 644 $(LIBNAME) $(DESTDIR)$(LIBPATH) + install -m 644 $(HEADERS_PUB) $(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 +uninstall: + rm $(DESTDIR)$(LIBPATH)/$(LIBNAME) + rm $(HEADERS_PUB:%=$(DESTDIR)$(INCPATH)/%) -# 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 +test_standalone: test + @echo "test_standalone is deprecated, please use make-target 'test'" -# poster, makes the single page PDF poster -poster: poster.tex - pdflatex poster - rm -f poster.aux poster.log +DEMOS=test mtest_opponent -# 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 +define DEMO_template +$(1): demo/$(1).o demo/shared.o $$(LIBNAME) + $$(CC) $$(LTM_CFLAGS) $$(LTM_LFLAGS) $$^ -o $$@ +endef -#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 +$(foreach demo, $(strip $(DEMOS)), $(eval $(call DEMO_template,$(demo)))) -pretty: - perl pretty.build +.PHONY: mtest +mtest: + cd mtest ; $(CC) $(LTM_CFLAGS) -O0 mtest.c $(LTM_LFLAGS) -o mtest -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 +timing: $(LIBNAME) demo/timing.c + $(CC) $(LTM_CFLAGS) -DTIMER demo/timing.c $(LIBNAME) $(LTM_LFLAGS) -o timing -#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 +tune: $(LIBNAME) + $(MAKE) -C etc tune CFLAGS="$(LTM_CFLAGS)" + $(MAKE) -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) +# You have to create a file .coveralls.yml with the content "repo_token: " +# in the base folder to be able to submit to coveralls +coveralls: lcov + coveralls-lcov + +docs manual: + $(MAKE) -C doc/ $@ V=$(V) + +.PHONY: pre_gen +pre_gen: + mkdir -p pre_gen + perl gen.pl + sed -e 's/[[:blank:]]*$$//' mpi.c > pre_gen/mpi.c + rm mpi.c + +zipup: clean astyle new_file docs + @# Update the index, so diff-index won't fail in case the pdf has been created. + @# As the pdf creation modifies the tex files, git sometimes detects the + @# modified files, but misses that it's put back to its original version. + @git update-index --refresh + @git diff-index --quiet HEAD -- || ( echo "FAILURE: uncommited changes or not a git" && exit 1 ) + rm -rf libtommath-$(VERSION) ltm-$(VERSION).* + @# files/dirs excluded from "git archive" are defined in .gitattributes + git archive --format=tar --prefix=libtommath-$(VERSION)/ HEAD | tar x + @echo 'fixme check' + -@(find libtommath-$(VERSION)/ -type f | xargs grep 'FIXM[E]') && echo '############## BEWARE: the "fixme" marker was found !!! ##############' || true + mkdir -p libtommath-$(VERSION)/doc + cp doc/bn.pdf libtommath-$(VERSION)/doc/ + $(MAKE) -C libtommath-$(VERSION)/ pre_gen + tar -c libtommath-$(VERSION)/ | xz -6e -c - > ltm-$(VERSION).tar.xz + zip -9rq ltm-$(VERSION).zip libtommath-$(VERSION) + cp doc/bn.pdf bn-$(VERSION).pdf + rm -rf libtommath-$(VERSION) + gpg -b -a ltm-$(VERSION).tar.xz + gpg -b -a ltm-$(VERSION).zip + +new_file: + perl helper.pl --update-files + +perlcritic: + perlcritic *.pl doc/*.pl + +astyle: + @echo " * run astyle on all sources" + @astyle --options=astylerc --formatted $(OBJECTS:.o=.c) tommath*.h demo/*.c etc/*.c mtest/mtest.c diff --git a/lib/hcrypto/libtommath/makefile.bcc b/lib/hcrypto/libtommath/makefile.bcc deleted file mode 100644 index 67743d962..000000000 --- a/lib/hcrypto/libtommath/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/lib/hcrypto/libtommath/makefile.cygwin_dll b/lib/hcrypto/libtommath/makefile.cygwin_dll deleted file mode 100644 index 85a9b2053..000000000 --- a/lib/hcrypto/libtommath/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/lib/hcrypto/libtommath/makefile.icc b/lib/hcrypto/libtommath/makefile.icc deleted file mode 100644 index cf70ab0c2..000000000 --- a/lib/hcrypto/libtommath/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/lib/hcrypto/libtommath/makefile.mingw b/lib/hcrypto/libtommath/makefile.mingw new file mode 100644 index 000000000..7eee57dc4 --- /dev/null +++ b/lib/hcrypto/libtommath/makefile.mingw @@ -0,0 +1,109 @@ +# MAKEFILE for MS Windows (mingw + gcc + gmake) +# +# BEWARE: variable OBJECTS is updated via helper.pl + +### USAGE: +# Open a command prompt with gcc + gmake in PATH and start: +# +# gmake -f makefile.mingw all +# test.exe +# gmake -f makefile.mingw PREFIX=c:\devel\libtom install + +#The following can be overridden from command line e.g. make -f makefile.mingw CC=gcc ARFLAGS=rcs +PREFIX = c:\mingw +CC = gcc +AR = ar +ARFLAGS = r +RANLIB = ranlib +STRIP = strip +CFLAGS = -O2 +LDFLAGS = + +#Compilation flags +LTM_CFLAGS = -I. $(CFLAGS) +LTM_LDFLAGS = $(LDFLAGS) -static-libgcc + +#Libraries to be created +LIBMAIN_S =libtommath.a +LIBMAIN_I =libtommath.dll.a +LIBMAIN_D =libtommath.dll + +#List of objects to compile (all goes to libtommath.a) +OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ +bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ +bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ +bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ +bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ +bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ +bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \ +bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \ +bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \ +bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \ +bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \ +bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \ +bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \ +bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \ +bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \ +bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \ +bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \ +bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \ +bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \ +bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \ +bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \ +bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \ +bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \ +bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ +bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ +bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ +bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ +bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ +bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o + +HEADERS_PUB=tommath.h +HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) + +#The default rule for make builds the libtommath.a library (static) +default: $(LIBMAIN_S) + +#Dependencies on *.h +$(OBJECTS): $(HEADERS) + +.c.o: + $(CC) $(LTM_CFLAGS) -c $< -o $@ + +#Create libtommath.a +$(LIBMAIN_S): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $(OBJECTS) + $(RANLIB) $@ + +#Create DLL + import library libtommath.dll.a +$(LIBMAIN_D) $(LIBMAIN_I): $(OBJECTS) + $(CC) -s -shared -o $(LIBMAIN_D) $^ -Wl,--enable-auto-import,--export-all -Wl,--out-implib=$(LIBMAIN_I) $(LTM_LDFLAGS) + $(STRIP) -S $(LIBMAIN_D) + +#Build test suite +test.exe: demo/shared.o demo/test.o $(LIBMAIN_S) + $(CC) $(LTM_CFLAGS) $(LTM_LDFLAGS) $^ -o $@ + @echo NOTICE: start the tests by launching test.exe + +test_standalone: test.exe + @echo test_standalone is deprecated, please use make-target 'test.exe' + +all: $(LIBMAIN_S) test.exe + +tune: $(LIBNAME_S) + $(MAKE) -C etc tune + $(MAKE) + +clean: + @-cmd /c del /Q /S *.o *.a *.exe *.dll 2>nul + +#Install the library + headers +install: $(LIBMAIN_S) $(LIBMAIN_I) $(LIBMAIN_D) + cmd /c if not exist "$(PREFIX)\bin" mkdir "$(PREFIX)\bin" + cmd /c if not exist "$(PREFIX)\lib" mkdir "$(PREFIX)\lib" + cmd /c if not exist "$(PREFIX)\include" mkdir "$(PREFIX)\include" + copy /Y $(LIBMAIN_S) "$(PREFIX)\lib" + copy /Y $(LIBMAIN_I) "$(PREFIX)\lib" + copy /Y $(LIBMAIN_D) "$(PREFIX)\bin" + copy /Y tommath*.h "$(PREFIX)\include" diff --git a/lib/hcrypto/libtommath/makefile.msvc b/lib/hcrypto/libtommath/makefile.msvc index 5edebec92..aa8d8bec1 100644 --- a/lib/hcrypto/libtommath/makefile.msvc +++ b/lib/hcrypto/libtommath/makefile.msvc @@ -1,40 +1,93 @@ -#MSVC Makefile +# MAKEFILE for MS Windows (nmake + Windows SDK) # -#Tom St Denis +# BEWARE: variable OBJECTS is updated via helper.pl -CFLAGS = /I. /Ox /DWIN32 /W3 /Fo$@ +### USAGE: +# Open a command prompt with WinSDK variables set and start: +# +# nmake -f makefile.msvc all +# test.exe +# nmake -f makefile.msvc PREFIX=c:\devel\libtom install -default: library +#The following can be overridden from command line e.g. make -f makefile.msvc CC=gcc ARFLAGS=rcs +PREFIX = c:\devel +CFLAGS = /Ox -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 +#Compilation flags +LTM_CFLAGS = /nologo /I./ /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_DEPRECATE /D__STDC_WANT_SECURE_LIB__=1 /D_CRT_HAS_CXX17=0 /Wall /wd4146 /wd4127 /wd4668 /wd4710 /wd4711 /wd4820 /wd5045 /WX $(CFLAGS) +LTM_LDFLAGS = advapi32.lib -HEADERS=tommath.h tommath_class.h tommath_superclass.h +#Libraries to be created (this makefile builds only static libraries) +LIBMAIN_S =tommath.lib -library: $(OBJECTS) - lib /out:tommath.lib $(OBJECTS) +#List of objects to compile (all goes to tommath.lib) +OBJECTS=bn_cutoffs.obj bn_deprecated.obj bn_mp_2expt.obj bn_mp_abs.obj bn_mp_add.obj bn_mp_add_d.obj bn_mp_addmod.obj \ +bn_mp_and.obj bn_mp_clamp.obj bn_mp_clear.obj bn_mp_clear_multi.obj bn_mp_cmp.obj bn_mp_cmp_d.obj bn_mp_cmp_mag.obj \ +bn_mp_cnt_lsb.obj bn_mp_complement.obj bn_mp_copy.obj bn_mp_count_bits.obj bn_mp_decr.obj bn_mp_div.obj bn_mp_div_2.obj \ +bn_mp_div_2d.obj bn_mp_div_3.obj bn_mp_div_d.obj bn_mp_dr_is_modulus.obj bn_mp_dr_reduce.obj bn_mp_dr_setup.obj \ +bn_mp_error_to_string.obj bn_mp_exch.obj bn_mp_expt_u32.obj bn_mp_exptmod.obj bn_mp_exteuclid.obj bn_mp_fread.obj \ +bn_mp_from_sbin.obj bn_mp_from_ubin.obj bn_mp_fwrite.obj bn_mp_gcd.obj bn_mp_get_double.obj bn_mp_get_i32.obj \ +bn_mp_get_i64.obj bn_mp_get_l.obj bn_mp_get_ll.obj bn_mp_get_mag_u32.obj bn_mp_get_mag_u64.obj bn_mp_get_mag_ul.obj \ +bn_mp_get_mag_ull.obj bn_mp_grow.obj bn_mp_incr.obj bn_mp_init.obj bn_mp_init_copy.obj bn_mp_init_i32.obj \ +bn_mp_init_i64.obj bn_mp_init_l.obj bn_mp_init_ll.obj bn_mp_init_multi.obj bn_mp_init_set.obj bn_mp_init_size.obj \ +bn_mp_init_u32.obj bn_mp_init_u64.obj bn_mp_init_ul.obj bn_mp_init_ull.obj bn_mp_invmod.obj bn_mp_is_square.obj \ +bn_mp_iseven.obj bn_mp_isodd.obj bn_mp_kronecker.obj bn_mp_lcm.obj bn_mp_log_u32.obj bn_mp_lshd.obj bn_mp_mod.obj \ +bn_mp_mod_2d.obj bn_mp_mod_d.obj bn_mp_montgomery_calc_normalization.obj bn_mp_montgomery_reduce.obj \ +bn_mp_montgomery_setup.obj bn_mp_mul.obj bn_mp_mul_2.obj bn_mp_mul_2d.obj bn_mp_mul_d.obj bn_mp_mulmod.obj bn_mp_neg.obj \ +bn_mp_or.obj bn_mp_pack.obj bn_mp_pack_count.obj bn_mp_prime_fermat.obj bn_mp_prime_frobenius_underwood.obj \ +bn_mp_prime_is_prime.obj bn_mp_prime_miller_rabin.obj bn_mp_prime_next_prime.obj \ +bn_mp_prime_rabin_miller_trials.obj bn_mp_prime_rand.obj bn_mp_prime_strong_lucas_selfridge.obj \ +bn_mp_radix_size.obj bn_mp_radix_smap.obj bn_mp_rand.obj bn_mp_read_radix.obj bn_mp_reduce.obj bn_mp_reduce_2k.obj \ +bn_mp_reduce_2k_l.obj bn_mp_reduce_2k_setup.obj bn_mp_reduce_2k_setup_l.obj bn_mp_reduce_is_2k.obj \ +bn_mp_reduce_is_2k_l.obj bn_mp_reduce_setup.obj bn_mp_root_u32.obj bn_mp_rshd.obj bn_mp_sbin_size.obj bn_mp_set.obj \ +bn_mp_set_double.obj bn_mp_set_i32.obj bn_mp_set_i64.obj bn_mp_set_l.obj bn_mp_set_ll.obj bn_mp_set_u32.obj \ +bn_mp_set_u64.obj bn_mp_set_ul.obj bn_mp_set_ull.obj bn_mp_shrink.obj bn_mp_signed_rsh.obj bn_mp_sqr.obj \ +bn_mp_sqrmod.obj bn_mp_sqrt.obj bn_mp_sqrtmod_prime.obj bn_mp_sub.obj bn_mp_sub_d.obj bn_mp_submod.obj \ +bn_mp_to_radix.obj bn_mp_to_sbin.obj bn_mp_to_ubin.obj bn_mp_ubin_size.obj bn_mp_unpack.obj bn_mp_xor.obj bn_mp_zero.obj \ +bn_prime_tab.obj bn_s_mp_add.obj bn_s_mp_balance_mul.obj bn_s_mp_exptmod.obj bn_s_mp_exptmod_fast.obj \ +bn_s_mp_get_bit.obj bn_s_mp_invmod_fast.obj bn_s_mp_invmod_slow.obj bn_s_mp_karatsuba_mul.obj \ +bn_s_mp_karatsuba_sqr.obj bn_s_mp_montgomery_reduce_fast.obj bn_s_mp_mul_digs.obj bn_s_mp_mul_digs_fast.obj \ +bn_s_mp_mul_high_digs.obj bn_s_mp_mul_high_digs_fast.obj bn_s_mp_prime_is_divisible.obj \ +bn_s_mp_rand_jenkins.obj bn_s_mp_rand_platform.obj bn_s_mp_reverse.obj bn_s_mp_sqr.obj bn_s_mp_sqr_fast.obj \ +bn_s_mp_sub.obj bn_s_mp_toom_mul.obj bn_s_mp_toom_sqr.obj + +HEADERS_PUB=tommath.h +HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) + +#The default rule for make builds the tommath.lib library (static) +default: $(LIBMAIN_S) + +#Dependencies on *.h +$(OBJECTS): $(HEADERS) + +.c.obj: + $(CC) $(LTM_CFLAGS) /c $< /Fo$@ + +#Create tommath.lib +$(LIBMAIN_S): $(OBJECTS) + lib /out:$(LIBMAIN_S) $(OBJECTS) + +#Build test suite +test.exe: $(LIBMAIN_S) demo/shared.obj demo/test.obj + cl $(LTM_CFLAGS) $(TOBJECTS) $(LIBMAIN_S) $(LTM_LDFLAGS) demo/shared.c demo/test.c /Fe$@ + @echo NOTICE: start the tests by launching test.exe + +test_standalone: test.exe + @echo test_standalone is deprecated, please use make-target 'test.exe' + +all: $(LIBMAIN_S) test.exe + +tune: $(LIBMAIN_S) + $(MAKE) -C etc tune + $(MAKE) + +clean: + @-cmd /c del /Q /S *.OBJ *.LIB *.EXE *.DLL 2>nul + +#Install the library + headers +install: $(LIBMAIN_S) + cmd /c if not exist "$(PREFIX)\bin" mkdir "$(PREFIX)\bin" + cmd /c if not exist "$(PREFIX)\lib" mkdir "$(PREFIX)\lib" + cmd /c if not exist "$(PREFIX)\include" mkdir "$(PREFIX)\include" + copy /Y $(LIBMAIN_S) "$(PREFIX)\lib" + copy /Y tommath*.h "$(PREFIX)\include" diff --git a/lib/hcrypto/libtommath/makefile.shared b/lib/hcrypto/libtommath/makefile.shared index f17bbbd48..680210736 100644 --- a/lib/hcrypto/libtommath/makefile.shared +++ b/lib/hcrypto/libtommath/makefile.shared @@ -1,102 +1,99 @@ #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 + +include makefile_include.mk + + +ifndef LIBTOOL + ifeq ($(PLATFORM), Darwin) + LIBTOOL:=glibtool + else + LIBTOOL:=libtool + endif endif -HEADERS=tommath.h tommath_class.h tommath_superclass.h +LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(CC) +LTLINK = $(LIBTOOL) --mode=link --tag=CC $(CC) -#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 +LCOV_ARGS=--directory .libs --directory . -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 +#START_INS +OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ +bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ +bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ +bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ +bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ +bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ +bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \ +bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \ +bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \ +bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \ +bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \ +bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \ +bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \ +bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \ +bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \ +bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \ +bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \ +bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \ +bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \ +bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \ +bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \ +bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \ +bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \ +bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ +bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ +bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ +bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ +bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ +bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o + +#END_INS objs: $(OBJECTS) +.c.o: $(HEADERS) + $(LTCOMPILE) $(LTM_CFLAGS) $(LTM_LDFLAGS) -o $@ -c $< + +LOBJECTS = $(OBJECTS:.o=.lo) + $(LIBNAME): $(OBJECTS) - libtool --mode=link gcc *.lo -o $(LIBNAME) -rpath $(LIBPATH) -version-info $(VERSION) + $(LTLINK) $(LTM_LDFLAGS) $(LOBJECTS) -o $(LIBNAME) -rpath $(LIBPATH) -version-info $(VERSION_SO) $(LTM_LIBTOOLFLAGS) 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) + install -d $(DESTDIR)$(LIBPATH) + install -d $(DESTDIR)$(INCPATH) + $(LIBTOOL) --mode=install install -m 644 $(LIBNAME) $(DESTDIR)$(LIBPATH)/$(LIBNAME) + install -m 644 $(HEADERS_PUB) $(DESTDIR)$(INCPATH) + sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION_PC),' libtommath.pc.in > libtommath.pc + install -d $(DESTDIR)$(LIBPATH)/pkgconfig + install -m 644 libtommath.pc $(DESTDIR)$(LIBPATH)/pkgconfig/ -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 +uninstall: + $(LIBTOOL) --mode=uninstall rm $(DESTDIR)$(LIBPATH)/$(LIBNAME) + rm $(HEADERS_PUB:%=$(DESTDIR)$(INCPATH)/%) + rm $(DESTDIR)$(LIBPATH)/pkgconfig/libtommath.pc + +test_standalone: test + @echo "test_standalone is deprecated, please use make-target 'test'" + +test mtest_opponent: demo/shared.o $(LIBNAME) | demo/test.o demo/mtest_opponent.o + $(LTLINK) $(LTM_LDFLAGS) demo/$@.o $^ -o $@ + +.PHONY: mtest +mtest: + cd mtest ; $(CC) $(LTM_CFLAGS) -O0 mtest.c $(LTM_LDFLAGS) -o mtest + +timing: $(LIBNAME) demo/timing.c + $(LTLINK) $(LTM_CFLAGS) $(LTM_LDFLAGS) -DTIMER demo/timing.c $(LIBNAME) -o timing + +tune: $(LIBNAME) + $(LTCOMPILE) $(LTM_CFLAGS) -c etc/tune.c -o etc/tune.o + $(LTLINK) $(LTM_LDFLAGS) -o etc/tune etc/tune.o $(LIBNAME) + cd etc/; /bin/sh tune_it.sh; cd .. + $(MAKE) -f makefile.shared diff --git a/lib/hcrypto/libtommath/makefile.unix b/lib/hcrypto/libtommath/makefile.unix new file mode 100644 index 000000000..4cefc7e17 --- /dev/null +++ b/lib/hcrypto/libtommath/makefile.unix @@ -0,0 +1,106 @@ +# MAKEFILE that is intended to be compatible with any kind of make (GNU make, BSD make, ...) +# works on: Linux, *BSD, Cygwin, AIX, HP-UX and hopefully other UNIX systems +# +# Please do not use here neither any special make syntax nor any unusual tools/utilities! + +# using ICC compiler: +# make -f makefile.unix CC=icc CFLAGS="-O3 -xP -ip" + +# using Borland C++Builder: +# make -f makefile.unix CC=bcc32 + +#The following can be overridden from command line e.g. "make -f makefile.unix CC=gcc ARFLAGS=rcs" +DESTDIR = +PREFIX = /usr/local +LIBPATH = $(PREFIX)/lib +INCPATH = $(PREFIX)/include +CC = cc +AR = ar +ARFLAGS = r +RANLIB = ranlib +CFLAGS = -O2 +LDFLAGS = + +VERSION = 1.2.0 + +#Compilation flags +LTM_CFLAGS = -I. $(CFLAGS) +LTM_LDFLAGS = $(LDFLAGS) + +#Library to be created (this makefile builds only static library) +LIBMAIN_S = libtommath.a + +OBJECTS=bn_cutoffs.o bn_deprecated.o bn_mp_2expt.o bn_mp_abs.o bn_mp_add.o bn_mp_add_d.o bn_mp_addmod.o \ +bn_mp_and.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o bn_mp_cmp.o bn_mp_cmp_d.o bn_mp_cmp_mag.o \ +bn_mp_cnt_lsb.o bn_mp_complement.o bn_mp_copy.o bn_mp_count_bits.o bn_mp_decr.o bn_mp_div.o bn_mp_div_2.o \ +bn_mp_div_2d.o bn_mp_div_3.o bn_mp_div_d.o bn_mp_dr_is_modulus.o bn_mp_dr_reduce.o bn_mp_dr_setup.o \ +bn_mp_error_to_string.o bn_mp_exch.o bn_mp_expt_u32.o bn_mp_exptmod.o bn_mp_exteuclid.o bn_mp_fread.o \ +bn_mp_from_sbin.o bn_mp_from_ubin.o bn_mp_fwrite.o bn_mp_gcd.o bn_mp_get_double.o bn_mp_get_i32.o \ +bn_mp_get_i64.o bn_mp_get_l.o bn_mp_get_ll.o bn_mp_get_mag_u32.o bn_mp_get_mag_u64.o bn_mp_get_mag_ul.o \ +bn_mp_get_mag_ull.o bn_mp_grow.o bn_mp_incr.o bn_mp_init.o bn_mp_init_copy.o bn_mp_init_i32.o \ +bn_mp_init_i64.o bn_mp_init_l.o bn_mp_init_ll.o bn_mp_init_multi.o bn_mp_init_set.o bn_mp_init_size.o \ +bn_mp_init_u32.o bn_mp_init_u64.o bn_mp_init_ul.o bn_mp_init_ull.o bn_mp_invmod.o bn_mp_is_square.o \ +bn_mp_iseven.o bn_mp_isodd.o bn_mp_kronecker.o bn_mp_lcm.o bn_mp_log_u32.o bn_mp_lshd.o bn_mp_mod.o \ +bn_mp_mod_2d.o bn_mp_mod_d.o bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o \ +bn_mp_montgomery_setup.o bn_mp_mul.o bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_neg.o \ +bn_mp_or.o bn_mp_pack.o bn_mp_pack_count.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o \ +bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \ +bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \ +bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_reduce.o bn_mp_reduce_2k.o \ +bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o \ +bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_root_u32.o bn_mp_rshd.o bn_mp_sbin_size.o bn_mp_set.o \ +bn_mp_set_double.o bn_mp_set_i32.o bn_mp_set_i64.o bn_mp_set_l.o bn_mp_set_ll.o bn_mp_set_u32.o \ +bn_mp_set_u64.o bn_mp_set_ul.o bn_mp_set_ull.o bn_mp_shrink.o bn_mp_signed_rsh.o bn_mp_sqr.o \ +bn_mp_sqrmod.o bn_mp_sqrt.o bn_mp_sqrtmod_prime.o bn_mp_sub.o bn_mp_sub_d.o bn_mp_submod.o \ +bn_mp_to_radix.o bn_mp_to_sbin.o bn_mp_to_ubin.o bn_mp_ubin_size.o bn_mp_unpack.o bn_mp_xor.o bn_mp_zero.o \ +bn_prime_tab.o bn_s_mp_add.o bn_s_mp_balance_mul.o bn_s_mp_exptmod.o bn_s_mp_exptmod_fast.o \ +bn_s_mp_get_bit.o bn_s_mp_invmod_fast.o bn_s_mp_invmod_slow.o bn_s_mp_karatsuba_mul.o \ +bn_s_mp_karatsuba_sqr.o bn_s_mp_montgomery_reduce_fast.o bn_s_mp_mul_digs.o bn_s_mp_mul_digs_fast.o \ +bn_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs_fast.o bn_s_mp_prime_is_divisible.o \ +bn_s_mp_rand_jenkins.o bn_s_mp_rand_platform.o bn_s_mp_reverse.o bn_s_mp_sqr.o bn_s_mp_sqr_fast.o \ +bn_s_mp_sub.o bn_s_mp_toom_mul.o bn_s_mp_toom_sqr.o + +HEADERS_PUB=tommath.h +HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) + +#The default rule for make builds the libtommath.a library (static) +default: $(LIBMAIN_S) + +#Dependencies on *.h +$(OBJECTS): $(HEADERS) + +#This is necessary for compatibility with BSD make (namely on OpenBSD) +.SUFFIXES: .o .c +.c.o: + $(CC) $(LTM_CFLAGS) -c $< -o $@ + +#Create libtommath.a +$(LIBMAIN_S): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $(OBJECTS) + $(RANLIB) $@ + +#Build test_standalone suite +test: demo/shared.o demo/test.o $(LIBMAIN_S) + $(CC) $(LTM_CFLAGS) $(LTM_LDFLAGS) $^ -o $@ + @echo "NOTICE: start the tests by: ./test" + +test_standalone: test + @echo "test_standalone is deprecated, please use make-target 'test'" + +all: $(LIBMAIN_S) test + +tune: $(LIBMAIN_S) + $(MAKE) -C etc tune + $(MAKE) + +#NOTE: this makefile works also on cygwin, thus we need to delete *.exe +clean: + -@rm -f $(OBJECTS) $(LIBMAIN_S) + -@rm -f demo/main.o demo/opponent.o demo/test.o test test.exe + +#Install the library + headers +install: $(LIBMAIN_S) + @mkdir -p $(DESTDIR)$(INCPATH) $(DESTDIR)$(LIBPATH)/pkgconfig + @cp $(LIBMAIN_S) $(DESTDIR)$(LIBPATH)/ + @cp $(HEADERS_PUB) $(DESTDIR)$(INCPATH)/ + @sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION),' libtommath.pc.in > $(DESTDIR)$(LIBPATH)/pkgconfig/libtommath.pc diff --git a/lib/hcrypto/libtommath/makefile_include.mk b/lib/hcrypto/libtommath/makefile_include.mk new file mode 100644 index 000000000..7b025e8e9 --- /dev/null +++ b/lib/hcrypto/libtommath/makefile_include.mk @@ -0,0 +1,166 @@ +# +# Include makefile for libtommath +# + +#version of library +VERSION=1.2.0 +VERSION_PC=1.2.0 +VERSION_SO=3:0:2 + +PLATFORM := $(shell uname | sed -e 's/_.*//') + +# default make target +default: ${LIBNAME} + +# Compiler and Linker Names +ifndef CROSS_COMPILE + CROSS_COMPILE= +endif + +# We only need to go through this dance of determining the right compiler if we're using +# cross compilation, otherwise $(CC) is fine as-is. +ifneq (,$(CROSS_COMPILE)) +ifeq ($(origin CC),default) +CSTR := "\#ifdef __clang__\nCLANG\n\#endif\n" +ifeq ($(PLATFORM),FreeBSD) + # XXX: FreeBSD needs extra escaping for some reason + CSTR := $$$(CSTR) +endif +ifneq (,$(shell echo $(CSTR) | $(CC) -E - | grep CLANG)) + CC := $(CROSS_COMPILE)clang +else + CC := $(CROSS_COMPILE)gcc +endif # Clang +endif # cc is Make's default +endif # CROSS_COMPILE non-empty + +LD=$(CROSS_COMPILE)ld +AR=$(CROSS_COMPILE)ar +RANLIB=$(CROSS_COMPILE)ranlib + +ifndef MAKE +# BSDs refer to GNU Make as gmake +ifneq (,$(findstring $(PLATFORM),FreeBSD OpenBSD DragonFly NetBSD)) + MAKE=gmake +else + MAKE=make +endif +endif + +LTM_CFLAGS += -I./ -Wall -Wsign-compare -Wextra -Wshadow + +ifdef SANITIZER +LTM_CFLAGS += -fsanitize=undefined -fno-sanitize-recover=all -fno-sanitize=float-divide-by-zero +endif + +ifndef NO_ADDTL_WARNINGS +# additional warnings +LTM_CFLAGS += -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align +LTM_CFLAGS += -Wstrict-prototypes -Wpointer-arith +endif + +ifdef CONV_WARNINGS +LTM_CFLAGS += -std=c89 -Wconversion -Wsign-conversion +ifeq ($(CONV_WARNINGS), strict) +LTM_CFLAGS += -DMP_USE_ENUMS -Wc++-compat +endif +else +LTM_CFLAGS += -Wsystem-headers +endif + +ifdef COMPILE_DEBUG +#debug +LTM_CFLAGS += -g3 +endif + +ifdef COMPILE_SIZE +#for size +LTM_CFLAGS += -Os +else + +ifndef IGNORE_SPEED +#for speed +LTM_CFLAGS += -O3 -funroll-loops + +#x86 optimizations [should be valid for any GCC install though] +LTM_CFLAGS += -fomit-frame-pointer +endif + +endif # COMPILE_SIZE + +ifneq ($(findstring clang,$(CC)),) +LTM_CFLAGS += -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header +endif +ifneq ($(findstring mingw,$(CC)),) +LTM_CFLAGS += -Wno-shadow +endif +ifeq ($(PLATFORM), Darwin) +LTM_CFLAGS += -Wno-nullability-completeness +endif +ifeq ($(PLATFORM), CYGWIN) +LIBTOOLFLAGS += -no-undefined +endif + +# add in the standard FLAGS +LTM_CFLAGS += $(CFLAGS) +LTM_LFLAGS += $(LFLAGS) +LTM_LDFLAGS += $(LDFLAGS) +LTM_LIBTOOLFLAGS += $(LIBTOOLFLAGS) + + +ifeq ($(PLATFORM),FreeBSD) + _ARCH := $(shell sysctl -b hw.machine_arch) +else + _ARCH := $(shell uname -m) +endif + +# adjust coverage set +ifneq ($(filter $(_ARCH), i386 i686 x86_64 amd64 ia64),) + COVERAGE = test_standalone timing + COVERAGE_APP = ./test && ./timing +else + COVERAGE = test_standalone + COVERAGE_APP = ./test +endif + +HEADERS_PUB=tommath.h +HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) + +#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 ?= +PREFIX ?= /usr/local +LIBPATH ?= $(PREFIX)/lib +INCPATH ?= $(PREFIX)/include +DATAPATH ?= $(PREFIX)/share/doc/libtommath/pdf + +#make the code coverage of the library +# +coverage: LTM_CFLAGS += -fprofile-arcs -ftest-coverage -DTIMING_NO_LOGS +coverage: LTM_LFLAGS += -lgcov +coverage: LTM_LDFLAGS += -lgcov + +coverage: $(COVERAGE) + $(COVERAGE_APP) + +lcov: coverage + rm -f coverage.info + lcov --capture --no-external --no-recursion $(LCOV_ARGS) --output-file coverage.info -q + genhtml coverage.info --output-directory coverage -q + +# target that removes all coverage output +cleancov-clean: + rm -f `find . -type f -name "*.info" | xargs` + rm -rf coverage/ + +# cleans everything - coverage output and standard 'clean' +cleancov: cleancov-clean clean + +clean: + rm -f *.gcda *.gcno *.gcov *.bat *.o *.a *.obj *.lib *.exe *.dll etclib/*.o \ + demo/*.o test timing mtest_opponent mtest/mtest mtest/mtest.exe tuning_list \ + *.s mpi.c *.da *.dyn *.dpi tommath.tex `find . -type f | grep [~] | xargs` *.lo *.la + rm -rf .libs/ demo/.libs + ${MAKE} -C etc/ clean MAKE=${MAKE} + ${MAKE} -C doc/ clean MAKE=${MAKE} diff --git a/lib/hcrypto/libtommath/mess.sh b/lib/hcrypto/libtommath/mess.sh deleted file mode 100644 index bf639ce3b..000000000 --- a/lib/hcrypto/libtommath/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/lib/hcrypto/libtommath/mtest/logtab.h b/lib/hcrypto/libtommath/mtest/logtab.h index bbefaefc0..dae3344d6 100644 --- a/lib/hcrypto/libtommath/mtest/logtab.h +++ b/lib/hcrypto/libtommath/mtest/logtab.h @@ -1,24 +1,24 @@ const float s_logv_2[] = { - 0.000000000, 0.000000000, 1.000000000, 0.630929754, /* 0 1 2 3 */ - 0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4 5 6 7 */ - 0.333333333, 0.315464877, 0.301029996, 0.289064826, /* 8 9 10 11 */ - 0.278942946, 0.270238154, 0.262649535, 0.255958025, /* 12 13 14 15 */ - 0.250000000, 0.244650542, 0.239812467, 0.235408913, /* 16 17 18 19 */ - 0.231378213, 0.227670249, 0.224243824, 0.221064729, /* 20 21 22 23 */ - 0.218104292, 0.215338279, 0.212746054, 0.210309918, /* 24 25 26 27 */ - 0.208014598, 0.205846832, 0.203795047, 0.201849087, /* 28 29 30 31 */ - 0.200000000, 0.198239863, 0.196561632, 0.194959022, /* 32 33 34 35 */ - 0.193426404, 0.191958720, 0.190551412, 0.189200360, /* 36 37 38 39 */ - 0.187901825, 0.186652411, 0.185449023, 0.184288833, /* 40 41 42 43 */ - 0.183169251, 0.182087900, 0.181042597, 0.180031327, /* 44 45 46 47 */ - 0.179052232, 0.178103594, 0.177183820, 0.176291434, /* 48 49 50 51 */ - 0.175425064, 0.174583430, 0.173765343, 0.172969690, /* 52 53 54 55 */ - 0.172195434, 0.171441601, 0.170707280, 0.169991616, /* 56 57 58 59 */ - 0.169293808, 0.168613099, 0.167948779, 0.167300179, /* 60 61 62 63 */ + 0.000000000, 0.000000000, 1.000000000, 0.630929754, /* 0 1 2 3 */ + 0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4 5 6 7 */ + 0.333333333, 0.315464877, 0.301029996, 0.289064826, /* 8 9 10 11 */ + 0.278942946, 0.270238154, 0.262649535, 0.255958025, /* 12 13 14 15 */ + 0.250000000, 0.244650542, 0.239812467, 0.235408913, /* 16 17 18 19 */ + 0.231378213, 0.227670249, 0.224243824, 0.221064729, /* 20 21 22 23 */ + 0.218104292, 0.215338279, 0.212746054, 0.210309918, /* 24 25 26 27 */ + 0.208014598, 0.205846832, 0.203795047, 0.201849087, /* 28 29 30 31 */ + 0.200000000, 0.198239863, 0.196561632, 0.194959022, /* 32 33 34 35 */ + 0.193426404, 0.191958720, 0.190551412, 0.189200360, /* 36 37 38 39 */ + 0.187901825, 0.186652411, 0.185449023, 0.184288833, /* 40 41 42 43 */ + 0.183169251, 0.182087900, 0.181042597, 0.180031327, /* 44 45 46 47 */ + 0.179052232, 0.178103594, 0.177183820, 0.176291434, /* 48 49 50 51 */ + 0.175425064, 0.174583430, 0.173765343, 0.172969690, /* 52 53 54 55 */ + 0.172195434, 0.171441601, 0.170707280, 0.169991616, /* 56 57 58 59 */ + 0.169293808, 0.168613099, 0.167948779, 0.167300179, /* 60 61 62 63 */ 0.166666667 }; -/* $Source: /cvs/libtom/libtommath/mtest/logtab.h,v $ */ -/* $Revision: 1.2 $ */ -/* $Date: 2005/05/05 14:38:47 $ */ +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/lib/hcrypto/libtommath/mtest/mpi-config.h b/lib/hcrypto/libtommath/mtest/mpi-config.h index f69e36d65..ea576e563 100644 --- a/lib/hcrypto/libtommath/mtest/mpi-config.h +++ b/lib/hcrypto/libtommath/mtest/mpi-config.h @@ -1,5 +1,5 @@ /* Default configuration for MPI library */ -/* $Id: mpi-config.h,v 1.2 2005/05/05 14:38:47 tom Exp $ */ +/* $Id$ */ #ifndef MPI_CONFIG_H_ #define MPI_CONFIG_H_ @@ -85,6 +85,6 @@ /* crc==3287762869, version==2, Sat Feb 02 06:43:53 2002 */ -/* $Source: /cvs/libtom/libtommath/mtest/mpi-config.h,v $ */ -/* $Revision: 1.2 $ */ -/* $Date: 2005/05/05 14:38:47 $ */ +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/lib/hcrypto/libtommath/mtest/mpi-types.h b/lib/hcrypto/libtommath/mtest/mpi-types.h index 026de589d..f99d7eeae 100644 --- a/lib/hcrypto/libtommath/mtest/mpi-types.h +++ b/lib/hcrypto/libtommath/mtest/mpi-types.h @@ -15,6 +15,6 @@ typedef int mp_err; #define RADIX (MP_DIGIT_MAX+1) -/* $Source: /cvs/libtom/libtommath/mtest/mpi-types.h,v $ */ -/* $Revision: 1.2 $ */ -/* $Date: 2005/05/05 14:38:47 $ */ +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/lib/hcrypto/libtommath/mtest/mpi.c b/lib/hcrypto/libtommath/mtest/mpi.c index d8d05b00b..7e71ad609 100644 --- a/lib/hcrypto/libtommath/mtest/mpi.c +++ b/lib/hcrypto/libtommath/mtest/mpi.c @@ -2,11 +2,13 @@ mpi.c by Michael J. Fromberger - Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved + Copyright (C) 1998 Michael J. Fromberger Arbitrary precision integer arithmetic library - $Id: mpi.c,v 1.2 2005/05/05 14:38:47 tom Exp $ + SPDX-License-Identifier: Unlicense + + $Id$ */ #include "mpi.h" @@ -176,7 +178,7 @@ 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 */ + /* 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 */ @@ -358,15 +360,15 @@ mp_err mp_copy(mp_int *from, mp_int *to) } else { if((tmp = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL) - return MP_MEM; + 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)); + s_mp_setz(DIGITS(to), ALLOC(to)); #endif - s_mp_free(DIGITS(to)); + s_mp_free(DIGITS(to)); } DIGITS(to) = tmp; @@ -507,7 +509,7 @@ mp_err mp_set_int(mp_int *mp, long z) return res; res = s_mp_add_d(mp, - (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX)); + (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX)); if(res != MP_OKAY) return res; @@ -772,7 +774,7 @@ mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c) while(d != 0) { if(d & 1) { if((res = s_mp_mul(&s, &x)) != MP_OKAY) - goto CLEANUP; + goto CLEANUP; } d >>= 1; @@ -875,13 +877,13 @@ mp_err mp_add(mp_int *a, mp_int *b, mp_int *c) */ if(c == b) { if((res = s_mp_add(c, a)) != MP_OKAY) - return res; + return res; } else { if(c != a && (res = mp_copy(a, c)) != MP_OKAY) - return res; + return res; if((res = s_mp_add(c, b)) != MP_OKAY) - return res; + return res; } } else if((cmp = s_mp_cmp(a, b)) > 0) { /* different sign: a > b */ @@ -894,10 +896,10 @@ mp_err mp_add(mp_int *a, mp_int *b, mp_int *c) mp_int tmp; if((res = mp_init_copy(&tmp, a)) != MP_OKAY) - return res; + return res; if((res = s_mp_sub(&tmp, b)) != MP_OKAY) { - mp_clear(&tmp); - return res; + mp_clear(&tmp); + return res; } s_mp_exch(&tmp, c); @@ -906,9 +908,9 @@ mp_err mp_add(mp_int *a, mp_int *b, mp_int *c) } else { if(c != a && (res = mp_copy(a, c)) != MP_OKAY) - return res; + return res; if((res = s_mp_sub(c, b)) != MP_OKAY) - return res; + return res; } @@ -924,10 +926,10 @@ mp_err mp_add(mp_int *a, mp_int *b, mp_int *c) mp_int tmp; if((res = mp_init_copy(&tmp, b)) != MP_OKAY) - return res; + return res; if((res = s_mp_sub(&tmp, a)) != MP_OKAY) { - mp_clear(&tmp); - return res; + mp_clear(&tmp); + return res; } s_mp_exch(&tmp, c); @@ -936,9 +938,9 @@ mp_err mp_add(mp_int *a, mp_int *b, mp_int *c) } else { if(c != b && (res = mp_copy(b, c)) != MP_OKAY) - return res; + return res; if((res = s_mp_sub(c, a)) != MP_OKAY) - return res; + return res; } } @@ -970,12 +972,12 @@ mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c) if(SIGN(a) != SIGN(b)) { if(c == a) { if((res = s_mp_add(c, b)) != MP_OKAY) - return res; + return res; } else { if(c != b && ((res = mp_copy(b, c)) != MP_OKAY)) - return res; + return res; if((res = s_mp_add(c, a)) != MP_OKAY) - return res; + return res; SIGN(c) = SIGN(a); } @@ -984,20 +986,20 @@ mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c) mp_int tmp; if((res = mp_init_copy(&tmp, a)) != MP_OKAY) - return res; + return res; if((res = s_mp_sub(&tmp, b)) != MP_OKAY) { - mp_clear(&tmp); - return res; + 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; + return res; if((res = s_mp_sub(c, b)) != MP_OKAY) - return res; + return res; } } else if(cmp == 0) { /* Same sign, equal magnitude */ @@ -1009,21 +1011,21 @@ mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c) mp_int tmp; if((res = mp_init_copy(&tmp, b)) != MP_OKAY) - return res; + return res; if((res = s_mp_sub(&tmp, a)) != MP_OKAY) { - mp_clear(&tmp); - return res; + 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; + return res; if((res = s_mp_sub(c, a)) != MP_OKAY) - return res; + return res; } SIGN(c) = !SIGN(b); @@ -1157,7 +1159,7 @@ mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r) if((cmp = s_mp_cmp(a, b)) < 0) { if(r) { if((res = mp_copy(a, r)) != MP_OKAY) - return res; + return res; } if(q) @@ -1173,7 +1175,7 @@ mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r) mp_set(q, 1); if(qneg) - SIGN(q) = MP_NEG; + SIGN(q) = MP_NEG; } if(r) @@ -1264,7 +1266,7 @@ 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; + unsigned int bit, dig; ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); @@ -1286,14 +1288,14 @@ mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c) /* 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; + if((res = s_mp_mul(&s, &x)) != MP_OKAY) + goto CLEANUP; } d >>= 1; if((res = s_mp_sqr(&x)) != MP_OKAY) - goto CLEANUP; + goto CLEANUP; } } @@ -1303,7 +1305,7 @@ mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c) while(d) { if(d & 1) { if((res = s_mp_mul(&s, &x)) != MP_OKAY) - goto CLEANUP; + goto CLEANUP; } d >>= 1; @@ -1379,7 +1381,7 @@ mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c) if(SIGN(c) == MP_NEG) { if((res = mp_add(c, m, c)) != MP_OKAY) - return res; + return res; } } else if(mag < 0) { @@ -1388,7 +1390,7 @@ mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c) if(mp_cmp_z(a) < 0) { if((res = mp_add(c, m, c)) != MP_OKAY) - return res; + return res; } @@ -1637,7 +1639,7 @@ mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c) mp_err res; mp_digit d, *db = DIGITS(b); mp_size ub = USED(b); - int dig, bit; + unsigned int bit, dig; ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); @@ -1667,18 +1669,18 @@ mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c) /* 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; + 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; + goto CLEANUP; if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY) - goto CLEANUP; + goto CLEANUP; } } @@ -1688,9 +1690,9 @@ mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c) while(d) { if(d & 1) { if((res = s_mp_mul(&s, &x)) != MP_OKAY) - goto CLEANUP; + goto CLEANUP; if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY) - goto CLEANUP; + goto CLEANUP; } d >>= 1; @@ -1735,8 +1737,8 @@ mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c) 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; + (res = mp_mod(&s, m, &s)) != MP_OKAY) + goto CLEANUP; } d /= 2; @@ -1973,17 +1975,17 @@ mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c) if(mp_cmp_z(&t) == MP_GT) { if((res = mp_copy(&t, &u)) != MP_OKAY) - goto CLEANUP; + goto CLEANUP; } else { if((res = mp_copy(&t, &v)) != MP_OKAY) - goto CLEANUP; + goto CLEANUP; /* v = -t */ if(SIGN(&t) == MP_ZPOS) - SIGN(&v) = MP_NEG; + SIGN(&v) = MP_NEG; else - SIGN(&v) = MP_ZPOS; + SIGN(&v) = MP_ZPOS; } if((res = mp_sub(&u, &v, &t)) != MP_OKAY) @@ -2111,12 +2113,12 @@ mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y) s_mp_div_2(&u); if(mp_iseven(&A) && mp_iseven(&B)) { - s_mp_div_2(&A); s_mp_div_2(&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); + 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); } } @@ -2124,12 +2126,12 @@ mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y) s_mp_div_2(&v); if(mp_iseven(&C) && mp_iseven(&D)) { - s_mp_div_2(&C); s_mp_div_2(&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((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); } } @@ -2148,13 +2150,13 @@ mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y) /* 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((res = mp_copy(&C, x)) != MP_OKAY) goto CLEANUP; if(y) - if((res = mp_copy(&D, y)) != MP_OKAY) goto CLEANUP; + if((res = mp_copy(&D, y)) != MP_OKAY) goto CLEANUP; if(g) - if((res = mp_mul(&gx, &v, g)) != MP_OKAY) goto CLEANUP; + if((res = mp_mul(&gx, &v, g)) != MP_OKAY) goto CLEANUP; break; } @@ -2387,7 +2389,7 @@ mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str) /* Generate digits in reverse order */ while(dp < end) { - int ix; + unsigned int ix; d = *dp; for(ix = 0; ix < sizeof(mp_digit); ++ix) { @@ -2463,15 +2465,15 @@ mp_err mp_read_radix(mp_int *mp, unsigned char *str, int radix) mp_sign sig = MP_ZPOS; ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX, - MP_BADARG); + 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] != '+') { + (s_mp_tovalue(str[ix], radix) < 0) && + str[ix] != '-' && + str[ix] != '+') { ++ix; } @@ -2541,7 +2543,7 @@ int mp_value_radix_size(int num, int qty, int radix) /* {{{ mp_toradix(mp, str, radix) */ -mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix) +mp_err mp_toradix(mp_int *mp, char *str, int radix) { int ix, pos = 0; @@ -2567,8 +2569,8 @@ mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix) /* 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; + mp_clear(&tmp); + return res; } /* Generate digits, use capital letters */ @@ -2587,10 +2589,10 @@ mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix) /* Reverse the digits and sign indicator */ ix = 0; while(ix < pos) { - char tmp = str[ix]; + char _tmp = str[ix]; str[ix] = str[pos]; - str[pos] = tmp; + str[pos] = _tmp; ++ix; --pos; } @@ -2817,7 +2819,7 @@ mp_err s_mp_lshd(mp_int *mp, mp_size p) mp_err res; mp_size pos; mp_digit *dp; - int ix; + int ix; if(p == 0) return MP_OKAY; @@ -2833,7 +2835,7 @@ mp_err s_mp_lshd(mp_int *mp, mp_size p) dp[ix + p] = dp[ix]; /* Fill the bottom digits with zeroes */ - for(ix = 0; ix < p; ix++) + for(ix = 0; (unsigned)ix < p; ix++) dp[ix] = 0; return MP_OKAY; @@ -2898,7 +2900,7 @@ void s_mp_div_2(mp_int *mp) mp_err s_mp_mul_2(mp_int *mp) { - int ix; + unsigned int ix; mp_digit kin = 0, kout, *dp = DIGITS(mp); mp_err res; @@ -2914,7 +2916,7 @@ mp_err s_mp_mul_2(mp_int *mp) if(kin) { if(ix >= ALLOC(mp)) { if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY) - return res; + return res; dp = DIGITS(mp); } @@ -2970,7 +2972,7 @@ 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; + unsigned int ix; if((res = s_mp_lshd(mp, d / DIGIT_BIT)) != MP_OKAY) return res; @@ -3555,12 +3557,12 @@ mp_err s_mp_sqr(mp_int *a) 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 */ + 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) + for C arithmetic (we've already noted if it is to occur) */ w *= 2; @@ -3568,7 +3570,7 @@ mp_err s_mp_sqr(mp_int *a) 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 + if the addition will cause one, and set the carry out if so */ u |= ((MP_WORD_MAX - v) < w); @@ -3579,7 +3581,7 @@ mp_err s_mp_sqr(mp_int *a) *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 */ + This is why k must be an mp_word, instead of an mp_digit */ k = CARRYOUT(w) | (u << DIGIT_BIT); } /* for(jx ...) */ @@ -3665,10 +3667,10 @@ mp_err s_mp_div(mp_int *a, mp_int *b) /* 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; + goto CLEANUP; if((res = s_mp_lshd(", 1)) != MP_OKAY) - goto CLEANUP; + goto CLEANUP; DIGIT(&rem, 0) = DIGIT(a, ix); s_mp_clamp(&rem); @@ -3790,9 +3792,9 @@ int s_mp_cmp(mp_int *a, mp_int *b) while(ix >= 0) { if(*ap > *bp) - return MP_GT; + return MP_GT; else if(*ap < *bp) - return MP_LT; + return MP_LT; --ap; --bp; --ix; } @@ -3851,7 +3853,7 @@ int s_mp_ispow2(mp_int *v) while(ix >= 0) { if(*dp) - return -1; /* not a power of two */ + return -1; /* not a power of two */ --dp; --ix; } @@ -3980,6 +3982,6 @@ int s_mp_outlen(int bits, int r) /* HERE THERE BE DRAGONS */ /* crc==4242132123, version==2, Sat Feb 02 06:43:52 2002 */ -/* $Source: /cvs/libtom/libtommath/mtest/mpi.c,v $ */ -/* $Revision: 1.2 $ */ -/* $Date: 2005/05/05 14:38:47 $ */ +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/lib/hcrypto/libtommath/mtest/mpi.h b/lib/hcrypto/libtommath/mtest/mpi.h index 66ae87311..9a9cc4101 100644 --- a/lib/hcrypto/libtommath/mtest/mpi.h +++ b/lib/hcrypto/libtommath/mtest/mpi.h @@ -2,11 +2,13 @@ mpi.h by Michael J. Fromberger - Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved + Copyright (C) 1998 Michael J. Fromberger Arbitrary precision integer arithmetic library - $Id: mpi.h,v 1.2 2005/05/05 14:38:47 tom Exp $ + SPDX-License-Identifier: Unlicense + + $Id$ */ #ifndef _H_MPI_ @@ -210,7 +212,7 @@ int mp_count_bits(mp_int *mp); 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); +mp_err mp_toradix(mp_int *mp, char *str, int radix); int mp_char2value(char ch, int r); @@ -226,6 +228,6 @@ const char *mp_strerror(mp_err ec); #endif /* end _H_MPI_ */ -/* $Source: /cvs/libtom/libtommath/mtest/mpi.h,v $ */ -/* $Revision: 1.2 $ */ -/* $Date: 2005/05/05 14:38:47 $ */ +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/lib/hcrypto/libtommath/mtest/mtest.c b/lib/hcrypto/libtommath/mtest/mtest.c index bdfe6127a..06c9afb1f 100644 --- a/lib/hcrypto/libtommath/mtest/mtest.c +++ b/lib/hcrypto/libtommath/mtest/mtest.c @@ -39,39 +39,71 @@ mulmod #include #include "mpi.c" +#ifdef LTM_MTEST_REAL_RAND +#define getRandChar() fgetc(rng) FILE *rng; +#else +#define getRandChar() (rand()&0xFF) +#endif void rand_num(mp_int *a) { - int n, size; + int size; unsigned char buf[2048]; + size_t sz; - 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); + size = 1 + ((getRandChar()<<8) + getRandChar()) % 101; + buf[0] = (getRandChar()&1)?1:0; +#ifdef LTM_MTEST_REAL_RAND + sz = fread(buf+1, 1, size, rng); +#else + sz = 1; + while (sz < (unsigned)size) { + buf[sz] = getRandChar(); + ++sz; + } +#endif + if (sz != (unsigned)size) { + fprintf(stderr, "\nWarning: fread failed\n\n"); + } + while (buf[1] == 0) buf[1] = getRandChar(); mp_read_raw(a, buf, 1+size); } void rand_num2(mp_int *a) { - int n, size; + int size; unsigned char buf[2048]; + size_t sz; - 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); + size = 10 + ((getRandChar()<<8) + getRandChar()) % 101; + buf[0] = (getRandChar()&1)?1:0; +#ifdef LTM_MTEST_REAL_RAND + sz = fread(buf+1, 1, size, rng); +#else + sz = 1; + while (sz < (unsigned)size) { + buf[sz] = getRandChar(); + ++sz; + } +#endif + if (sz != (unsigned)size) { + fprintf(stderr, "\nWarning: fread failed\n\n"); + } + while (buf[1] == 0) buf[1] = getRandChar(); mp_read_raw(a, buf, 1+size); } #define mp_to64(a, b) mp_toradix(a, b, 64) -int main(void) +int main(int argc, char *argv[]) { int n, tmp; + long long max; mp_int a, b, c, d, e; +#ifdef MTEST_NO_FULLSPEED clock_t t1; +#endif char buf[4096]; mp_init(&a); @@ -80,229 +112,263 @@ int main(void) mp_init(&d); mp_init(&e); + if (argc > 1) { + max = strtol(argv[1], NULL, 0); + if (max < 0) { + if (max > -64) { + max = (1 << -(max)) + 1; + } else { + max = 1; + } + } else if (max == 0) { + max = 1; + } + } else { + max = 0; + } + /* 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_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); - } -*/ + mp_add_d(&a, 1, &a); + mp_mul_2(&a, &a); + mp_sub_d(&a, 1, &a); + } + */ +#ifdef LTM_MTEST_REAL_RAND 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; + fprintf(stderr, "\nWarning: no /dev/[u]random available\n\n"); + printf("exit\n"); + return 1; } } +#else + srand(23); +#endif +#ifdef MTEST_NO_FULLSPEED t1 = clock(); +#endif for (;;) { -#if 0 +#ifdef MTEST_NO_FULLSPEED if (clock() - t1 > CLOCKS_PER_SEC) { sleep(2); t1 = clock(); } #endif - n = fgetc(rng) % 15; + n = getRandChar() % 15; + + if (max != 0) { + --max; + if (max == 0) + n = 255; + } + + 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 = getRandChar() & 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 = getRandChar() & 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 */ + do { + rand_num2(&a); + rand_num2(&b); + b.sign = MP_ZPOS; + a.sign = MP_ZPOS; + mp_gcd(&a, &b, &c); + } while (mp_cmp_d(&c, 1) != 0 || mp_cmp_d(&b, 1) == 0); + 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); + } else if (n == 255) { + printf("exit\n"); + break; + } - 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); - } } +#ifdef LTM_MTEST_REAL_RAND fclose(rng); +#endif return 0; } -/* $Source: /cvs/libtom/libtommath/mtest/mtest.c,v $ */ -/* $Revision: 1.2 $ */ -/* $Date: 2005/05/05 14:38:47 $ */ +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/lib/hcrypto/libtommath/pics/design_process.sxd b/lib/hcrypto/libtommath/pics/design_process.sxd deleted file mode 100644 index 7414dbb27696fe716fe8c73a5c2b21d8c3e0c23c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6950 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 diff --git a/lib/hcrypto/libtommath/pics/design_process.tif b/lib/hcrypto/libtommath/pics/design_process.tif deleted file mode 100644 index 4a0c012d565ecd12a43186f132b3bccdefb9a23e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79042 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 z 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 z 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 diff --git a/lib/hcrypto/libtommath/pics/expt_state.sxd b/lib/hcrypto/libtommath/pics/expt_state.sxd deleted file mode 100644 index 6518404d5fa6eca01b4457a813f85cda074c0915..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6869 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 SkP=n~Rt6PD28P*^ARYiC`4Gea diff --git a/lib/hcrypto/libtommath/pics/expt_state.tif b/lib/hcrypto/libtommath/pics/expt_state.tif deleted file mode 100644 index cb06e8edf17017dec815be222c845f1b0a938e07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87542 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

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

%N3(dw zXXV*G%TBCMPkeOn=#Hs%?d8_VR!MpZPc|f}_w#;~Pn=mVE&P8zXm{hra|Jn{*fy$l zZkOGs7Ly~sGhlp=F3?#hIkBh1|Yoz{I^y?!5;uyFj|s;$4)JidH%pZ7D9n9G~boZgW) zkNbIT)Vej6Q~w-`=n>zk?%!3t{A_@|ji_^y&z;Sn#Z>Th@rzF!Ia0a&@$B|+v)ak4 zH{Ra+`+Lgsb8|mkogSb0PqO{{A>9|(Kcu&1w?C<`cyU4T=fmIfCinLi>)6aHXX^0~12nb*;K4`yGV zv@Uj+R(_!kkEHqf`y1kZeSf{a@a2#B2G8qY*c@+Cbjd&T4CjLcUmHTUw9_fcm2Suuh}UN8X7lMKhOJXH&4FU z@fqWpr;8TPv1IuiHIMb@&y3`?x3^52bv1j{@no0d9m>g%mYvZ1^^RLy|3uSIZqVsT zuUx(LxMnccn&k5S*OKr#)+4!fee&B0HT$2`D%i)&IQRH^xo+&X5KEDLaX*3|o(|ns z6R8=wX34wy%6sqKC!c&0xpQ(SyI69>FO_?)M@%DFEX{K3WD*EHTN4OKbkicpp+mxb-Sj^WzrVlZKe4@YeZ}!US>~FfJKa7N8^wWEe?|H6zq7ya zXQ6!EmxWWbgY}MBb}9c5EZ%c3{(D&eOm)M;Q;hHI>mF6iG%Dga+{Djd-oJ*Kl7XyHQ5ZKG7m|9 zJ?!T! zdh^0?Z(hwc(9vZlCuw@mh@mH-~oNexJZ2w+)F>$f!v8lF_)@Q_PxjycAO7jtN$F)9 zS1I39JYx&mGI(=GVKRg8asF0Ij{B!g&(1dYujKs9_U^i{PtCJ4Gk@8fNIddf+AL2) z{_kgH&9EI29XsFIDxUiDXobM{oBlexoyEyTfr#j=Xbwl-JZX^u*p|mJ(AtH>39ABG*g%>+9#r8^pi9w6weA z^|iMfW9B>*{O&GuW%HZTCo?yuPyI9h%t9N@b+gkyE!j~Mz9>&OdZW*4$vFNajiv7{ zMQVkv_~J9K@4U0Y$A0^N5tCHCmz5f>;)*-=p3t^J5PcRxnIb+&0BBk0mH-d zCJ2kK+gbeQpO1{=F5^X2v@&*|B3a;Cemuq6Fa&+m_ZPws38{1jXF@v3;xmJk2; zupd@>CIdQwa_`a}ahdlb&nDgBzo%K#W_ir|{hr0iDo19R9q`}da?)V!WIJu)^!QiO z`Fj<6rA@BcEE3dQ*Iqe6{Wiy^IyTwkK$JZ{l z)9HEpf#XTt$%W2$I8zztt4$Y3ZJurcx)u4@fi_e1ZY?@*IR9BYHDn%@?J4jN35LwP%vkjY5zfIw$q~9HuLhc-#JDzeU_J=Tkjh1Ju3pVr@ZC1!SwUD%rltF*fRhrcgP`q?!}Cv%fQe`vGu$A� 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 diff --git a/lib/hcrypto/libtommath/pics/makefile b/lib/hcrypto/libtommath/pics/makefile deleted file mode 100644 index f55a600b6..000000000 --- a/lib/hcrypto/libtommath/pics/makefile +++ /dev/null @@ -1,35 +0,0 @@ -# makes the images... yeah - -default: pses - -design_process.ps: design_process.tif - tiff2ps -s -e design_process.tif > design_process.ps - -sliding_window.ps: sliding_window.tif - tiff2ps -s -e sliding_window.tif > sliding_window.ps - -expt_state.ps: expt_state.tif - tiff2ps -s -e expt_state.tif > expt_state.ps - -primality.ps: primality.tif - tiff2ps -s -e primality.tif > primality.ps - -design_process.pdf: design_process.ps - epstopdf design_process.ps - -sliding_window.pdf: sliding_window.ps - epstopdf sliding_window.ps - -expt_state.pdf: expt_state.ps - epstopdf expt_state.ps - -primality.pdf: primality.ps - epstopdf primality.ps - - -pses: sliding_window.ps expt_state.ps primality.ps design_process.ps -pdfes: sliding_window.pdf expt_state.pdf primality.pdf design_process.pdf - -clean: - rm -rf *.ps *.pdf .xvpics - diff --git a/lib/hcrypto/libtommath/pics/primality.tif b/lib/hcrypto/libtommath/pics/primality.tif deleted file mode 100644 index 76d6be3fac2cc8b07a401e008fbe45f02758cef7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85514 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 diff --git a/lib/hcrypto/libtommath/pics/radix.sxd b/lib/hcrypto/libtommath/pics/radix.sxd deleted file mode 100644 index b9eb9a032d0b5229d4828911466490a95c126a2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6181 zcmWIWW@Zs#00FH9;rdUFFYJ(EU|;}Y4h9B>+|1n6lFEYA#DapH%;dz9%=|q4vb+?% z;?g|5irgH%l%m9PhzT4F91I{6KqkR3Hv}L}W z7h5=I&bj#8*Q;0bq3fYdhDEyUk}BMhQ&K)k)K>mT`F8R5N&dz1%eTwR{oC_9W5Z7y z&XWd74~NNmalhb zyYxA7V#kG)lB}YLV33ADXERMGeN#xJ?4%v>9no~>wI@t`TkMLCKo z%V3_Z@ph+>4;_z7m7|y(K6BZpn^x_Oi_VT$yn8Sq;eTO$a($A`(XUZvCMWmJJEEP> zdUo2&o)6EaCN%PwoV3(T5Z@4>dC8ziKH~jBt-7q#sK23S&0`Yo>FjfQ^W@9o^e0~y zbMbiT`mMOU-M%^a@6Vdem**|-o$T#!R{x3Ty*)*|j-fAGM8uCuT$PTS#hBK6F|_r*58%x4yAC+uuZp1C_G_kDI1 z5}Rs!JVtEAF2k=HX1}{zlIC`>Mt4;@X|7UwB9rn^NwHONy1|rlhNmLfG?(#g+K}Ls zqbK3N&+%e%R?@5^3*0yoIqG|&Prf`PtL3|>L(A`*+)A~!d)g9WOzDEpE_x=lK6shRg5B!&t+UK`s!PABuTFz4!M76YmgH|eJ*9u8;ji!W_sXy5&1 z#%|hqr<)w^rV3tJ=`?M*W9;hcBTeVdcZFZ}ia&6;nvtJXr%2|I56ir^4N}Kno#F|W ztE>pHY0kJRxM*(v%zgL!_GMRw``TxC@2|i5#ro}w>ac>VUv|HJ@jKji-}Om7`E<`U zw0rw&_R#LNYc%y9h{l^zt@h@n-f^glp1UCaZvNBByOg=N`Apn%=knhJUvKNbDJgr? z{{2H|G?$Lx)EkyHD_7R#Ut5>F)A74t?sn7s_godp@@AlWfj_2#sHF!ezHD3LixPkHgTiXlI zV<$WOlVp8p;VTrn>(6_mpIMvr)rFr-7N25NIeo%Q-xW{F_Ij_rvU`cw^Ujp(=U3gm z>}!AIjqrc>nSa;=yxBRX&E&Zp&ceX(PLhEEcX`Ccz`#&kQkj!l3@VP^M#tyhHWR47 zzx;wpN&cpko1T+({5G2D8YpCTt1@nLk6M&tHc2C3%G@vBZwl|{&rfj=x*{JPv}l)S zmIJ52k#hH!<;Qm$*Nc??dZx$KE1IUc@Z%YoewoV$HoDge>8CwA`<4CmiJIbXmtUTL zKL1|q|Gz)?IyN^{{5Y~aPVC`~XwCing;_QGDyu&pw?4cj=XY?^WB*H8E;kQtJHP%s z@7JF;@+k*$bAJDIzie>zshi#RvzsqZ%Vs`gVHE1_-fPWzH)r%knhPBX)YaoWtm(t{$jH&kEsVF@GD3IOgq1JW zbJg!vO}cw%}(`akA}bAH^CP}-W)d2V7Yr`ONtpBDAlc3bJ|@o@dOahsI)y(vHT;+Ba*lDc-&_57E2&y?^SFOW@sq+!XT zBGr6Giu>lJ(tWeO-CVinU1vY@l-5dHNiVSl9WCFDiw_2DQi;pTdfd_|-XpAGqk1AJ z$Fb;FNiM6%s!NL%TV)>UG|OC1#<8XIYFTxt4zF{ zc!cYErwJ@!OK5eq-g0P(V9dhYrt2$2_Fiz3T%OtF60Byo%xJQXh}vnUlu1YB&ZoF< zxVB*4OijUXZGj0A(Zy|oU)E1?RuZ{!t*0QPBaFq^$k;jUW97t!7orrWW=?Wyx;@)7 zx+BYTeS4U;!_=@-fp3(b&9;5z6sGoI>GnrVCMx?@IjS}#eRMrtxMzjhx!2Fc-T%#S zTY8OAWy|)Y2N_Cjd9Q6V)-S4M*YGL4%W%Bzc)`M4DVYfdIyM?AqDww6Rybk$Qpl0J zAR0X=;wsymWIot*ES)g%Xi+rR&JC)w zgU@9yNq_jzE$n3Wtip*iTvupm^iS@r4+Z1RcmI{yCX@t0$v+k)-2CmUA6hf zai5=&-;;YoCw!e6x1)91xv6uDxMv)?llbAu*)2?)FB#r$*f!%t=Rv`e0Moyxt#VK zN_= z{SQOyc-Oh>pWmwd#QbN*x%~p9y`tngitHfxQfebUi$YquWUuz#*+|1tL3lO-E7 zuQ_gxFTb24`rmI_?sxvhN-6$A$LG9S>*1wRSSi%?k5`X5QtUUE|HI9<4o)a}aq++v zw||$PZd6LQJ~%u0|G%G#d0%FIRJ?He-iG}tnrF=N?gvx{{m4o-Qt7Tp<5E%C@&0|& zqhtDy9s2LCx9XoBZ+8CZlix-Ot0P|v3mWpjKN^*ILs6oPqfNFcu{{BWc_RF5OZdD= zdqpB=`c+R9ZLIvWW`Xs*O{?AS|Fzh2`{={%Q+WGt&X!XNzd899>r2U?@7C>GGWAbb zYV28k)R4pG{f{3vA4jO?WSuZey**{MGWX)b(+gXj0%tBgnfP00?~CNSZkrzed(m6F zpqP2C^ou(V&)KZZFYIhQ$6J!Opg7BN-;opI%emsee01MuGjCV!>*Vc;jc>j!YPfa& zd1~YRqZdC0etodsZaw$Ur{Bx}R~v78Ua93?gH7jq|?1@o(3ef~}KyWF>m zKOFtL<04;t*VyswZTQy8sZS|v<9J_Iu{-5Y%IfB4`NmO6HQBajCYJ9`FlqJ) z)wEcCMm$=QUvAEZ=*tG-8Yfyq;tX8AJE`o`Ieq?W`5OlZ zf^QPM);gc!RAz12vdR2!faA%zq8rzpJ-xH)|H_=mqcKsbeXp*Cd^0qhTPFFqH{jOU z^)KfAz zEh^5;&$CrB)H6_0NX<*mPsz+nw^a%aanrR>vbW>1QFQTl4v7qKRme|E%S=wSO367|sUDB0OSIA|tUQx!o6&cp zqKhAyiPXJczhK@=Wy1+~@2DlVXCKyKGJA$*?K%8;V)`*WW(P8XQ`{Oqrz zNrl@iu4kXVe*OBoeY@kV(hsPr3PlN4OWf0ov40b6bnvom|J1uzh0@m^DA&55Q?vK} ztG8K|Ofg58l$Q2570q1WvFf3E+fg@Hzgx!dumA6~lxq)2ZfGlcwqY0SMNE*4iG z{rnpG^4eY2Um_LaYD%(ugHH1P6X!dk!@DG>h+<**z-wxKyt-!F%~Dxj*Hl>1y5T z%1a#ni)QY+Qs4F?ITO5$fy)fZj*Npo&-^u$ZZQhgmDT)D6zKQX5~UrJ_I7dY>wqIlZyxf9Se}DM$5q zcGEGQiJCT-N+s*QyybC{Vffx)d&%{eV!h$HZsT1aBvxpxbuKYXe0|`)p{;^mL+z3D zIwNL*_dkAZobY$5s!?hTSEa%dN9ApAA6OYnRXvp2<$knpu?%zgPKDmf(LHzGp8mgO z{qAjdu1h{z?Y7ua@bLuA+MPw2D}IE3sNMA3G2i?98IeDa{$$%d$yr(KxO$yZ^ljD4 zNfo?%-LLQ5xb=p8RUr!x=czX zH)e=wlyLjrzCXpSc2ZE4oKo?rquZUAuep6vM!S}gz3|4CqOYoHyOMsNxv|M?e*0-b z_G>Ooviqm3NLDnr3@J0HdXv_3Ma`l``sPd1yqNxrn$8#Vrv^pGJ&C^j?$b=E+~YyF zTqLHetDcfvo@~sSy7BacHx?1iZdt$9upM{Sycal||L&u?F5LTOHuxS%SD&bFFoj=D zgRfPjP~p<*4d+u{zhNwzy~&V|NkMw^346bHr}DJ?GSh|kG8t}N8SycFK_6RNsBDtN z+cW*bSD4*YOJ^i4N?U!5Ls#fctzG_{zZRa07`!)3-f{TKnRX!mRw2u=-%U`v#q<$X0kai_ZsEP zt8JoQ&R*0#ZMX7{>sjvKTXyaUs`>oklhQ$nhK}v8Pkhf`k+pT!!`aIl`<*sij?I3t z_b{XLgNrs3IvtnI%iy?ZW8y6|Q+Lho&%!e1udjPtt!D(au@DZoz+k2dYhz&> zG8JWDVDNPfan$wnbJNdF%*#wmEd~#suD!G|>#%_U+k?IS3-9I4zr2#gy77pn$gNw= z#w8-xECo+&+HfxO&$m$aj>)2%Oht(N|@XAa+@JNb6^wlgUmIW$psmfLla^1qCR>x({GUS*Xo z{Lad>YHgV&-jj3+w74eBSn4L-b)v}rpSO?K=?-^y zNss3}>r~t0AD>)xgWrtLIr-{o`5Do(4$e5?X_wZ}Q0}{9?UY^57OK~;KUR{)!Dq2A)Q(COpps?RoTnZ89cZtc}q;-K)0nmys_Uj_z-cTAx0V`LIx zz&&gYYP}*bY!ExZ8=?yq?#P2iprLAn4ky%sYjlms&1KM-5<=r87UU5om_Cp^w#GC_ z9D)UT7#KkHE~se@(*<)Ta>4;sz7QQCQe1$6p%|$uM%RfPWT1ov(gVSzqBxRSfHx}} SNC_JQ8$%Q$1H)D^5Dx&ugP|V) diff --git a/lib/hcrypto/libtommath/pics/sliding_window.sxd b/lib/hcrypto/libtommath/pics/sliding_window.sxd deleted file mode 100644 index 91e7c0d9f43b612ff0a59d86a71c8928fbd695f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6787 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 diff --git a/lib/hcrypto/libtommath/pics/sliding_window.tif b/lib/hcrypto/libtommath/pics/sliding_window.tif deleted file mode 100644 index bb4cb96ebff4e06478672dd3583bd26a51d85b5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53880 zcmebD)M9vZfq|i7&fB@{Q>Hxqx&6IHhsjbcm#l!MAYB$#R{?Gh!Ho$U61+{aM07ec zbPSa$L_~EM8K))*IPQwb@S3dWS`~PNRYbs*G5eGK_1bfr?{Bz&?%kVnZ{F?swfo%6 z%@(^q?|UDtkp5nK|L>po|Nr}LFYLsj*dl-+GSB{hQi3et#G!ae&QcadkyFPPcRzPj zjY@wfUKT`{17dm9BaG^}^6_!M{jGhqzjL0So4YOjyqtFArX_PL9(9H-^O?D*Zi~|M z=kx2g{r&y@_VfAmdArNrZkk{B>!hF6OO@3jD}(yx|9)TpKbxIj?u+Hq&Fp+K8-kX4 zMP6MM`nU9mp!y(j^QO^5&d%w-T|L54L>H7IsSBGz3+-G&F zOH@1TO20;nfK!Kw6TyLO93_DY$)x#%vxRoKsB z;R^Z9Ck{L{FpsbQyEXUTo||cBW+WCrJ5#v-@^XK9>)&rS-%UNj+`c*WwAgH$%1yrW z?e1>Ny`5&7eQitG+gp*x`($hTyr*acb|`!C?pUS2@5iC-WM5me(ckXpk-vVI zm-)VJ6_5L{=G=PTXYDdv_Z}VQx8G9v`Pt1?p{wt_p0HgrdfOUaIhz~j?En9fnS1Wq z+UVRXD+0|@Plt29y;-sL2^p{|KIobYb|$P*~r7!*R=Csp>FiHGkf_YXTRU~`&>O=`NvD%`cGe# zgsq84XHFw#zeh$bPLH#JsdGHuuJcgPYZ# z1bndkAzP$*##h5tRs%_Pm4NJYJSMhIW_TzxCna;k&OdxcBIA#XGa9e#kDds+is> ztiJ2~&CTikYh!m``)p~^bHm7Gkzf0p;QRY(bDy1=X?NU0+2(lRaoP0e^Qza`{`qjY zZkgYe1KfQQhKJ&6KDy3V{wM7}Uc$?CVStPIY5e5|+Z$HVsMySqx)1~2!!wy(B2 z`_7Jy5X+5_^8P3H7s_t`Ql6fg`t3@v|II0y!A9p@8{-#WZZt4Ib99<+bk2(l3(YD% zB>a9hJKv~YEpWN>d9yuyd+*r&c))DGenr;RRqskFLf1rG1m#zW!(N(a_&+-y<4!*s zKF9Cxudi!!Z*L1*?kB4qy)7rueiMNu8hlr>#s_f z&hXAud$yqb{k^(8ABDi>hfPn|U7Xz`UVrT26rIRR@m~_Vv!=0rKU$aAcWB?kISW9A z%g0AYC);_epOMa6>oe1+&KFbyx`-oLRJrfRBX0Z4|E7k=O}u=P>F>3;iifP#PbRv5 zdRpT0?|}G4=?Od+R)wy9b1QrO*L``Q60t+C$O=S*9PRSy#LFY@e#KEFN=xB8nKliPh~o1L9k{mwFaQ%dLD znolS9@jnIC2pt*9;M5Mv@=hxKbNp(alyLE%vibe(?dReWHa?k*&(F?&-m3{#^v7rd zqBfZ1?x${7WYv1S-~L|)sL1>H`1tR*l=w^SzF?R9NL2u9f|%?dHLVf zr1+OS=VgC$wLE|JI+%D(L8jr6$0u*i5whMEvOe(I&y<)wLVtDa(yy_ctGsn^Ym?((@)wL(ArToJUi>wf?I-!B&TuZi1RRd&f!{pWcuP}-_QPFtQwUe$9+$6w^Ze2S*8-^n zQd2Yn581jMZsV=3jkvxlboH<5pC{iGyf;{GVfXFmn#j$6{@GT4+ahOMb)?iyadvZl zqSw8xk6Q=h@s`e|B@h z-p%K%PS54F6uFnYX9w4@^A=j+>)yP3JIPzGaCyt)6MS~3ZyBmDG?#pR)-Lh>nuv{u zmif=mldt=+@VCS#$D02K+2yzF|NAz-a4z4z*7WC6oITu;6Z&MWqn7*4wV5n* zURuN?CG14whd)2~i&U<>FAPlyJ0U#rv%+9(DhaaWi+LD=UUH*mX@+H zd_RSaEK{6cJU+VTVc7|**3Ts~=Kryhox^%vP5kq}-|ws4mdETYdUv5>nVRpcAI3&( z^ZI{JTKy>fc(3&Hea!hsfBckMzh5G|>=38=4bkwJhu4>1m#gcjHumq~K7L%L^=IN= zQ1~A!wR$7^Eak?A#CdNM*S(aUepk}BvBFa6SzqyK(wCP!ln=%D_%O`qYW_mpR{c zo`0lsZEf`P*BAHIR=>WtclX@7UoY={*88?|hkkbV;fjw(#s3ytsLj({zAt-?;=UHS znlB3v_dl3e@v!v7vz9mB3WCd>_0msFP<+>PXwCAc2yd*0nU zz8{NYnq@>DOWRazi0}S>-r_OO`QC}~O73FswwJyR1Jya!_M1X_*yE4cO$S#YLEYfs z0ad>o6Ky`u;rl5X!&91nZ@J#N`pNkR8z1EVkc;I0l|He&;LWi9wlv<)bd;FUh>+!T`$#k ze>^6A_xX|6mB(&aaA$(r(`9cWzWX!&n(*=Fg=U@ttFyDsw;z|UzZ1)meRijLh43?0 z_GAAz_4td5ts15uDn7bP;ac}^9x0O-6F!%GFs=Rl?d#@Qo1FG_m@X-o`mUsXB&uJ= z^3uJE$GrRhwTj2RxYu5|K|a~obB+1=Lw0JD-SQouiPx)utIj22$PJT6maf&PuGi^-+%qN_SBYpDPJV3 z|9-u0o8Ek0arwcW-=CDMcz?W@?+2UR|0k3EtM;*r3q`k`IQf#r{lnGp_?^ce%E-@a z{G5}t+3shdRgCogFa7m@4$trZoE^b$d0xkN=1z;bZw|aPShswBoz>;91@$p} zmWp>0@*cdsalAtP+z-vzU0d!}KA-z;SJ5lO_S;IcO>2G>d{2E-3--R!))OzmjR+8N zQuzGK3)!o4Z*Qwpn1HvZkMZ5YTk}VNSJ?mHGXe&9Ox%RaxVd zpYMC(abnSg=?Bd}%Gt4}7an94SGmH@ci*wBc@KN#lp8u;etzm=Mao~?USD3`KmWZ@ zb?+Yw*?G-6CzJba({69i|NgzeutIB-dyH`ZG~pjY*E-S<@jskfpnv9MZ28@%*Aw3s z7v;w^|2+8kq1_8saSgBK&idQi<*H6puYWl6#qMjX!}Wh(p8s!3avkUTqw|iwEYSZq zd%rNa!Q%1?xjm&m@AAU7e=ipI{|euvV0rcVPf^+WM(qXfMQu-?*u{|7;BzMa|F7`h zr{n)Us$I)vv|9MwW=V^J1=j2~TwnjJUcc{_vGk9wJA2qa{K?<@by|P>=dc34MwhvM z1*~WE>pK4gDA@af3e<0(PV4W!&iVQD=7M(@UBzQlKxNw1#Sgqs{NRzbx?-$(kawc* z%R4(af7i^uyv(;xPx;HX>fdj--(`L{i^=t6NrCtFyJfTcyR$dE`ymq}_gw9%iP}5+ z%u6cO4_n3etd}X)f}~wOaO8oSX97xYrOm(ToSqsU_p zd8>k#`@Iu>yjJ{Oe_ihSz29b8+niIM1Sz@N(MqoLEdk#4ACCwN?-MKi=-Mq-8NdGL z=jXf6Gn~7hd2`cJYtgLNb1nu66x7?CvHgDM@%Q709~7L}5ODpu+K?bfo-X8kr+e|u|d@%7;C zd9m^T-(1uAG8xo|%snwdabLLQVh?az9kl_ypwUG-#U_qy2KQG2Vt-qBY*_5FVR`@K6X zjM>bEHMEvDYgd0b$j)y$UESV~J>0bXU5xzoO{u4i_8(8*UH<-ETe8%0)8}Gf5K4+J8Z_m!}3%r;3&j&mZhZ(l#36fl3eng8E8v#kE^>$Cs&BZU9(!udBopSRE7oPPe?o8N7p74BbJ z>MdU1=5p>5=aSi%AI?!Yr*&&{x_?^O@}j4w%I=n4zxi}}{JZCDPp4^jJ};4A=WCwB z_fDg0@AZiFp{v7w#>tuG+)zwcc$jy>@S*U@?1_gThA#J$t@n$oyeSRJm?xyc#SnO4 z(B;#TTQ38`@9(MHeEqq)-<%4M+JAG3&wc#EXZp3Np)P-p`R2sKY}OSY7VLK~WA!ii zcvSqk=3?fT&q{t&p1X1|y5-|k?eKHAw&lKl{$Nh^yPZ3~OPo1dv?vr{YAJ?;sn2bwpsRk%G10u}YF z&Bz&TWtr7M$uDniUan3MU3U54>^tT6YwP}ldPw(wt6I+eey{rc?^A_wXYTE-{%gC* z)OVK2N8@G-<7FY)4hpM@)@Z?Y;N9Kb zYu)?h%(AYma4NOZ-}hrty3e<_x2ONSr+@Ng&fQ&CW6vb_+dg~FYPkJJ=clKqZ@=As zKd<~wVY_VUl|V~7;in?!WTh;Nmh?&*9|Ltl|5vU%7-?0ZC=;kuIlrXD%0}Gw`U}nD zw+fdD_x11Ozs~!iX3p%xH!SnptGDLey>-s!v(Nj>YU@G6R!b1&Zim>$(x|!76YWH% zU0zt{w|9@i+;a;Yo8P?K{od}0%+&Zvmn{n(G<^43oPKMOYj@2&#_tz)7N`IIJpX^r z*;%HiKkCSQ^4=kF?##jJ2m4Q~-k@f&kXwJxh0R(!d$nWd`ZX9ggN7^L@BhEAdhXTL z;lCp!>#t1``u=cdzvVND>l22e*Mh2C?S~4iuEf54T6(YY`AuPen}@dRxSHO~;rq>7e{rd|`1zD4 zOWEe+`LUP1yOa6&SnuZR@%4A7=|n!NUtXYoM$@kCbAg34oBw3d8n#GzJL`l44Dr=5 zZ1(q82CIXHVyk;xVtjU4%g*cn8oj%0EojX3_r}^kACJ%TzO^yAeg5XjrrQtyZMwhc zf6Vbd*|+8Uf6wjr6w$5z_U2^Cgn(5cn*Xg!-fTQB_Hi<&VvC0eyo&4K19i0S7M<3O z^M89`Ve|LCRS_GL0_~@5IArPHe#>s}+KAtAd#fVP&N2-fb$U!uXXvUB zP5+(UB_&oBlCN$%xAT>5Z}$KBYNTO?-`!p7JKHR5b(n6s;2GQOL$`|9&QH+{ z{!^S1@guHR%Jk0GyEUKBhV3qU+w#|Sm-XBaJ!dSh|NHfN{oBR;cAFwMr`>#Wb93(R zZ*TXRS!^u$CiLOVk0!TXshdlu$GzJ7;>3H6^}$Z6vRp6}l@5yBUJE!-2K4)!K`>W*q z`ze~i$Bv(P`J zUbl!pdv9$Q1gh&6HNs037k10JUsSL9wcq*!s_te@R`>t*%SP_$n$71n<=x%&bEp23 zR4yi&lZW~3-&7jZ@J!KGSGezA9>HC0PoGouYURCn9sPf*ckI3V)Wxnf*7|>I{#^Fr?6$nSyPU7h zNawe`al_t1e`oU|XRsR)W8E+}vX?uoowLuwIQ`t0UpA%x?Eii2FT3n(Ug^L3&ABR1 z)+c(uzQ50xuldmU{T9=^tBYK@?bF%jPnll5eD&o-zmLYRudn~U=G-jP>^qM?ly}K+ z&6Is7eQmN3*WV*2K3rKDd|b*TBY{`iY)jG8Q#&7@T791Lx{vwt!xbm>MfKzEY)+`@ z-EMcMIfw7OpZzYw+)w@$vAcpBMK1D48KTJQrT412e3Fuz zlr4D91v34rFWkpxd*K7e&q9vQhSQQ}IWv4`7#zIIHbGEneG#ZKd%OMqJIRGE*#};} zC@B#9GOhac+USY9ZnrVOkUkUdADd~#GrRP9{x<8-K zFMqxv_qJI%M@q4Ud;7oiD}T7Vc%{uMV&(V`$1%U!YvX*pPj;_bkGJCGNgOX~e zW`^P6WBu~)-!1f>t_K<$TOGAEE2vLx{gTC(AI_O0XIu4S^WC!Bx%a~LCT>-my*cHi zQ2gbKi`{?Mvs+B=s9!G>nH^XF%55%R;3H5SFBFzf-nZn`%MaOBr9XETKfkrO-!AL) zG~Lg)EMC`K4Gq7UIz9H;*PnNagimfrKQDLwRl%}zr>1Hf%W|z-T=(}^*~g>eyTc#- znQ`Zi&|^jZ!!lo9URK{cU0P)7<%dycUN3NL&iVJ}=RN!0t&g=MR~%A_oy!-wW^MHL zsO#%u_uh~H`s%8%6nAm=e&y$%-)_I3*4JA5`N?GesMpulKIQ8Y0L5~L9a16wq~y}{ z3cvO@$BWO~J~w^qlJ)t^FRt3_D^5?oxNv{?<72&h!|v~?EdI{N8d-moHRslrlX5j5 z9A}$mPkVc7tM=y{k$I|5T0ew-Nj|Kf`rW36P5$WC0`ol|tQqH=JJ87dwuxKs#8uv< zmtIa#m9#Ef(<@_n>37e=q7SL*b4#a%u8XmJ_&TN4GC}6aOs{D=FVo*V+2+^!wB&~U zpX$P2FPFy}ibN zWuL#CQ~7LW+55fUU)ju6a>JS#=UvXcwr1w@U{J$v{q*M{^ZEH&Hb1kRo^o!E<-Agb zWXG^3)AfOi-5TdE7UqteTlo0c&DHDoy^5UnAaIBI^EDrQ?(QlrmTzX)jN7y0dW&+7qlr+>In z;K0nr^MOa`vv0iNyYrHc6*K-c9k+b9#1$gL3zCIi@QWa$n6(>-LkA)vNc)UT^rk z^x@nf^(M7ckF*~vp}hW*NYd_4d3;#iIuzN z{<^rmx9)S#W8A?u|G8_vRSk>W62G}t?N_Gn)W4}Jb3A+f-m;F%ipkFYhBCsIlU)?d zUHe*$OD(+BLmxDM2>G()@y-twDfJ(0cFbMVvae*$Oc%D!xO7GtNxS9g=jVm(tNGco zm+$qp_3`%d%GE|^%BO0D*2u@z{d_ua>cgs(DPsC@Z}guv*1CPuvXK3z@Ox_Ehxfdt z^>dQ;?BV+)G>8)7% zS=)ST<*&&POF+%%N};O2hsG;?)I>A}-xRdPMJ8XZ~zwm8)zu=l*ol=S&7x%pE zUteC<-Ls8PmgP9_nAR*+-z}!QCoX<9-+71nJ&*hC?`_ruO=CV!*<>eO-BPKZ$jq}{W$r&ApT!$=G9eG*Qc+!{BYi#*`|uC zn~xt3+;}e0ev{mt_SX+o;_LsG{@3|E|L-};0MHQV|7g|xfGwcZg;6#JT#nmSveI{s z#l?FypMAeueUUrd7+|kH-$AVPmc>8j^9QT19JVx0e|V_1uIwymzMTJ|JE#MjeR)~$ zZ-%TFt+BGy)aKffb=%-w(6jT~;dw)DmC{Cn*yxNBJJpWU=v-6mD^|KH!-`}=DD z)z0C)r?i9ZT;;*|iHeG|kL-PEecVzXRIBb0uxsDhrJGui|7>&h_jm8K3Q{YSVxnxO z=|(?$F4`+^e{Zwl9rbI%OPP+j=XI1GIsKsQ)Ku-~#fR=pIG>nzQ`5;vMq#&Hg-o z>OHOVlXX%yosgSodD!xk?XknVHux{|oBJyJY{U;cTjra`AKqG&0jg6vULa=qE;{NUti6;%2|8rhfHaSjX+9BCSOr+eine+KAWv_{@KRnanPPcK%t*zP5{krO^-h4e|!S3~>2h=`9Z^`iPPii*~ z3R@HL@OA6t1=o6w4+ID7R`))5e&Wpq*L?TNu{+J36BqjBz@hdBwMD09i#*#=k@rb{ z&j;-*e+z9lK0avr;mi|b33k54$;bQt*`?q6^78WW*T*b$i==y{OpE*v&i^T6`ad9i z*?p;-GSB$03)Og+@o^qXFXa0nEaSgN%JljH&xaRYJpXpD`u$JiO>8&kR!=_h=fSK3 z^^~v|i`(mycxw7TUi{qixo`)29Z$R~o93IDZ%!E>T+YJo%-30$vvaQWk*x)mDWxas zCKf-M8KHjcxbX(IGxqyBtLonDh`fC}Z}-`|Dz7_&pG4l=zeD=h)s4qbnzueb_Pxc{ z=e*@N{Wzig>CxLfMC3qqzF;kUN<+!&PtaVxuT@#+u5^EtNijX4;UZdhb=kJ_-0vHi z7uub>X|yKx#aGuhW_HKBvvruCp9*k(zW0V*+DnGyLy-@bSunTl_24)Dq^HP!D9+~P zlF2sHo$d9jR&DIt!E&ym^5xR$e{vM7)_gR+GWqaMr$}R&GyI>w9Ok!Ad2RjZ;GBu_ z4`+Q$*#B@*g!no8r2D1s?%ezw_(kpX`8yA+n;vteb6)i4U*G)xK>ow6Co&(_OGL*N zIbOMaQ@GMHynU-ucJuXvA0H%1$V;j{n_oQPMB_uzB`dy{!H-<*GS zb@g8!xplu^E}vf&r`^-IMkL$+Ui%x-ncDM2)g?{C56n1G)Vi-!F6 zk{_W{tm;>=2WQJ!7A=|Y>Ri8Ro^5qi-Q(#Deoa>PUlTX+K9O}=r#h#w>3YJQhcUBC zPCPrp9Ny5sAYURm$!1}?L~XNYsQu)tsv=@**!$i-ogV+K z=L)Fe{@wfh)JfK-E(H~5_+R&2pJ|xfw)fku?03#5ZcMONk`Ip9aQ=h-mvxV4MzDVi z`yl+W$g_u;{m8#3m67WI`i%0|l%G)f7}xN6)3-I&`rk@IWEmeHa_p0}zV`p$BhEs( zIo%?^6xu#7SY+mg(ezvNrX;EUuZpFZbqoS4$83Os2RV zcRzO#mL1OLx)k+|OJ9Y2*O}vA{A%U$WqX#3{hn2vV{yBEum4#Y_XcaBm%d@knSbn? zFh6tu)NA+CY0-bqzjesy)VEx+I#zWr5dzg{l~`F)yhblUnopSpUb&ChMizn{k|WwPPl-`~}K z>Qn!2I>G$VApQKj+~i|D8%?vXMNHR=eRE7Y|4WSf#-yV`W%_{zPmaHIIPsjp@A<6k zbsyz&_qgBR*2XI>*5Q1H8>7fs(tP>g!+_1tcq;0aF6qBDJAdCxxwh{L+rCG|O}s3~ z%2@rSkzH;>>FaAZ4>q%}t@`?^?wW5qpRA30@T!oNOR{gxVLy7mSJivkjTTPfoNH?$ z%RZe{zkM}4J~#LFwy#n9UOjv1UpLoJC#C2_O6$GsFNwSV{d)cP{#zkcuOD^?RKwOp z7(Pw6eAD<7MZQ`LKrBG`q;MVz#Vx*^Ozs(SM##as{Qx{5>DrKoecl zCQf`9IZL_U=2F)6b-8bEZ{H3YS-b0fa+0d?@8s6?A79;3tQPyl_vzNo;^m+1d-vz+E1~iSK2CnN&VS`h@3gF)DT%8y**aY~cZPI)alYa2#Np}k zm$k7okuy`nQA9*EDo7y7DJ6B<(!{83D|f!1>Af@M^x@|RV%`16JT^0KB%gf8X|B4@fkK9p^xa;-0-BN%5 zpS}5d?e=?Ko72vEWnWw4>E0)EvVU&%yPcUYE-cLa@!{diPp9?$r^gg|zPh`++>U*B z>Fa6vZ*On+e?F)9-2XrOA8juD^W!6^)>yLGy?ed zetm!6-gl;v>fO5EZ+*W>F3tS&<8goHvokX@-`&~y^2y1`zMqUA-2o+o%QrSAU;g=g z{`_M-l9Si%ez)t&uF}`LuAA7rmpc6W{r>sO{O8ZJ`~7Bfjofj||6eZqFOSaOyVbK! zj-mIxxi32d!vcx3S4-;te!adW_x83e$;bO_()K1CY}%4^wChhyjN89IpU?YVDsEcl z9Q@G7za=*Ek9vp1`tXt(X->&x4TJPz4 z|IM$-&hP&bBV$#fA!|{fU_OUe+U&`BACm_3vE3`X)rk1JuWzNET zpcOsytAm&Oo&Brd_qe9JIR8Kc#Ff3(<+jTm z&R#9idL;Am;$rt#x3*@#(<(gYDm=$5H|o`mjmdSsb0*KVF8_DD*Znf1#{6Z>3=9E% z$Fi&nH6>)17kNr#2k!m#YIWwm?{XQ#Dk^OTIS7F}K$LUplnN|!>FPAVdFr2y=;j8}aPR);p z?Unz0JC<#(`1okoGGVQ|%Xem4nJl$fzyJTg-+TOS9ha}4^S!g{{N;ate}9h3GK^ol zDctYr<^aLsiX`2wGpq%x7sM1CWUc%^*IR$D$@|u#tD)gb=h;?YTRY!%X4c&jr=>Sr zcJzly_^O}VDe(QGKyu!VnHNeJPAz}Qz`!tN@vUXT**>oOJ4=^6GAj7}?d{8t$K}s| z7IE4#TjF?6>9s81%L`W?{VDf)>CvBcZ*FY-Q`upex$*hAcXxLe-@myz-GAQo;P|Bv zk61-Av-6$#T-e4ZJL|V!$-IcwYiI2g-lC(s@TG~!=YvW2=XyQg`KU|#(qVr4Ic&UA zQ_gRnabDQgFz$1@iEP8COe+QkhNnMv`>H<^5BcTWVf#?N`pw2WrH?jd*vvM|U3FW1 zpK9mFPe1mm`OXS?z5P(6!Y{uXxukbdXU=vS{>iW{%(n2?o#p#xr|@^fGP&Zir2feg z{^oN3-V6Gse|vNDXY~rzl6UuopT~WfW5NIUPWSt>lE!IE1eM*ctmT$?o_goiWq61@ z?w{rN*L$}_d!Hry>FN6CldmK`KR5T~*6VSnv;DS~7`j#de!KnoPkx58x>Y}_-|wA% zeRNNMwH+Pk0zq2%C+nIE<>&qGA^H)sg?D(?UK7YCD>OZxWslAE~&&0AnPrX#^bol+* z8OMv?@BO~4@bR&yf9F2>xUcs2ve?~aOMk!LAAgxqV+JIF|ME>g)WVs0ZB1ll-04NG z-IqR}x1WD~Lf7d%H&bM%A}P;rd*0nkmCxr+kM><7ZjpLwip~Fz6W!%b zzAj|*WnW-3i;sc9!BWdN{qwW4l{$G(PE7onzj^aVitoHA)w66aC&i8n~{Q8f(?Tl@! zzIYTrJ99GoG^5FO`T9SG_0#ntHYm)sDqVFg|9Ma8iwlZhUtQG(Eh?9HKVA8tk^R$s zhBc9!)oj09aDLgXzi-2QK8J-SvJ4CjMOX5zCae4VeSUWKboR>@W%s@%zO&7qemo&i zop^q}y?ySD4T}ADkLn&%f1H0Idee_uF};`>?{>Xj7qwsXfsV-ig~sXUe2Sl+^Huks zx902ZpWYk)rG1(0HCfW8qF|O`vYV7eL4sZ1vEr9Yr!QL=d(+*tQb-+ zflG^z>AuSszTfv-Pd9d#N$%}!Yu7zLQh4V1$`xDYO>?=-n6+}L`P>ZsufM(DOg66j z^W(}=@98x)7hT1lKAvY={qO$%+W&vQo5E9|#pGqe)2lcBi%OmUKB8Io*t>gmzu(r# zd@kLVe}CS#yt}s+ee1bU(h!w((sz02>adrOy7m2-*?2ra>mvG(&dU0Jw>>l4B4XKB zvHG&FSUT-W$)eLG@9tQZzPVv&K7Cv6?Pb>Q_Za)mwc45&=Vv2-fA&VU+wm6>d2_zW z+_t27es3o4Eqr|J&wayi^>0xTdnyXwSt;sCKK}S@Psx>%hNxAkmpj)9$u2iKt`_BI zGG}A*@n>n5ca^^06Mt@Mc-+k2=Vo4l8@bqUwqM6ji>ap%WtguHU+?EVO=o4c6(||K z-}Bk;*TZ&ssi%Mc%g*8p@ZOqZHP@=tYq5JjXc7A9;}=WR{N~Ka+xPR?u1brk?}B-K z*%#D6vX0d5mnJ2zuB_an7M=QbYw7E2OWoybO}5WH^%*ofxIR-0WZv1EB~~RbCRBZY zH}}@|{Q3RWUtUa~Ms@n-Wxl14XWibG z>+Ns%GbL(&U9DZ8_o>Uv{hx2WE!Dk@`ASf*+1v1J-&cR{m!Nmng(oW?9qBB2b7SK!+p2$EAdheL zRiEWCT`xB1c%SU+Z--`@WCrDF%(X5*x4!dvQlH;!v)oy)-u~A_m>v~%Ia5RG{IOo? z%h%)UW6hU8zgvF)Z13_*wU0i&u&yt$T=kM+>zDG`eoJqMM0vFH$$t8NZAanbqRpMh z*?A-;wDHTwZEm|f0TGEq+$pC4P7zw?o=`QT_(^yI|* zf6<`SzyEeg(z~-KCMpO2|M$1}cIN$kwX+NoousVGa^n1Tw`}oS^patU|7Au71`T&j z-{t#)m-{{adR^;taoGB}xzEnepI`Ro#>DykhL>Y^mp#4C0y5G*%j#mzuP-krU-##> zt^RhVHs#C=!wJ*<_-}l*F{{GzYxmKm8eh2c%+3Yy>p2tFZu3fFwdP&Lq+c(yw zxPE!|Bk$Gi?fJa-@7gbh`}X+$jW3T>Xllv)Y$2J8VTXF)oxateA#~tXX^vR}p1_^JT^bQM33Q zenQIp3@e5ZZ+PP7^JQNc$t8ZmV&%1xG`)HCO z0|P@yMMcGo$B!RZR#whjym;}>UAtz@ojW)6Jkx>$ckkYvGjHCx$B!TX`6G1a_U+lX zZ{N1Gv6(Y<>eSTp%n$T+z{x{u79Rts907MNE;wIiR9O0w;S0EFUzK6Su*5{Rp$=Rb z@cXhiOj*W!0i2UxEPTl@;Zh01FK|oH)QorpsjtGB$E4%jo^T_>wzunH~ zWB`E%r{BJyz6=8cLqLU*EJ%o<;n8GJs4y@vh|Kq42MaCukpk)#GcYh5RR^^K7#J8d z>}K+T z`^1WYA>bg`TT}I?l~sRx>3XyC%lZ8M{r&vRbI$y>Q$YQvE6e@o z7x9ZSF#PC->)N_?Yv!FDg_#GNSXVAws5sZMSgrK!Ez{VlmrFBmY)E{$bb6c@GaHY_ z_W(wX885EhymDmQ4Jwm2;Omqvn?1t5oNeGFeg6%(9>$DSN}ljfQI@H>=ftJSx6&*)p~Bn%Cp& zYj^$s_xp0M`MnvxzP+7&UyxzJAGkxc!`67{@BdR2wWp%cs^mq$KfP}clJwub+x^}z zf6qs^U2is>K4lxiz@?H^GEF~z-ZJ0W)1IB1J9}I1?P<^Z8=2Xk&70eA^T|WXD8<9- z`J7^q+DV|au|T4t6?JTR(tXZbnVW1wsyZOS;pWi9D?EA8jUCyK5_FKfe#mo$< z%l+nh$=7}fl(Mg@xwWUVI4dvjT(Q^rdA65D!(%4St9&-|%MoG!CvrIqQ^3h?L2?Jr z@^$O<(yi{-eD=MyyF7p0>7CE#Rev(A_>k~ElKF$a-#nX{px&ZM+L;+O^Zc&7ZCUZT z=R3o^`hP!bKp~bYr^(<5N|F~0kJ!cRiQilN{M?rG^Yi{#etW>iBQZg5-;YN%>-?tc z#h$YDVc=4ERbuz=$77SkLoJ|@%PUu|OxfRW`FPdpbzaKueLns6|0-6kTc`KggOLN0 z&QzyW>Q1kk`1nK-!w=(+b`Eonf4iAJf2n2hvn9IG+n&5<=arfQ8ikUp`|+^k_1f*L zKC@_WKypoq-$v6LH*Uw?Wlf*J+nmhp)e~HhOyzzhJ|EXwIzL@4F&j-QnX2l5?d) zwMFqWpRBw*KXw0kXTHboD)9sjTs)swoj22+4OB$TOtE5ci0+hG{^jzc3k#hyUtL+5 zd3KiRPrFZZ9v*IAemj4^ZD?rd)Z!TobDeDZz0W`SA$_yz`nuTDHd+h}58i{)c&?(+ z9MEvOVXfPXBM-*xZyX~YASf> zx%&G%P~?FIltEds(EP-=2JlSFc}RUcG+btZjLB zXTA5IZ#TDiUh?t2r@wD_%h*aKonuj`^nFjy^J1I&?Kw9mfs+3E+}qoh zX0P9C1{&Gnm9f}x$C;IZ;h)k>K86qbJKm_RyX4<4svWkZ{C=(Z+xz?N@5@^jsa(Bw z?b-f%w`I&1wmqtpvDJUvwfS_}+gnqA$6mW~WeKme*%DdnvL|o;9%y9#d9&v8S@Y%m zc0Uw&zu7&TJR`p9+nbr7gvrJ$HRZD`Ll-EM{E163-e|w0 z`1!dS`RqNQd4~P>V^sPNnm7DQ#kKWwUYm{`Dy=>MD0)nQ9ZUtgPBd;a(Pe<>4QGHjW9WAg8h z$K{K!-COM5|0j0NV&mdxXSSrAoOI>JjUVm*-Ip<6s63kg^F-z%KKr6ME8h3WWe3g{ z{%a*ICG~06f~Wcave)fY^POW6xQsc#z(|(iMNQIr{i?4n{jEPV1zvAIIa&R=%Xv+08K9EZ56>y53n+%a4{u zb3sX`>hH8-uTCHK1v65t7%mhZHIcX7uOBfa;cdp!PviJBc-Fw$T3!eWy&1qfi-v2B{{Z;WlO(WTcZ^GyQo_H#* z6EPvK;$dsd=FinevJL07pLPEI{r$Q2xx{YmPya!KJp1NOeE(-2+{G^UTPobE54Z7F z-W9X-+tdI3Zu$MEb=*%?E;DAt2d)M!*If2|UbWuZ*xldw|Hm$4cJRJfp8M|3PRs3) zo6~ylWiyC6En{Yws(sFK?fUihx1)8>os_h%tBKlC@bKp50;SWLr;7{!Y0czw_&w<* z!v(3p&GOGP`=m^@bmR6!EMpE(OtE4Juw3*`EvwMW)Vy%r%h~z+W@cq)f0okOcYk+z z{<(@SQ1;!IV#Tn#E)>%+dF_GAe|hVD#0ho=)?GB{M4n3^sH4YI6_+iUgyu6Y$z4tOFKHM@Vt^D1cnaBEMXJ=()eX4z80Sexl zIp+*yk6RghOFVD?{|{&oxrm>Ag@brZfuodZR)~~Y&Wz_L=1+LZZ~-0;+eAyvHm9HW zGfqEeQ?2J`QS+nV-D)w*zL(+)zAB0L?Op0FUmLRQvpOh_r}?li_;jL#VL`6zGUN1f zb4;?Yt=T-&ueP@K*T3KI{|D@5KJfqDA#Q!2$!flnUjC6rce!odpNf56mvf$2KR(uL zT|Lb&#g?5<=EU>oC1M--diHtlt^Tg}J)nW>>h}EmUruSSU-J9iZhv&U|GvGwU4Q*_ zFG;`L+}v{&k9JSG(f#_ws@1D6pO~n8`NPA*!QiGXbI5{scXuy8t-s&q>+9?5?>K9! z%;aNOt9qGng^iIc!;j}jZ)u(bk96zAAB)*~_Tdn#i_ zG_n^yobP_QJvG*E&C+{Suh)hI2T$H_U-~KpG%|Xw#_CjvE=t1u$A2%xrxMgbiOsnB zRsO)o^Jmh7PkA<MTOR*0Z}t86<@cWd z{wrr+_osq^p|bSLi;Ec<86DrgeS5QG=~C5c`tfq__kNEnDJ@Mszx4X9czrizx1J95 z`87uGcE8^zVUXakubnxdsP6yY??0YQ_D?!FN%iAle)}&Ke{W^4?=`<)W2~jE{n@~Z zf$O5b{a=x8as58u*=9#i#tZt*u`pb6V zrE|W%zW)DW$))dQrlzJFOJ84m@#4ja&mR9Jec2VZo5(U$frj+#X7MqI>?_&j_j=vd zty@!%XWlz^tXKN+)9LYj&z?Pdv-5B}zk6+Mt&DY<&U|NERSd23OMdz&I#UMatHD~Fw5 z?o6MwlvL8$S*9Dy-`}g@eeZ7~+i>Sn3BwD}h~ke7D~156OXZcB=ls6!nRBHG6#l!* z-k$2aoNZnHu7{bO@5_#OYhesMvo7tk%B)%gfh%aQwD6zDn=y z!OIsf7P?9GqdV+Z+qZAua?a1)wQJX#I^C^vwq{>HcC1%=^S{a2v-lkHGOZZCfCfx! zOk^2eSnqoNTqX10xnEyjC!e0C3yKWe?X|zZtys72-{T)8mr59lye~5@*lr@*@M!T% z28a7o^cXM6S*xGB7`eBqbQ`<>tizMHY~6Y^fB)aIC`_lknD)yzYWCXItF^8FJ?hqf zv~u~pQ{SF?UP?W@e{abJG{YH|2L%TUOPl3%IJfhq9{>9F>&CphyX?O`dC3clF6FZ~ z?{7?Y*NNR_V)y66VY%zy#p7!VZNA?rF8qAf{P+UL=1(SG41UXAGBDIXKeE#jG+ccx z&HH=Z-R$je@9Z>|l9vAe{=fTW#uK`}><#xava(J+dkWgU`|)ac{MQVt$H)8okIPl- zJUcg6`svfB&t5TzaQLz_{8%1z*z>R2UtcLHsZD;LUoM~j?_%90Ih(g{-`f6L3l0DO zA-D96|N4QJt8`7(4o};E*(%c2)m0~EhrzS+^W~?zgPUfu+TaA)02~i`SCSoSf(Xz32A!{QkAk+ta?+&*F1<_b2wU=l#8BXPIip zRlnVuqbtksYudVX>)zbikb8SuPTb#nd#g8Rf7$Xa%G=xf+pm+CqOxB~)xEm15;T1< z!ywVAY)+kY!CBMmM?h;+K6o-*C}C*0tQs4(r1Uzd=9OK3Y;)e-T@f3TT+8Nsi{JbC zob}@R|Nnl+(5p!Ess9$xY|)b`J~_H-Mc`GJ?^tCmf!OSi51@?yu+Y0-~99+&U`eBR!^e=&=K{3Xjp z`}WzrdiCmGk)L0FkCds_?9Z9+Y#r({K%+KC-@l*bcZ>faXpXEdeC{pKz{ec$SneZ` zq2Dg;e6?zI(!nOy!t1f+u9cOQa_*cA41dHy<5LbFtwS$+{+2&8(^&o8zTfY1_*+1S z=M+w1U^q~}5Hw^VvOm~#?w0jmZNJ|U_MWcSd+OAwHxdjC8h#M%zgI7td@WYmvM9yo z$Ajj`%bvw0poC--#K7rKzKwX`-(+njK)X@*^G z)tA@T-=E=;V_-PJ2_DuqSaN%FUtiyf)vLQ-y?V7`<;s(N=WV~=+3{jgchadTnuc|M ze#qsjt=+w?{{O#-yh#q`ufrB{QbS#wr$JVcXmtWukVlCoOX0a;p0bdHlIKD z?X>5mUD@{kek8An-E9V1CADJx`hHGfwIg?S7C*jM{l2$TSpAhH14954IEoGxJUKBj zVsBMxNNDKMb+Nk_ZQW`*yZQ3|`u`F(6$L$VwpM9pW(anR>2`tE+_?40%zQg>^0QA% zO0UP&|NWZdKi8!H`L*bL(89qZs?%eHKnsGtyE8K|_%TC+#O(8{)$5OKK5r-e``g>@ z$5X6g+D(( z-w#??H2ZvVA0Gq56gG&NGPYGF_bQ*yt$4X~`lHkO`+KHMnj}H%RzujYGVCb3-3ExX~R-o!L^YXHs zduQj_RzLdi@bJw)b4}9K*B+j>#BcJm`%BV{b8c*S^S)I)PQp0-Tn}g%LT|@|CJBpz z1wTPSnFI;S33=y(_OD#OzJLAxe^#qjuipIAeCyV&7jN8{v3B*eCCiM{&diW7&x`ps z!z?$-XO@X(^}0oilwMmhFgU!t2pUY`@}4!h_``#PD^{;QEyv5td-2vSskw9K-h7?; z4>WhWc+Vaiw_d5KTjzYa-^|8qWX{gO;00L?Q*mi+R8;ob-|tTb?Y8`wcwdHrK?64a z>+ldfQ^UZ(zy+Sb0gbc#06Ca}fuZ3Lcm@VE6boM4#=yX^-~)KRhJk^h6+Ddt8j7s} zu1@G*gsAx z{&1JC6*+J7*~e$5k?UnfjUb4_E|)O;((`3sPy#Lum-=63e6ia^w&4=E_?lwp%f8_K zr4k0Oc5rh0Wg^?K57aJ`#jp9Jy~EqR;4%Bm6=9+G4?L_t=R7OSW2InILfZ^i3BHR7 zQV-iZt{6>S!S6e3TC4ml6(8r#CcGz~E$T~a%QMD4-5_#2G#S7%xqU)M(IXx>)BWPTdcTAH)_j@3&Knj zmdx8+`1n}F<}_a!yP6$J*Z=%}zd!lsr>7e;FE88i?N;{U=amy!H`AKpA`uckL zYX%bqaK-b{V|~W!>+Ab(ZcZ1^&IWY?yJF1Ga=*L1UH{g$TSy=!38>w7 zr|$RLqhA?T%-Lf1d~W$Y&1+Ye$bkl=t>TS)bu-ucNpauWo*!>AW0%?7E8j0iO!)RC z=kBi3x$^}ZlELcHxC8%#>$bUT|?(U`Xo1pU%?^M6vd(xvzrP{TS;n$x$*umc`9b_%wf4QN!OMJBe%{W+AY%>j18BwCnuv{y zZs@<=`~9A_m4EVurQXveEQ?Y=wf(Q}@8fHh^Ey1uy}eC$nqI8b`n}(x*2L}I6<9j= z++6G99fHb9XJ!~0W?WGCUBCnlmqM@S@_RlWlRjF0;pObNS>E?kzrVX{4Q|}WRb_5W zV{iC1aoL-)x3@(3?f(?m{C=~!@Wq9NS@xIyzq+{C9n=xf+yAF1{Uw8m0oaX&zvdf@ zzT5x*-;F($#YfMbvJ1@2pZoc|{r(%=84nILhSrKT82$Ks-ah%+nVGJaZ|7;t{hX)5s?WVIgJcb0O-^F%yl*XJwS z!q!HK7ME|oTNWKtbW-)GTn@vP^;_bM|Gtagl;XMP(<$wbxAXUhey!QMMNR$f)@jF@ z6rI~7xEWSCfQq$@J7sTf2!f`)43}>&dwYxRz17O+F*P5L9^J{g*sZtg+uPgbFa9!~ z(ph^J+;86bd|o%`u(pi9S7)5_eqF4$>&2oS58I@>>}9P=GCrg;Kumpespg)1{U5>N z=jVDOH>a8Yn8`KQs#NRU>}MZtZOu-fFWbO2?b_>{J39UE?_7AxfE#yYDK-gyj;9?`NDG{85bA1&Z&Gh^Wza=|05lO%2H3} zG5m>--j<^|>)h`5`=oz=f1iJ0t5xRtt?OcUA6wjSCk2}N`E(21AJZtDmQ*>2}YWH48LOBDLoAlCKt- zIv$T5URl=u`qG(pcGlJ3wTwUhgKKKv!xNR=yY`l+ou3zb=K0@0pU;1-JAbg5T|C_a zbhJ(RO@`1Z%RYb(@Ob1i_xb#KyM2E?oxZU--GA>rE+ zB*tag`Q>^*4TfcYbEWe4{Y=|?SG{)n+;iR%RwWsr{>HBI_i_2(nI7C&lDTI~T>8;2 z(T@+B`Nih$w_E=0)|O0R^SdR%KC?_#zOY;ywRP3@YQ};baNV{n_5Qxv!t=J@k8tbn z33zid?B(@cSBgOeKzMv@so`|-G5l@c3F&P?}`tlUecNt9AK18PJi;()oJ~+jym) z?apa%OFKPH7j$~`(dhiWqM$K>Teog?-CrEM+^_Iv>U7cMgHyxfBG=qxT<{CxSk=A9 z-rn79ZujfO;zv2419!#$ubUFLx9aHQe*3sHPq$`YUzc>9b%D{PpIM-OZ!5RBo3F1g zXsbuzj}H&KVyxGm_q1JJ|Noz1<)+n#uYr^yr1c{z8KWwvVON?am41}@JzY)P274Ng^!ONHN74qe0O*G`UAmC z0rNp+ldzgkM||DSrApVmbL+3H2sF&Tw&umPwb8EYI31pXTVuZAvkuR;F3&Su4w~w^ z@^a0aX}ZzJW*8GLX=S;Q;;z5g-m+M3A1I;W_`pARteA9=Za zejL9)x5H9U!)f2&Z?`L+Omy!uoek;$3D11zZTo!9=5t-U-|bo*v3&Be#w~Ti4aZ!; z+4a_?TXR4IhPU(g%lg~@E&221vj6d~pEGU!X6^RQF1fV*=JUDbaa;24?wU7GtikK{ z{`&fwuUEre@5k?{D3r0O_^@OB#ns{KXIK;_#gtwRE&O&fU3{&4!!dWT>A$kFvy-o` z3OzcL>-Dv@*3ag9+b++(zRs}b$A=w1pUv+6yrFhF?}aZib~P5D!aI1mpYF9+GW{lE zJQ4;9VtO$WwZFcsT&~WtKnRky^!MHZ9nx!Qcl{I2Kc*}nei z$+&_WlnNC1tG~U`+;t9AQs3N^3K~27f2;J8P2BBmxsSWF*L6g0P80q8j^TpI()-_U zZ_Dj|dV2ctIhMsqhue4yUtC!D|CjN~*X3_+7`pYzNN&GZmHp-2UF%z0v#&e&^Bm~> zA%5g?0=R9>d1qN@r2PkLZ${Qg74agDZdvgK%cQ0ynzDo>&E`1B*47qMG?PJ;<;ba| zxjiPq4v{I696>ilSX2UUa;A8DrgTkYQ}M9%tl@E)%QpXhJXWqN`+7Az|K9I=-_6`*OG7q4o0V;5|Jm5y zxY5*CMX2*g#e@2P&+BJBJw4rAeNKVX=bz{6_f`J;`P}`_n_sWj->>;Jd45jW?cD9p zj_TKaWVvPpa`Ix=EGv+wLDsq`8E$?sH^tp2=d`rb8_ho$dbm{arVq>vq@AsxPM0J$$Gmf(fKNL)N%ic`=kuaVWPe&S8s3k~eqVKc z_pG^Pw^mkOT^(oIxfL893Ld`dAlpEW^-xKZvw8LK1E_9)_NZGwFK_qTZJ*|C`@SL5 z;`iI_@x>P$*{9Br|FTHjx2#mS(?!WJrQ>J${o3-2B~SAHJz%%jC~n?-W!v4d+t14D zo|m7BnNXdtCe(T4ixW!t88@E)eZBtg^=Dr$`|DSKsK}4*J7@R%&E+{ImpoO&)jt=5 zyz$KG&i?oNe$V2sec^nz^m=S~QR%g)?6uDp%m2+VuK)KZt=IILN38us50zz-L7;T8 z_3*4~a-Y{$zJT~d$e8v2-~0dX>cs8YVfl1Qa9D=b?{~ZNFP2=3Ex&tmT^uMSACm+% z={_IiuiLQm+pX;I3@iEHH;&J0=C`Z3R9gGf@l%`HZaI)Q=T4aAr!;Yeq|<{+M+Z^LhQh=O@?sfs7IAJaR!X{Q0-r`T2Q!zg`oqUZ1<^q}o|N>o*tHY`c{;Id(57 z-}D&ItNZox*)i$-n9TQE-)_6T?q*WAu9~fT`q!)B`pQvjeOCRSAyaXmQI%;di^-*UlJ zrX}-zSb2{|+Hs5NXr%wn+4u9=S?{<{lTNM+0;RD^a2m@x!e9U6@UtC{`?A;Vd^T$n zduQ#l`Y(&+eap5&42R^i6>RtPBhu%Vp0X=AE>rCDxhs56(x%l@JXC~&YZaM#aOp4EX?ngWR^=+;C_VtY0?>}>2f0@~TZAMA5Zve`<-I{;@i2~ zrxq__&R(<8ZS&`I*5kEk zO?G9QqmOz2{p$C7Q{(vee44smr`VFu;P{U-jX!eZQ=WsO>yP`-**~M>tK02=S3P?O zItDs#$HTT~7v1G`_wWC*RA2Xe`s}=2nXkSW3p~p){M%>!PQ!jVxD;qsG@a|B6sUa5 zbnf)MZ&J^0JT7-zrtZhXpJxo19gqKflWu=|PSvZGPirn5SQEKS~b ziA~zGV7daz>GLYnHXme@_KABc^q5WR-bHu$*e^Cw^Y+?+ zI(=#PYrp&Q6|gogbR4t$h=Jm=*~gFO|ME*% zy>?rcn10-yoSjdnO^(=oWP@T|eC5-rs`K=tx2^e;`|Zum)Vt4oz8^W$Z0skl8+9e7 z{_oeP<$Lz+-NbM6;lPy_=?ZV^>uzN(pZeqN^D8Bw9B%-PT6N#&{r_I{&-%Xa``(o= z&p14&v-^3{->m+VdVSD2KdwKI^#3J&29+OY^Zz}|SG#V_{89h^C;hYR_CF3j`#k^u zAFo;G*8l&tUVQHJ>GeOSt8Xmp{CEgdA_|>;`sxA8-t&LO>pzM=y>nOQxiSB}`~Pno zx4TyJNO*q4!k2&Uz5g5cuy*g`xic&c>i>U~|6lldrGIUfs&BiW|K;CP<9|+-d2Gz_ zXnX0dioCmg`#(zW54@I}UvXG^)B1FUC#id1$G*?n_v`BVY4_v5t_q)O_<#5Q-@8-& zTaTP+vb_CU+(ZT~a)U0f)Z%U z38RWZ)&GEpM%tuhpC`}%vt-M`J74~MK0p1(mUC9Gm)z%T*pOJW@!_rP^>_C?QPqE0 zx%Ow%+xgY+c0O~r{}s6TR@UmNrU~}f)sFF3m_1fJ*7p44^!SDLrf^W^v)ra}7g32P@x)tXhN2Gyj(M48}gt1Z>nr@u3tiCFk z&fPU(mS3%h?{Yn#a$oj#hjxM0^QvC0eD?46`+U&c)U$)^@;Wi^Cc4W-&NCHOUVOFf z*^e;kM+f^Y9(8~k5AQ1Fvk%_R-@kX~!#3$z?((%;&WKvS+2FkSqMNjDUWy)pcS8+|Nr}KUj1gHyX5=34}QI``@Z{Zulc$<7+ z+bzM7pD(^yru4$%Pr%&&59R+YoM~HKw)t_Nwb|_4Z8vxPOw6)6?6_Leee=FKZ(a)@ zJ|6Ka#p>JhlGVkK>|ix&xir zK4Q23;rMyh^*zfh|Nr?s`}+QWUnj?2)#UzTE-m#v=NqUN1x+aa{A4WM^?m=h?ETk1 z$DN+8uRlL_Q;O&38_E4szaFT*_jz90dE4)AR?4chvH!ZW|Nrm()Bl;M_3-ZMvHSY> zX8QcxKI?Zoo_(+X|GoNIKxNtfM_t;dX1(vTewR`AP`qxT<%0(1S%>-U_t@O_b*=V5_X8ZTc<)^zNTFjqG z@BOu8tNqU-v$EIST(kS#uHaqvTm7TwS3K(cRI_&9u>&E`1EIl&tB_f?dRen|#IBOe zO8NiKX6J(&eTTvy7ry!3%D?Do#WfG#<;FKAd}~^remFXB=hBR%9FNzW(skc9&wuNE zxln)OqfMvvw7(x%DOdaD;#o&_*(tNmu`vCAY58XM{Xc1+*XGx*{`q_V|KFlE3)2f< z7yZ4`zbskjqN~5<(Cabf>mR=2Yojl(--S1-4_B%zV`}P9I>UXQySQ~UL*>hvJHC58&_Wm@*xOTh&* z?)(?-+kP)0U-egGI&aP9IV|s={*r(2H0ZLV(5!S@xAvwKby@P6Zg;J z`*){iq5qeocXk$^-X(88`_8!|59j}TIp1sD6=r^$fVyRu|9)t<*V$uvqV~Y?FNz(pDNy6Gkx#3TdQAK2Mg}FuV44E`|Q%`aZx!N&YInxa!2VmL*Mjm zGiIH;q0sjKY5c#`lWU{4OjqOkFwfg(z^6dM+*4}?*IlqH({=YBFXKy}lw>#$jU#3~_npnA)<}Vo8|M8$)aT4rAwL#=zx#3L zxe}x4UthORG=A{;@0^2^XPvvzpdYoTqVQtLmzg^n)$M*fXpVod_=k#3b42O$x#iRJ z_w3!V{{2_UxQT98)-QW(d2LtNn#H0g-&%dS;5@s0|L?o0dsL3empnfqJ~iLZOAN2`kGe0y_K|HN7&|C{qqNgXZyA~S38kEQ3oPQBCSXd+wn z#eCn#-XOc)7ryyb!J75I-)_$ji%gyRF{5Y^@2|g)y7l!cqrUJ~udF(+FwgX5&fhGn z5`~X`^~dgI{|f$hE#$5LFHzg$GH0fj-%OpJ_I~g8JhS^XpEYgU357$t?{d+3h9Ato zy*}9PkY&}(xV}@n^jpW?%LxI#>V{hr__o(iwA=frOWSSf%PVZ>O}@+t_P5=7v-EoG z>CZmvcjn)i)pz^h(zP42W|U_d7X4mhTzLDM?3XQDuSLCPeeE;<=+DRhj@DX6?kK4C zc(wathSkEyn(?+D#6CG)i%g%Zxjz1!$O(Ou_Yv(cqSG5Kg}whDQkd2Eak2c<_ipvO z>fUa>K5x_C%su+?`}X`;V59u+eRi+uHHjB?g4PaiB;G&Ya;4;zQ5K(eei0UKlT6OFyd-68CmnSG zG*0l$uuQsl+2y#pDRZ;$bh6%O|J7H#$L`BQeo;S8wu>bSzb<```)3k*!H$h>t^RMz z?&FcoNo_InKc4gU@?EaCWLdC!&}DF`2+GKgkm~yvq&2H9=;525rer$zU*qI0?AO!n zKF@r%Y<8a3^OZhZmOY+%DpKiLY`XZ|f+QLmVLJE7 zmByVX=1l~RcD&p1xbM?;N7K1diu;dSCS5DpVg7oDxSMzRRtHF3+6l;hS#IA^XGJY}dD2 z*|X=C-`n|T&Md#A86LjN{h(nD>Nzw+?ER_;DKwQP%sO|*CCh5>M^MXjhvVs;Z#JEt z_50oK^+%k3&-0zK?6KInW<$2ZMd!X+e!1WreEB8JRq{#ha~3!ESAICiKD+Ysv!%-> zOIShUvlD6uaw~JmvdJ7vmKhsQoaI+;(VX=1($c3hzuqZ6uUlz!ZTsqVyI!?qTIq?` zzu)zG-LpyFdYZR{`mV*yndMgw)l@HF-P2h8Zs+oye?FZC*AbEXYAPd-gX}fKYwu^L zj_QiIVwu?$bq7O#2z~BhmeD^~zV&LDv}yiAneXA#-d9N0bHC^YjY3X&oW14odE2Lo zTc$PNX8*I?XwB6vFSFx+M?Fk;Tl|tm|7_mADWDO;X~wgD&(yBDSNdw@zE@k%S-oDf zVSU*P?*H}gc0NCqKIP^ASAE_|>SfZrce-O2y}xV!OKyv!<;DLw%if%v!G2XU=iswf ztKQ{^*qt)3wf%TR`0Vd{-}eP(TV2#Ql)Lpib%NFRP3xX8nz~n^?KSq^kd9uibhrD)UXh>*da0 zcHeF!pZ)oK{(aCS-C0nza%uX?mtWkVY1-|DuXXs|NHfN`tRAFKkWY3=lzEL z;Bo8zyK?^b&Tc;s+IVv6zLR}a`Q6gf#h0GV&cBzl^=jDJ?D*fe8jmk1+Tw2gZtwSd z;JWr<-(TPAkNWeDrk|e|duy>>x0vp$=*xlr-#KN^{GIE$Xw7l?`aL)E_y3)>egEIL zvZd29)Mx(=(!aj3{kO&ANS!41|J$!k@h=3`voT%m@^uxhd0QT~Nl)AP5>&HnzE|~{ zcg^dTeQy5?-m}Y9EO@g0MRn>5_1nA6^9mRDnrXe3J8wSsl#%(b-xUQ>uTII|?CxKs z9Sd5rs`c7vpGMwh*8f+I|9A(=#7}R<&GK7b_c7-9yDe>J&2F!WSsl-|()ezZ?OpXZ zr`-?j%Q?F5PfYzM&u?#^e17{a_p9^M5AyHVN*_PC!rSfd+%YFR+05gBiwmU_qjlNw?-7>51^p~gK_y7Oad-)3i?oN_PJc_^ZqBL6lkH+WT8; zm(MNJdVMN<|F5f0-~Z71`&jbv!ge{W`4{soRBGn$0@VVbf%EVkKkD8tk$rVAZ2O%e z?}sODco^+(Fl{Y}%Lpx$dp^X~T6lu1jQX&wtVP$8Yc5 z>dU_7x>d32zfUa$oz^}}ciW9cS0Z=co&Nvlx^=JKl-Ig1w|TWEn|K9Np;`-TkWsTvX$(;5aqV`<%ig}q3&fnUo7hO+Iv;mMDNenL#^E2egOv} z7HL**yH=kl9X0L7qW`rkjdRcZxWN9$+4^Rbm%A2M{dVfB+x%Br^;btY(ZWW4N%0*m7c;DGojI3d7_^_KX+!=G_Z#Lre3KVk-S?{`;P)oq zGbc|O%=;#ZcQ*FjO)2YRO#~C^ zEYY8m_y0UIpFKNo*UAq!*3Gpp&+9DS;U&QQ@lkk8p=;&zd!`n#^A8(eRQTYg+&lS( zx@%tR4lQ?uisVX`gMyD|O-;`K18V*J>1)23y?(FP?+-io{;`28hsecei%gJ*vqdVg+~X}0QbsmY+yRI>Qb zS?j+w7pDJPsCbd}N1vHo@fkz?3nfW5tCC-oy|4fO`}B_Pz1K4){Wul&KUDpD&Ry|5 zlUaR+YUQtXyzmAmccvL~FG%>T?wJZs-}@3s3h zv0o(i@DGFS(#~(Rr)`w}efoLT=h^pTuD!3zXZ`)r_$ycKjCIR(>;!)+UQ&6{{wJ_5 zG{f`mwT^dd-@QAZ|1$EG*jMWZ4a}!vu6WOuUAt`YyFk0>4gKFb8NayhntS8wJmsrZ zvhs&l@AlgpyZ!gO-P28{6h8m|h`aVsMOSsP_-Ae3qT9LKbet#5|?eDy9nBKyyc>B0X`cm^N8@b0hfw~{UQp0wATxZmTx ztu=0zUv<6P{tY{gzTZgh7y8V0_qaic#<$Y_9ZT1KGi5vT_Y+Sq^Ec7WZm;~4n`@QV z2h2Tt^UWguv#XEI`PM!4?e`1&RWSgmRDO&nXWtH`_G)m zS0B=X1J%`_2A+7(<(2H9M*o$PSI${hr3=e^+2fVBT{P9(^Wo5;?#G`prCMv3f3W^_WtYx9>pt5(POA^?)wZ5@ zb62L-C&f9M{j(33|LmJx?tfr6XoN}DRQ9#o^W7KLd^r2V{QKr(2Jaut0^Lac?C$%z z?_6?I+>-Ze&ynPdv@ZO)v3^?hEB(Le=RV!cOXu9cXzMZi>)yJf<*)dEiSLWq`*rEQ z=i$Gc=3fY1)A)yf`?~lKn-7Zb@~aDcbJjHMf!57w_V+6u_a0S$8Mec}?$ou1)~`i9tlo5|FS!aja&f8M+HXs*w$%RI zzHy=cjqtsT_g$0u{QSKBH{M#)Z<)pX`_gS5Iser2?ef1Y(_jYba_@7voXLK!$@hiV zD?PC}1&27#f`+5!NxjN2kiQ?cBaC(DHeG(n>TOk zmVfoC{!N<9=B4wWE}!B4RQ#7s$>kEI>-yhfzUV(g!O7d;fl%GjQTj>53 z+1B}8{l;|(j^D>5INzGTk^ZN7euBR1JI(oBh6>j<-_Be?A^nrfzatWwVQ$pq(9pEK3%xZBg@ zM8w~gH$6@_m+CH$FPvbp%deXMq2|Y}ubx!h>Aq3*<)Zug6X6^cX@~YdnttBq^O;L( zHWUAb?Ag7#$1gy9r~W6;E#16NzMl~1Ji9{H!gS95O}Py|FU`ClJz_Mzj*JT#rOLY=WEwl z4Rwe8cg5M4J<=?k`9*#YqhHv}FWj^IZfyT+bzb3@;Ww8aS0S^76tXWRQ(KgIo}IO=ZvYqltwv%%0m{($~&v5cK1e94wYFJg}CH<^d2^-2HN zUao#@=P#FYa=mAF90~32{}hm+`o}~5@$R2bL&IZ3x2P1l&DqpvkQV(~?!dp?oU6x-#MIEWUW-X&EUK{TH4soV)SmPx0fui^apg z1pf$rk+6mF|Mj$Q2RBgPSb%P5Cd6rS3dub-nc5yw1(qAA&7B-dkLb zzttE$dA_sof#*Bh<~4igKA-hiwsNP{zyABj&d$g#G~c&f*@S)0k4dWDUNvd_zjuAT z)qbX?&%0RH`q<_wb696Yy*BxE{@Zn3HipV|oe&IX6%=HV{7Lop5JGH7_PCT(+?|RP``+mbk{uvEFtZTK- zJ64|4o8WEavw?pezj=@QL-s%1_Ae!ON#B1PHH#Ude!By8{4O*=d}J?qWF-v=6cz;tL9sLzU9W3x5zhHWi3w^O0HU! zZMD{*?MkqH`?6%ce?N}f|6{7}`ODE8T9Y?N)nzvCzSeU&Z!+2|W8xa#e{n4AXUp1C z;WmBp!gy!qLjLcIu1d&nVgEnfy#0EZ{Nn)o)#hjW`d=E$Y`0q$xMNwcj>)~Fj#g6) zMJkQz_~I&TOl3cw-662~iv216yTSG4mrCx;f9GplAUnHTxp1yU`g`|cj#|e(8~Ep@ zE6-V8_A#?c$bRwh50U3jtqWeZwNzbpjp)LgUEH@E^EWJC_FeEx@oUR?JLz4A@BcY_ zU!>Qs_NM@E$NAIVqVdl9CU##xMqK}qld^7!w)FH@9@znUdzDL;+%Wh3fBE|l)83Z) zU)Cj;OKwcDzgRr=JvXCkY?dT2yPjTE~C$dd0?P25~pS z{bn0FCmVlbTDM$$Ztb_5Pj{cc{O`!g8`TqQcV$|w6<}WT7U|c;?>!$s*!9-2TD`K=a)JB2}GUpG&$kgYJ8 zv-VSgL513RkCGO@n9a}C_UP(yJzwGXBSdER-+i|luYannYA&Dp_H?WNq3d6zcAq-b zc=G+mX@{4#^15Ftxs|I__8{Tut1pXRvOKa)u5IK#bn@uF;4f=#Oka2T=i5^s*ICVV zopWeo)&85sYIbq|9Mvy8b+TS?_QCsSXJ?0hF{-ZWz4E`p>W+%_MavtU-%r}@_#Rg# zCGx}PkKw=T(<^$kkAL3ix!%&^9GBJCE5Y7=Ox0g6l`yUSduUt5!#Y#he@E6?c$Xc! zy6ar^le_2khTGp+R@z>)cfEYnGK-`8?%t9~z8rDv=&xF}EUPZz=W9-HnK*aO>E`Qc z*$L*ixOQK@T#$EbiA=Ja&87W?eVn`+^KKq-o;BllB=?H`LLc)^<7G_$+!y!Rs=i$O z&NbTN(+TD9TjzBj{B+zCIQ_)q1*R7wwxsVdm3=HG7pa1s!Q|oJ^>BsEmow^op!Y$Qp!&@)B`3dK&<~O%*@cwe=*({_rFj}npb04$Zx-Rep}%_uLj$U@O!ljetvXK?L1kNvBbFW z3+MdJ(oM``ViEmDGyODi&?K{gA%MPm_QT&!_{J1U7t=yQs{L<8^y3bZF zp7FN)z4#x{x}KNe?^Ur@~Jb-h0y3&qY}7FnBDu zpXG;@P37)1m9WQBYjs-XD>T}6 zu~l^g|CW9JcTf6VbDU_e8n*G@3%NrXDVx>>KFEZ`-$BDi zlhRi$`&^&8?#H3)rv(M7GolWh`;lMB@cxoj+oN3$uPfyr)cxYBcV1lhc9Cm$*ZJ+o z-M<^Ay*+>I{EPE;&4-t%_AOcMCi~%HNzm(_4%x?RUv8NuU)8Yd(Ure;la^hsihZ*2 zrTq1k?AD!Ak9GXj+bjRzSJ_&ZJ(Jasy7%UP3kx^&msz~EWcBt4g|N$03-v&=nv$1u zbl>%D2^W8R=Fj2qD|7Q6NEP0;n|}DwgPU!6seK~sH?I8a{KEOV%kNiBwr!^0v4!7- zpL9E#`>MYY`m4F@wRqL+jV3FWE%y2LHOBk>=RL{3N5Y=H^$XZ`K1+YCpZw1?8`IxJ zL~r@+c*XKtzsTnd>j|^`lC+?c8K8a*Xp#VV65na)y4FCbBjbdLH{L&7)?2TwVP9 z+}qvqh4EXs{`6QdOkVl&1^;=zz2|Zn)8!r{6lOKZZ}mI)wv37I%wB)1mrD*UpLP1z z#S(?0fHU3qF0)Gs)rt07>qI2KWY5;VqhIH9zv6oA?_D1ktvzsZ_c^=bUlmFwb9eBq zm)hfRKa20dv8UcE;%`jX%gnd?=Ii^s^+V-H{(Rkk8z;&Lo=?kB(@&c4RZ99&{t@@O z6JiyamaTKoaV4kkTJ_7S-#apC>ei(7h6hVN-TmPD%O_gR>2hZ4kCVrHO*gKXz3g(H zx|QvH9$k+&;?-|0m%p3)W?klp~=ecSH=4t|N3pyWBZ(==4b1F-Ke>dEAuk=>oWdJ=Z{FoY%jA|p1Z_GBlXg~ zLiHWS9=_^^qR=H6e$c5XlwN6=@A2xJ&vdR=te5%z=<~V4_u})iZ|J;;`6w{I(Rz~q zMZWn*MQ?U@$+f6|dbiFtGis;Y_oIeYZJYYOz46g+^aJJm`}g*Kv#*+H!}s@9?9aOE ziH~f3+u4GfmpSi$`25<29qLh>dgt~9?tNxfeW&%BSzM*nr~OI)jcgRpO}8y<{;{v_ zyXT^pGY)?}?UH3>CtUq_>t8 z$GG_ZlCqeFYfjkSKNQI ztP*rC%HK>enblW0!G7cV^w>R1D=!rLn;)^OE6RU)se##e{fX(X#WtV4U84WK&>_pJ zb7cpf`SPt)nq*2``@?)Bzp|MIQo+~xt|JeR`0tuZC&d9DYcW(4Hmh+9B7QNRXx=<2_O{Y0 zVD&QLTa7y|@aDK(ei*;@b#~#N==mGZt4@yzDw%2FzcSwUc>34nGv4qhTwPNxFQec7NRASH0DB zwpFH;gd&GoI8YSEs}M78eS1$$W6tppwVd{`uie%zGmVJwdC>WUv4t(+zog89zyAt%K9;?GB;~Qo|gmrs;nR1u?zgc z5asuz>cK?o-i;g9?>kufx!N+|&F^d5_ifdW_wY@BGpp~Jgz~kY`?Bq=KUwd8JfU`@ zseS3Py)&|8+~UHrtR63ZxudT?EB{Efp+{Vg-TN)(aoSO)vh(jIb?cszNv`2_zWk8; z(Kgd1Hy;0cvpDzfvz|jKSyoBY>I|1}T)(qXPgU&eru@~*4ws+3`R!!z`zs|vmt~<# z@~|!C%(_}KCtI0c!Gt0A=x&zz_VYIO&V6Zq?&HBmD{}^QyaF9>3DE zxpklAw*OwO-FtNNI@_acH-*=V7tHz({ny@ji=Fped??D}Op` zf13Y}((c>RKD{n5{Je-oar*Yh>E<^Qn%B+pQ81mmG280x1)I`Od$yOnytL?X#kKF7 zYn*EM{(q2pkUwG8xgVKUpIDAEZFHP{H1pf7%;j^v;!b!N#@nCT{Yc$H>a*P6_~^5m zhaWt6E1spd_v^Lj?%Ff^|2W)cn;EVieA)2*t$x3Gvn;P#IviVO>$|pd_s!|c4$m`@ zHT0ja5j`&`%c}EbAAzz>X;xo(7h`=>dtsloU9Qazj+*v##owzR?)vEV;{<5#&W8Q* znvaDRL3jGkKQ8Zae;)=)e>Ia`yTztj-r8CbQvKucqF=JxO*5@>q@TAw4tP4{!p#>( z&#Zq&73D>}UhBJKGibE-#%!_YvR|0_EEc@rJLe|#Y);4JE8i`GzD`}9%r8IdltQ(H zFDO`ZQfpqa*PYo{BlG|GzM|42voqL#e`2=N*zdmk@V--TuJ2pSzls6R~S#_o4nEU02S-%?V^&>YeIg(XtkbiH_q0J?;_a6x>mf!n$ zT6CUfasQ7!zu)aPf4zSHKZi;a<%1FC{4<{4NZFNXwcuUNMY(d5wA5(n8}?_d#g%V* z?)+BzwEK&~XVc%O9*X?lwbkBq?vWDE&;+zChOw|D%2YPSZXK)s`nwjv=NH}TtCxH$ zXJXMi@zEknVgK5*rq@My8RcKdu*6J!|8~#Y1+)168C&=kO1WpQmzd*czj2qEuew8e z!8Yr>(D@PPH_6IR*!EZv~Vfp&#=QkT3C+}Xi*v7`Ze&XiK z`tfFxv-}QNzdIMXaPo%r`;Ibh&|f$IZo#)xA0xj_wO)F5i?7`Re)f&|SyqQHmwcIC zsH^XO=7{y?*01;HSQek!d-G()(ZtpIb}~ViCGCCFe|~zZnpgR5693|}Nn8KjPwuz% zy7_ij^Xns}kG=PA*eN4q=l=V>I{P~L7|=$~GQ;*6^;3S z8#!K_e$-|A>c;lVbF}V%?$TbT@o$0uQ`IiTzcxpL-;Y_pudw+ufA94#{oik_P5!vGBIM7!8rJ&5p^x>yoHRJM zFrz(Pb7y$Xl`8Jz>f3$pb^Y9azxJM5@a2bxYhvT1eqSp8!Swr9H;4bJX%&?=tLjqX z|ET-=+MQRMonthiHu$pSxk{^7%ICZ8f2iJe`2Gc+CnX&df80Ky`DFQ<>9fxL$g;Ya zmj3cY`eMZ!vnThTP+s^mZ`aFZPs`_2y_v19A1J?ZYPsZ@^51W_$9HbN`z>2qBqW%cIwjpTmQ=W~kvKGuI;ziamTr_L8MZkX4^$8TEyqx4#2 zy6D;XIKJOq(}@e@Kb@tT>ny);&*9zI#@4v`<@EYP$rbkwI)YY+s$RwC(LA$r z?cXK$KR#x2K4-_nwxi24c#nDLpR3%m;d#H^QuB}UuQT5synV^)*VpqWua(?U{w8f= z_h#X-v^THo-+nvF`{Cw>_X;)!OO_dz`5rHxTf=SF{J-CL*Ae%9_y6TgpLOm?mQ}-X z&}C8H@;^VFV_183rhdtG-R*Za^_c#dEo1T1=F#k*?Z*<{ZG0}JR~BJubz$CevJCe4qY^VR&~;>y=L(<=<-eEswD^XY$Kf1kYCF>P8?_4a?JVFg)?HtcH~=g!U5 zz2E#SN$x0r?~(63i(Xdr%hh*pzHAmVuTs*#tNX3``Gs!2?EJfPZf*)nf3C1$_TN`E z$GKNc-?l-19oP9|`UR73na`Ues@ql{2il;%{>G7FyKZL&Dy*B zLw60Q_^Ew6JnGK%y~*Bh`kZZMxm))AD<#L4y*yzqkRS7Uo{8|CE$J0IgL5uwE;lfp z+j+IbVdfSoJ8$E!G0V<&%l3X_EKv zMMmr>NZfqh?)Q{AbL&3Gt4CjE+_$vmo2dQPb~oko8?NqqlXvEY`#-5~vQKPwgDP@H z{1y3{=ry7K)^E2Qy6UozVcpGA6WRCH)qZc;429N%)+wDGLZ2z$MjlNuU-?8bI=Naugx4%95^>9k2)w->DAMWkj%Q*Gv z%>y?i{C_W7W^Cqre8vLhSH@OzOdHZ|cJ=)^m3z(hxaHj8efzo#n~5qDH@bwqJ@xJ8*Xwpqvzfy%@35urv8j8Dro8=s&Bv}= z{neLy)^X=7j)Xp{UNCtX^S#5<(wjCHrFHIFXLrcZhP;(`AgPc{BC zb`kfgk1y;s5&zuGE?=|Z!{Zvy-7lGMos7G?uJvM;)gRBhA1D8D-~XW4R{O)lk6YeH zn8?oJ@O9TQ(0ki|V!3ti#jrCXzV5~^&i!egcVgNOt7K0d8BMk&%ZxwH>ihJ?bS>lk zr2D3yoBn;We|tf{#&PeBDRPe52If8D_uu_x{`=6DJw18j(z=TKzwcd_srhiw_IOZ& zk*RE1vFz_z!e@m~-OtWqCok!IpmO(cUGxs=!in!5@MP3X{`+}uZPVwEarU+=rnZ;(S1*3J^XF>4YZNXz*Hrvw>dQZ@3Cyppf1h|TBj&ifRiUYJrqzxu zag}@rg@62U$*}ri@l$!8|K7)bvnSgtecSqM;uq%9RQ|G;;|5W?z#pt{W9{tl{Hx5Q+QI0Q`ueK=Lt!Fy7^Kyw2`#H&kXL=teukX5CnC4r}7qfi+ zac0oLt{0ib_2Ximxjoqb`~CjOp{twS8He4wAFt;Kt`{2Z9+}{o!j12EEt&>~5ths%g+SO-% zg{OZ#U9C$Hb48g#PMg+yQB3VPprKa{loH~ z+y0hii{t%lzg{VN>mkKmUH7hdzV`gb@fMdh=*J)b_-%7tfPA%iYwhjhVb(w9er&DZ zS|5>NwS(iA!}g+|Hh){%PN{#GXkvV8`p0A2-ek?uXg)i4`a!nCmrCZS=F4oD{>j$+ zp}VvH+iULoA3nn8ca!ZkFGh z%6xg<_m`{A^~ebC5%h~ZbEv=Mk@yjd>g6X}3#Rq_nRdZRDP8?jkkwJ^Y?+#VrY^^`?aOd=0k9(dnJX~8~`l>a#sP|)r&ZA>jIls5g zK0ck5z5cA}^(isTPd9YemFCN={#5XI-u|nXi)Vd%{P*b>4S(CiZFYytEK2{Z(9ae9 z&-`ks+^NUjI}FN>zJ1{OF=U}^$)o0}EBAitFPL)cz`IXOAJ&|b()2(0_11^2>uc8* ztiHumqAM@&)R=@2tOUR$9I4oqpu%?qjwu%680naDH+8 z9ra&Fqwa4lQQ7vi+2Wty<5M$^_|7l6o?w%_ zEr)ISY`&DAp|Mc;>gn#(cwS7V9MU^+!$I^~%{JUgJWBn;hscFj&@2jZH z&WvjOCSUQO@#wW_$h_3N0TqqR@vc39}nD>=m;{Csi0U6rbDyPNanz&P^_?HdineB1XP zl`>Q`k*%C^&90_KrK7rJO=70ivBC^1<*zeezxeaYYqjY951BP{=HF^wd;iDd;$KH* zy!bw6cHD*Q#}@9r{>D>l|AiY#(tkJpez#jZ{?oda{jNED@(+ve=_W|We=A^lEx2vb z<}S`-3#!UbF)p<~U73Bgq=)zKrM32p{}qLO412S><~@f_#D)b&Jc^%J+?XEMZ=HFy z1y&OBe`e(=s&_l)=&tE74RKL&o|xXt@mQV;*)rbMf3t7i&#cK*)Nnf5#(Fsg(!&cd;FBRS#bG|M#J*`yR`_*Z3p< zkNr`M%eHxg+x@5Sblb+@cfUIr^n?=E3EG{ZL%%?6?=1GJ|6UhnMX5DpiEC+A4>YsS|LC(sq ze8w)m`1&sw-A~(P6_q^+Xqo@o+w7`YY3JUrA11sx_kHi-+?*e~&##uB+k33Nc)91r zvOo5}T6Hs1f3ddTxuw5x`h2t3!r!x>zW>42do}9ey4~-jx@rsAj@@Epm)S6>_HKCX z&1SO`{8N0TpSJ%w8u5tx*wh;1eHZ4PPw3gf#_xOF$ZhM%^p|rD!+!3sYPt5KzUIpe zQ&}mg`YHXc$*Im&Yd7`yK0Y3i=)cdQ|90K)x81cj9R4g;Z&{|S_n>0y-uuQrCeAnS zy??H6qVxUu(aTqQTw`qN4}ZLH{*AWh@6S)ut=K>4OHD0a^`+PLX2$te_ zI}V(`p!;*;M^hcXdGBYHZ}HzJcR#?t?u7o7=ci@bxUb#+b@A6^y9~ZU-dg3PUD-!9 zi>F3Bm3pjvFF#|e_WdXP$2RWTpxWDa_DlNq8)ufUVg4}vOY~Q>bBFisHCfnT^i-m1 z`;k4GVSOR%tfb0oj$5%Dktv+L?6P-#p!@so3O;kSv*Ihh!HuU=Z);{FF8f^=j&bM$d3u*iHn*Hkq z{X)LW83}qJ@zvZHZx&SiEvo;^lrHnre1~O}*zLzQk8MioI$l5bKG$^U`DbrSfh}I& zE-e3bYsZ7r6<+_^k8fLNyeuQ!s;TbVNq$*f@dC8cr+#RoCoJ47LC3K^|kk}?fd`uEz|Qjz3IEp z|NgtC^jd56`J3tQ%lXsaKQF&mUjOIgarxsyzaBL6KLVY03pzS0Z};166~EtZPo7(P ztuuGqO|@U&-^<7DF6-TXuS$EF|NMFX{{B2)Z)f*?=lP>etlW=4XQO|7eEc}8c#J^) zo{w&`?(KTLPWt}ecjd|bw%gkmA#QTt-JkB((}hx!{dAH|GxAu1fB8B%x@zg zU-u(%Oa6U3v%4jiZ)7f?oAkKXyl-k))XKUz(3!ULe_dIA>CgXX=KDQAAIc7k&fR*W z`u*PI&1cQJr-sK_hD9W{n(RO0Z72^qw(WX+y{(%6JQ@4nH_tzsSN+cObZ~gMIOy<= zS@rkIr-p`gmc6}In`BpcZ%^gtNAdrEg=cLJT9p?lp3v}E)2)tAU#Fd)CmX!nuNQRU zZ{7FZ_m8^E*G`#Mxc~3B?#KQ1`|5T|A1;os`FL~(=%DCH-g=#po70xwzq}39u&eob zI=&Bdo4`xcm~u0 ztK-|xuj}h&zu&K~kMai{)m9Zht@rDx-=I5-bNzGPUtZ?x-EVp=LV4@Yuh-+}-&z^5 z&u^~P(dG7kUz(iHagYD|Dm?ji?)J6u=0~e4zg%>G{M`P3<)3fc_xtWouHB@|Cud`^ z?N-+67k74kR=<|6TK3fb&qMx?i{<}nY<&;9*SgMsw^)DHhBnL;)0KHS&q3F=mb|>Ay6tw}?i-cQ=Pq_`=L^+6z39*H`~Ulr`)$qM{@x;c z`%h&0T+!pQ<#(KJM?5|Hui$3t^rN7w8UDp2?BDb0l=fro_@7=^e|MZ}PUbp(YGikesPsIx@p|L6Jt=bW>(nEz<=)bpy}Ki~R%&iXy*biYeK zD+=>YR$4q?IcNFGvJXFNzuinJ$CV`Z69XVzT5fy80cp0 zf4*-Y-@gB^?3aCM!?rG~v$fyvPVe)7zwdY6Dpiqwr@|VoR|Z$YZ}eG~nYLXInqKpE z>-8YrS3952^FD5y)wf6fwtcDCx6bo5&x}{DyRy6dz1!HUUAO4p zsXc+)7d`{+y1sHfYDM6`&-4HLe3g3TeZ`|9f8F8=x#tnQ*>jIp7v4R($Nuk^%Paj{ z*7j71f0chWGrQnkaWk)($MxhZzLxd-e?FUix$MCG6}v_2SLgT}*kNe zb=&)Wzn5861g1aQxkdB(iu&KT?_aVBj9>H3;`nRJ|EaPYyZQBcy!~2hx$Jd2)1sbV`L&{V)80*fH`^-oZu_Oq zomAU7>p}d#Pt#Xj*Tl4aoKOi>;6~zXPwAV&Z*wh_cUqOmap9UdnRPPc;b($@g@Ap-& zYA-&M8l}Vh`C#?NyTw00&(^4Jd+w7K7Zx7WJze(H| zsTSvbdqZsTo85oE-G2PO{(to^`-*$h_kCIVrRrL-;r*$vd%n*!NOU^2;RNH1`f0l@ zXDfU@ZS~aFLa+GU@l9rDWM_4M^*MHY*ZZJE~uU$^9zJv%dVWo@MXn#rfW9{QECSLF5Nx6QS)zFszX zzgYHXP2%t6wKL`B-}cRo-{yR8`nD$)d#=Y-ALUe^GvVIs`y1!)`*ccsr7h^tiye>q ztb>-FtYf^!J^ypg;hMZnx(2e(c5j^1pLw_T``wo}0#gEYq6^i#t>DDP`GYb>q2vX1siI*hgJI&FZJ&<&)l##e2zD%iqq}zwZ7o{(4I8=Ayly>i_vg8}2`Pzbh)s*|qP|m9I{- zP3Opcb~h_}yY>3ATefdce}A<)H-6g0UDl>o7u80_r-Y`kyYet?EFJ@9G&w&*=iY3+x){ePb72cMnycJ6=iNbc8--__kU?#<6_Esifr zJlA=0ZG~R$q1RpSML$?Qn|fVTQYg3N$wc>MKNSxz{C9NEC#yLBw8)xcBDK~t@;51b z68)7G5*Pi^ZcTcY?&D*<-laAB>Mu;OQ#o4FmCT;I>!?`tk$=D6&!4t2{ro)LvbytT zzV{A%a|v^5J6hOSdd%)v*`cCMwZ{Bg#9wz_FL>*C?BIXPx)0@>l5ch7G=Dwx%_TZ0 zUFmgFtjO!7Cr)*JJ(QghZP$Kd`U#~OVa{uWzuDfJz6Nxb=-T;y#kZ!XruXd9mMOf9IYk z`eDcXTj_UV^65JThZbim zQlD5|O^d8KKmQ;9m-mr#7Pj8|^g|Nnh|`SZ}`%)s-@&-49P3tm_kpF7V-cD~KV7v9G#%lWLEA7i<2?p__cK7IjMR1lcOiNPcGfmJ3(^7%+Tga z{Y?(boYM{#_WaXdKBvg*RsXd~&%Yo2y)pK3*`E~I4gV_S&zauXcXQp3lV)zm4w@bM zcm90_^S^WVrIeH(@6>VMx?AaWYi?5F-)lGAGULA)-fGL9mvviwYNhh&GyfcqS?1i> z@MW@2`#F^GB3uUD%dgYG41WM*Ghcz1=j$=3IxCpvaKdwNgm zi{`^Q6`5ZzYcj9Lm$PoeD=@sT%+ITpS!Z{!lapg zAOF^ETluK^-%$&{D<0ienz?tT?DOl>uso+ z%71V73;pmf#hE$QtLBsyUweM&*McIwBQqMd=qG1QI%r@f`~2`#J#9<-x88cuTlBvQ zy-IvyHK=gUq55t=KEn=QkE&}a?O^q-zqAMo*Gz zb}!R6w^^X^-}KW$+%mfgyBOicN< zjCo$ns?`N|ByB1RR&6c3|NGgO#^lRSt>*pty6^Wp@0;4my-zFZ&YSXIx02Zn+BtP> zP2}cBD;D>4UG}rqy}D`E?R_!&_lwWluAG1F<8k@jx3O`eAnzdZ}Z)<+osh$8>1Zhia(uH zKR&no-pqCUC*t_5UM#Tq@t`^R_1f)uMR{Rc-e2~&pZkjKiomSNdv$%&tg?7}CLgO^ zb*x8na$kJPi7yu=jZ!>HUR_xk`TU7bbIxy2hjpfL`mwy-Z>RnG^Q5BAKP_g9{`cs| zb2|1Uy|}P2GiLX*Eu5Ay7x(G!`;oNkz2MtuLVkIbC36|H|9y)11m1w;#bO`N=GPfl zeS0(WRe6eF&sOKyRi8HZNyQe&uRoZ`|qkaQFK=&s&r49+S?W zV|N>L{Lhu=%c{S>Tlp_c=66?NS6ubmts$Rhn`8!Ai9a%(^M3;S#Ly>yZhG9E`EBpZ zWwS5+?OHMUQl0DXOWSIHf9vHnzhm&!ggZO_oTZx2j0th)vn|d)srwKUzGdq-)60R` z52SK_e0ZpNS+RLx+P(et|F5w3MQQDH4u19GO?vP$AJ5v?H^g`L^HpX?zhb^V%iNS50^G-H@b^JYvx$vIj?@zzBo$zsA+bGlidj0G5`|WxaPww0H>(%Pz*#^H3 z}B!nziqXx#oJERcGq^*cF&noeY9ZT_cO-lmn6&W)GW39^fucB#dGgGd^>;t+)q;H^1EJ#**&-TR%my6aq;tWEBj8FzR}zLX41R) z&i@V<|MB^wpEY}n{`UzFHn+S!bn4sF2g`jixr<^XB=O;UN&J>^Y)oZtT*-Jj2;4|ya!W;P~bh_*czQ{lP3Oe_&HtkeI zM{cQnHgAf>WOaYPx7DxLZojr&|G4V0YfI`CA1^Qb8@xq7H|)WUur2z3=UY4zeS7-j z8nN5g!7*ED1a7#2dMk-wzyATZ2;6r*+BHQ==K88T>z{r+F7JQ8HeE*PSm@*LHEf?O z-Oo9kowD(2*TD3N z`ZS|$ZSUO~)fE@_mESE5x8h$`yR!JgzAxt&)>fKa+m~`P<*Lo}Gwt8*mfg<1T)1}a zH^Z19{JB+je({x$CnSEHtQC3Tf5_4=aMknO@2-5P2rz%TtL(1t`KR*w$%lp(m+!4?H*ZGI-Z}IC-UFFVJO8*x9E&N;b@tU=} z-|c#N&+^LS6TZcA`D+z#O*ecuuln82EBk_%`~7wK{mHy9-lqTCQwdkKv(4X9=WMmB z{dML0`G+#QrV)sSu3tF|H<{eu;1geS&-BmAqtP+H!?vYL-oEbRzP9sh??1Dc_KD^f z*0=mq`C|AaE^+<7Us<(x*Y0qasC6~Fk&6=0@U6aa)zqNi-?a2#q zRWFxb+1InuZN5x_y}_~6#p{C)f7AW-@rn`NW`SpvQJPhh*o`+k#1`lCJzg*RohkXx z`lJ}=SFcJ-OJ6$fooiWzO52e_y)4f#Oe%sjPeD~AmJ&$W)BBi@dr%*^I0ALCLF$hBsH0S+Dw!u|y!1FV5nQig?TUBL z>{HQ|G?w+W#M>;MxI{I1nX;xk-sClDOUjuNm8UBbmtEeNd>nMCn@qt0#xyI_j@K>G zc{^2MCGg+(yUX9pEuUXk^=89izH4k*7v9|59IX5Q+wJ`RpP!#!|GzK){=UL8ch0}Q0Can~Td$O8^0A&y&{gDr z^X}Jv@15*#XZh;Yt7#watW-Ta(^!4ozF)7tRK`6izmYQ8_tBQie%+w6PiyzI75v%v z|KIP&e?FfFU2eDZ{=}y|vQ{S7;_GX#m-5cCtF5xKpKXxn^y`1t>a}8^6DX6<+kQ8> zywVXg_HMN-zWA)^%lm0oldhPgSxqXsVsKgU_`-eOz42SyOKp;m^=!GP{X4tl#RbJ* zUtUhm+PBJf&Fjp|%a%q3JbigiYxNo->6{IYQU6!jUilGU@vt@IKdWg|>GfFiuh#?L zE_~-LJ0aQT|FK!w>m>J9fA1@MdrSB6&S39HGtNE#ab~9R>+7Z#%Qp94ejc^8_1`v7 zi=;O0_R8SpTh_g84xjy^{`hnA`zIMK{m##`4X(Y^6*%EH>`M;}+l#oVu48H4cRmtU{f zFW-3mc%Q7azwOs6>c8?lCaHK%T5>IMnX;!ZIF;OqZvHq!qW=G;(|X;NpP%Wzj+~_8 zxr*z%T*d3P+h4sGJtncKM|szyE^WQXmXlRX*_ZCze!tFI_PTZXyE%7%EKIRtX5;br zZdJM`#xu&sSk`mrqYuYtob|W)*z&hT#WN_==JOfj!jr1gm;B~f7`;8O@X18?V`9-c z8+)GnOu8adbNs`z+4+8tJ$a-|G{WL*zoy!Huk9-QR`vCjXzlNBU*}Dq6v7Hh@s9;w zBnC`UnR;@G=j2BhocVjx=hvG3t>63gn)lzn^1G$iQ*F{GEqOM>INcA_fLP`~Uk-HD z>6aH5lOxXutyaGNQO;{ph^(=!=Oh(REq@G*v|NZ*-(`kM4%M+JOQo0N} zp7Rl?v8L$U=CZ%;?U4g-ncLMc;D$NGgZ&ro|%0hH%x7x*{3p9zVh7TetYoQu6GI! z^BU&f+VX4v+8vL&3cp-*KMtCcm}^xU)mE(OnbnQ#_CNRP|NoV+tty#Q{cfjW?XNFW zK8j3>ulqUWr2*UQnSClN6=A_{EbFOdZ!}kX{T?IGxu+G6d(G`Wnj6hM%x`bg#xE}i zI#zy5{{1@1vrAQ0>LUC7Q*_9(%j;ry-^kf~HtGN0@BPmFwkB2I-t6po7BuOK*i0mk z?>sx(Twkv8$;2JsZe>4SHao9tXYuoY=Zjy=-h9^V_L9fHuSMtYFwp1QxkmhQ9pGeu=(0#ejI{dUP)|EQ<>T#@Z}%c5((Ty*EI zmHS(~ZpWjpEAj0gZ>V@SAqQ;q)|q_YFFve;eIF3+Oz<@UOE%!(+GFfs#q| zsbURJEoS5>TmCG?N_+jDB2X1!Sn%M$jjGpclb22ni#i2L3$KyAQX^6Rw%7b#$L+k` zx^6uZf|r;1u6|Ye_SRPK$Lrtje!mZNxemCh_%z3B(k&}wTjrPFt5nb1_w(6~XS1@C zKv(7F-`le){`S7w-=L|`$A`G}d+zP6*55mGipo@!@IC+L=H}!lCngr&Or373dA<>p z<|ZLW0RPN$k?C`%8qNKFuX?@b`qV#L|NZ@aTyyyxq1*ZUYuD_0wQA#?qSLxdEvKq% zElslm<@OM{G^3=N zVWDC6wKb}{ru!{iw@xqB%IC6=`=n1P$ci178E0KtVe$1!aPql1mbym1Mst<>ER=jV zM{m!&2)dDP<~m532rnCDKzCP9dC4PbwB)FftkE1_^SdVBZs+fpuqa6Q^6Khp*JawC zTKq^!DeL#W>i2sqUMy^XwCnY{ZqQ^u=<=JS%X!z=#pdk)`>pWh(&@*hMdwML*4-Y{ z?HfJm$~WYq;P!XW-Lx;4&zF0Athf8-=5%-O>Gw|*fv!@yQFvSy)L(jLHED_%cRL;@fz}5+ogTmM=zZr&SIkhX+P=kDw&d+CQ@1`D zNzgSnYc?F>@_uTo;+cE?KjZtlukD~!622W_snQ2NW|yQ*I@4e1P~hbfIO%}hQeW+E z4z5cAJ{QF59C@#8St)jDhE<=3{FErerluE8Au%_crn~9>kr3<=(dG~>TsY;7!403j zW0v}-etTWCHu*fKcz)gfvk!0DeBW9nx8whv=lg1Ze|yWoz@WgX?l-4H)qC0zfBU~v z>gQP&r`3EsDh?_s#BC%QX1>0@{`vl^v(0k5*6;sk<(Bn2_tBBgjiAdDw`PT!n3(jO zkYbo}J{NptljJNuhn=;*-)_Hn@1ERpzqwuW=FJm~PCwMb3BJ0xOH@1Q&ySCWSyxsF zMsqiOx&XTI7Ia7Il-m=P-NBciaf|Eqys+x+?KLcacPC;`Md6-rx3Yiklx0{2zKPbO zeHn8=UOT^hpZUFt;;Xv-lVo9IQ-a8;W+7z7DIK zel9$|Ry6zCn$FYH^{=PgUGp;M_BP+kj6bF$?7!SAZJzY~-QA7J$NMabpZWaxc01oR zvi#qlpFb_+#ryZ~PkU|m>4fsel9!hvwqyi? z77M(3^(t$d8N*ia-MUMhFEeT^U-NQJ^me^`D`sY9)9CUqFD`;=&zig9aTSi28CO_< z15kDrpTkccKE7jDSBEd&yxDlyu3cHTN{m3cT7Ul^qqv%nuD8Ytd=UVmK{mQs<{rdG9Hij(l6@TDxwu`)+nVZ}D_;|m&V07-y zxmLcuzCU^1@BJPJsms)2 z#m4L`S~_8O$-5KpE=2AqNUV#?I5)@g;{j%V5i@QEW$?Xb5IvEXZ*EL>-?DxC@vYg{ zx#liiw@y#ZZ;r%yyWcq_B_&7R+}zAPm%U-)LeM?G;7IBJ_wV1Hmuq5oZ~L&U`1oai zd)e67*pELR_lw(dF(`xYVg#GaS6f?K`02^X8+)tEK{uyYRabY*X)b?>9K14m@%v=t zYd##jJ1_W2tkwUw8;{F%pF4N1;@Qmfq(47C{h)UC#ny`!E?oFxB7=k*BIRjhUp@)CINHj}D(PsK=*1g1 zBEDEK@F>I0-MDG(miYR=rhT&3V)JW0dCJ&UnXs|5cgwx5Pw`DZ+{U}H=&6@4`+_8R zB075N9r$v}PrFNY?cTk3{d)aV+xA|&azzA`XF#{AwQve2U0D(6+Rt*p0DMa|D9?&$ zXIr`V$#jBx2z7rx9$$3)XE127xy{ET!W%0-K8n~?l4)XYE^aHta2R|KB{(40h|Ka^ zwr`&u=q5Q(N6lxh)z%k<3=(Q^A3jR4eST|ecHxT)3tzl=(ZMaQCt`akUdpzrThoJ>jC>E@KoaG z<*Pnc16KHEJ1 z+5F9$O+htlTU%TGpS$Itg2Bq#`ti=^^FIGGZQz3E9+BtY@7MQlPCtL_=jZ3|%VyL+ zdOp9tZ?1Luv-3IK>sGGR1YKbb>eLzd{FZ-wtoQW({8Ljj@9kv^V1$QT67Tb{C{PaE zw(Z!;;N_p*=VoShp11#R6Ib{1Y2sV`C_aZ$@O_9cFO)E>dhB=kT|}gAll-AZ-#_@UR70z%z9jGXn#-z_Bus zWoYw)2NUSJYv-k~Pz7a$hJ}}4RRFTJJGQ^vvSo`)bab@M&nJ^v{n-u#{QYp4e`D(D zX@6F}WcctO;@HCc%PZHf@AsUnc65eeGS@twhJ{iR5*_h%KUM3~Ok^4Ufv*Ri&{sX1 zj{)TF59J7NEPcrUp9U^lLxde1MNcdAgB z;U5DF10w?zFfxPLrEClgj8L{Q69WSiBQpaF0|Udgiwq3RQ1ML-3=C{gHWLE_11}>J zgEj*L!@Y|P41A1C3}Orn3|yBO7z7zv7&t){`XvSiA*gzgeWFk{$Xqcf+kt_BK^&^y zf=dhxGEns(b2OlAW(EcZTPPdko**b2qz2?W4h9Hxwu&jq z&n=G0$xJHA&&^FN$%rY)OfHTo&dE&4%uA0i&&*57FV`!{Ok-ehE=o--Nlj5G&n(GM z2+2rQaQE~LVBlb2U})81U{JGUU?{X@U=Z?RU{DQZU}#KWV0g2ffkEgb14FGA1H(c- s1_o~y28M+^3=G2D3=A>c3=G-s3=C?D3=Fr}85kNYWXc#A7#LwR09f-sB>(^b diff --git a/lib/hcrypto/libtommath/poster.out b/lib/hcrypto/libtommath/poster.out deleted file mode 100644 index e69de29bb..000000000 diff --git a/lib/hcrypto/libtommath/poster.pdf b/lib/hcrypto/libtommath/poster.pdf deleted file mode 100644 index f3768d76904d62226e238a46fb69406e0c481a6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37821 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 == MP_NEG) { + return MP_VAL; + } + if (mp_cmp_d(n, 0uL) != MP_GT) { + return MP_VAL; + } + return mp_kronecker(a, n, c); +} +#endif +#ifdef BN_MP_PRIME_RANDOM_EX_C +mp_err mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat) +{ + return s_mp_prime_random_ex(a, t, size, flags, cb, dat); +} +#endif +#ifdef BN_MP_RAND_DIGIT_C +mp_err mp_rand_digit(mp_digit *r) +{ + mp_err err = s_mp_rand_source(r, sizeof(mp_digit)); + *r &= MP_MASK; + return err; +} +#endif +#ifdef BN_FAST_MP_INVMOD_C +mp_err fast_mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) +{ + return s_mp_invmod_fast(a, b, c); +} +#endif +#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C +mp_err fast_mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho) +{ + return s_mp_montgomery_reduce_fast(x, n, rho); +} +#endif +#ifdef BN_FAST_S_MP_MUL_DIGS_C +mp_err fast_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + return s_mp_mul_digs_fast(a, b, c, digs); +} +#endif +#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C +mp_err fast_s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + return s_mp_mul_high_digs_fast(a, b, c, digs); +} +#endif +#ifdef BN_FAST_S_MP_SQR_C +mp_err fast_s_mp_sqr(const mp_int *a, mp_int *b) +{ + return s_mp_sqr_fast(a, b); +} +#endif +#ifdef BN_MP_BALANCE_MUL_C +mp_err mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + return s_mp_balance_mul(a, b, c); +} +#endif +#ifdef BN_MP_EXPTMOD_FAST_C +mp_err mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) +{ + return s_mp_exptmod_fast(G, X, P, Y, redmode); +} +#endif +#ifdef BN_MP_INVMOD_SLOW_C +mp_err mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) +{ + return s_mp_invmod_slow(a, b, c); +} +#endif +#ifdef BN_MP_KARATSUBA_MUL_C +mp_err mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + return s_mp_karatsuba_mul(a, b, c); +} +#endif +#ifdef BN_MP_KARATSUBA_SQR_C +mp_err mp_karatsuba_sqr(const mp_int *a, mp_int *b) +{ + return s_mp_karatsuba_sqr(a, b); +} +#endif +#ifdef BN_MP_TOOM_MUL_C +mp_err mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + return s_mp_toom_mul(a, b, c); +} +#endif +#ifdef BN_MP_TOOM_SQR_C +mp_err mp_toom_sqr(const mp_int *a, mp_int *b) +{ + return s_mp_toom_sqr(a, b); +} +#endif +#ifdef S_MP_REVERSE_C +void bn_reverse(unsigned char *s, int len) +{ + if (len > 0) { + s_mp_reverse(s, (size_t)len); + } +} +#endif +#ifdef BN_MP_TC_AND_C +mp_err mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) +{ + return mp_and(a, b, c); +} +#endif +#ifdef BN_MP_TC_OR_C +mp_err mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c) +{ + return mp_or(a, b, c); +} +#endif +#ifdef BN_MP_TC_XOR_C +mp_err mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c) +{ + return mp_xor(a, b, c); +} +#endif +#ifdef BN_MP_TC_DIV_2D_C +mp_err mp_tc_div_2d(const mp_int *a, int b, mp_int *c) +{ + return mp_signed_rsh(a, b, c); +} +#endif +#ifdef BN_MP_INIT_SET_INT_C +mp_err mp_init_set_int(mp_int *a, unsigned long b) +{ + return mp_init_u32(a, (uint32_t)b); +} +#endif +#ifdef BN_MP_SET_INT_C +mp_err mp_set_int(mp_int *a, unsigned long b) +{ + mp_set_u32(a, (uint32_t)b); + return MP_OKAY; +} +#endif +#ifdef BN_MP_SET_LONG_C +mp_err mp_set_long(mp_int *a, unsigned long b) +{ + mp_set_u64(a, b); + return MP_OKAY; +} +#endif +#ifdef BN_MP_SET_LONG_LONG_C +mp_err mp_set_long_long(mp_int *a, unsigned long long b) +{ + mp_set_u64(a, b); + return MP_OKAY; +} +#endif +#ifdef BN_MP_GET_INT_C +unsigned long mp_get_int(const mp_int *a) +{ + return (unsigned long)mp_get_mag_u32(a); +} +#endif +#ifdef BN_MP_GET_LONG_C +unsigned long mp_get_long(const mp_int *a) +{ + return (unsigned long)mp_get_mag_ul(a); +} +#endif +#ifdef BN_MP_GET_LONG_LONG_C +unsigned long long mp_get_long_long(const mp_int *a) +{ + return mp_get_mag_ull(a); +} +#endif +#ifdef BN_MP_PRIME_IS_DIVISIBLE_C +mp_err mp_prime_is_divisible(const mp_int *a, mp_bool *result) +{ + return s_mp_prime_is_divisible(a, result); +} +#endif +#ifdef BN_MP_EXPT_D_EX_C +mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) +{ + (void)fast; + if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + return MP_VAL; + } + return mp_expt_u32(a, (uint32_t)b, c); +} +#endif +#ifdef BN_MP_EXPT_D_C +mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c) +{ + if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + return MP_VAL; + } + return mp_expt_u32(a, (uint32_t)b, c); +} +#endif +#ifdef BN_MP_N_ROOT_EX_C +mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) +{ + (void)fast; + if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + return MP_VAL; + } + return mp_root_u32(a, (uint32_t)b, c); +} +#endif +#ifdef BN_MP_N_ROOT_C +mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c) +{ + if (b > MP_MIN(MP_DIGIT_MAX, UINT32_MAX)) { + return MP_VAL; + } + return mp_root_u32(a, (uint32_t)b, c); +} +#endif +#ifdef BN_MP_UNSIGNED_BIN_SIZE_C +int mp_unsigned_bin_size(const mp_int *a) +{ + return (int)mp_ubin_size(a); +} +#endif +#ifdef BN_MP_READ_UNSIGNED_BIN_C +mp_err mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c) +{ + return mp_from_ubin(a, b, (size_t) c); +} +#endif +#ifdef BN_MP_TO_UNSIGNED_BIN_C +mp_err mp_to_unsigned_bin(const mp_int *a, unsigned char *b) +{ + return mp_to_ubin(a, b, SIZE_MAX, NULL); +} +#endif +#ifdef BN_MP_TO_UNSIGNED_BIN_N_C +mp_err mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen) +{ + size_t n = mp_ubin_size(a); + if (*outlen < (unsigned long)n) { + return MP_VAL; + } + *outlen = (unsigned long)n; + return mp_to_ubin(a, b, n, NULL); +} +#endif +#ifdef BN_MP_SIGNED_BIN_SIZE_C +int mp_signed_bin_size(const mp_int *a) +{ + return (int)mp_sbin_size(a); +} +#endif +#ifdef BN_MP_READ_SIGNED_BIN_C +mp_err mp_read_signed_bin(mp_int *a, const unsigned char *b, int c) +{ + return mp_from_sbin(a, b, (size_t) c); +} +#endif +#ifdef BN_MP_TO_SIGNED_BIN_C +mp_err mp_to_signed_bin(const mp_int *a, unsigned char *b) +{ + return mp_to_sbin(a, b, SIZE_MAX, NULL); +} +#endif +#ifdef BN_MP_TO_SIGNED_BIN_N_C +mp_err mp_to_signed_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen) +{ + size_t n = mp_sbin_size(a); + if (*outlen < (unsigned long)n) { + return MP_VAL; + } + *outlen = (unsigned long)n; + return mp_to_sbin(a, b, n, NULL); +} +#endif +#ifdef BN_MP_TORADIX_N_C +mp_err mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) +{ + if (maxlen < 0) { + return MP_VAL; + } + return mp_to_radix(a, str, (size_t)maxlen, NULL, radix); +} +#endif +#ifdef BN_MP_TORADIX_C +mp_err mp_toradix(const mp_int *a, char *str, int radix) +{ + return mp_to_radix(a, str, SIZE_MAX, NULL, radix); +} +#endif +#ifdef BN_MP_IMPORT_C +mp_err mp_import(mp_int *rop, size_t count, int order, size_t size, int endian, size_t nails, + const void *op) +{ + return mp_unpack(rop, count, order, size, endian, nails, op); +} +#endif +#ifdef BN_MP_EXPORT_C +mp_err mp_export(void *rop, size_t *countp, int order, size_t size, + int endian, size_t nails, const mp_int *op) +{ + return mp_pack(rop, SIZE_MAX, countp, order, size, endian, nails, op); +} +#endif +#endif + +/* End: bn_deprecated.c */ + +/* Start: bn_mp_2expt.c */ +#include "tommath_private.h" +#ifdef BN_MP_2EXPT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes a = 2**b + * + * Simple algorithm which zeroes the int, grows it then just sets one bit + * as required. + */ +mp_err mp_2expt(mp_int *a, int b) +{ + mp_err err; + + /* zero a as per default */ + mp_zero(a); + + /* grow a to accomodate the single bit */ + if ((err = mp_grow(a, (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) { + return err; + } + + /* set the used count of where the bit will go */ + a->used = (b / MP_DIGIT_BIT) + 1; + + /* put the single bit in its place */ + a->dp[b / MP_DIGIT_BIT] = (mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT); + + return MP_OKAY; +} +#endif + +/* End: bn_mp_2expt.c */ + +/* Start: bn_mp_abs.c */ +#include "tommath_private.h" +#ifdef BN_MP_ABS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = |a| + * + * Simple function copies the input and fixes the sign to positive + */ +mp_err mp_abs(const mp_int *a, mp_int *b) +{ + mp_err err; + + /* copy a to b */ + if (a != b) { + if ((err = mp_copy(a, b)) != MP_OKAY) { + return err; + } + } + + /* force the sign of b to positive */ + b->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif + +/* End: bn_mp_abs.c */ + +/* Start: bn_mp_add.c */ +#include "tommath_private.h" +#ifdef BN_MP_ADD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* high level addition (handles signs) */ +mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_sign sa, sb; + mp_err err; + + /* 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; + err = 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; + err = s_mp_sub(b, a, c); + } else { + c->sign = sa; + err = s_mp_sub(a, b, c); + } + } + return err; +} + +#endif + +/* End: bn_mp_add.c */ + +/* Start: bn_mp_add_d.c */ +#include "tommath_private.h" +#ifdef BN_MP_ADD_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single digit addition */ +mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c) +{ + mp_err err; + int ix, oldused; + mp_digit *tmpa, *tmpc; + + /* grow c as required */ + if (c->alloc < (a->used + 1)) { + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + } + + /* if a is negative and |a| >= b, call c = |a| - b */ + if ((a->sign == MP_NEG) && ((a->used > 1) || (a->dp[0] >= b))) { + mp_int a_ = *a; + /* temporarily fix sign of a */ + a_.sign = MP_ZPOS; + + /* c = |a| - b */ + err = mp_sub_d(&a_, b, c); + + /* fix sign */ + c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return err; + } + + /* old number of used digits in c */ + oldused = c->used; + + /* source alias */ + tmpa = a->dp; + + /* destination alias */ + tmpc = c->dp; + + /* if a is positive */ + if (a->sign == MP_ZPOS) { + /* add digits, mu is carry */ + mp_digit mu = b; + for (ix = 0; ix < a->used; ix++) { + *tmpc = *tmpa++ + mu; + mu = *tmpc >> MP_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; + } + + /* sign always positive */ + c->sign = MP_ZPOS; + + /* now zero to oldused */ + MP_ZERO_DIGITS(tmpc, oldused - ix); + mp_clamp(c); + + return MP_OKAY; +} + +#endif + +/* End: bn_mp_add_d.c */ + +/* Start: bn_mp_addmod.c */ +#include "tommath_private.h" +#ifdef BN_MP_ADDMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* d = a + b (mod c) */ +mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) +{ + mp_err err; + mp_int t; + + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } + + if ((err = mp_add(a, b, &t)) != MP_OKAY) { + goto LBL_ERR; + } + err = mp_mod(&t, c, d); + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif + +/* End: bn_mp_addmod.c */ + +/* Start: bn_mp_and.c */ +#include "tommath_private.h" +#ifdef BN_MP_AND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* two complement and */ +mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c) +{ + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + mp_sign csign = ((a->sign == MP_NEG) && (b->sign == MP_NEG)) ? MP_NEG : MP_ZPOS; + + if (c->alloc < used) { + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + } + + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (a->sign == MP_NEG) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (b->sign == MP_NEG) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x & y; + + /* convert to to sign-magnitude if negative */ + if (csign == MP_NEG) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = csign; + mp_clamp(c); + return MP_OKAY; +} +#endif + +/* End: bn_mp_and.c */ + +/* Start: bn_mp_clamp.c */ +#include "tommath_private.h" +#ifdef BN_MP_CLAMP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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] == 0u)) { + --(a->used); + } + + /* reset the sign flag if used == 0 */ + if (a->used == 0) { + a->sign = MP_ZPOS; + } +} +#endif + +/* End: bn_mp_clamp.c */ + +/* Start: bn_mp_clear.c */ +#include "tommath_private.h" +#ifdef BN_MP_CLEAR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* clear one (frees) */ +void mp_clear(mp_int *a) +{ + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* free ram */ + MP_FREE_DIGITS(a->dp, a->alloc); + + /* reset members to make debugging easier */ + a->dp = NULL; + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } +} +#endif + +/* End: bn_mp_clear.c */ + +/* Start: bn_mp_clear_multi.c */ +#include "tommath_private.h" +#ifdef BN_MP_CLEAR_MULTI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#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 + +/* End: bn_mp_clear_multi.c */ + +/* Start: bn_mp_cmp.c */ +#include "tommath_private.h" +#ifdef BN_MP_CMP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* compare two ints (signed)*/ +mp_ord mp_cmp(const mp_int *a, const 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 + +/* End: bn_mp_cmp.c */ + +/* Start: bn_mp_cmp_d.c */ +#include "tommath_private.h" +#ifdef BN_MP_CMP_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* compare a digit */ +mp_ord mp_cmp_d(const 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 + +/* End: bn_mp_cmp_d.c */ + +/* Start: bn_mp_cmp_mag.c */ +#include "tommath_private.h" +#ifdef BN_MP_CMP_MAG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* compare maginitude of two ints (unsigned) */ +mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b) +{ + int n; + const 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 + +/* End: bn_mp_cmp_mag.c */ + +/* Start: bn_mp_cnt_lsb.c */ +#include "tommath_private.h" +#ifdef BN_MP_CNT_LSB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +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(const mp_int *a) +{ + int x; + mp_digit q, qq; + + /* easy out */ + if (MP_IS_ZERO(a)) { + return 0; + } + + /* scan lower digits until non-zero */ + for (x = 0; (x < a->used) && (a->dp[x] == 0u); x++) {} + q = a->dp[x]; + x *= MP_DIGIT_BIT; + + /* now scan this digit until a 1 is found */ + if ((q & 1u) == 0u) { + do { + qq = q & 15u; + x += lnz[qq]; + q >>= 4; + } while (qq == 0u); + } + return x; +} + +#endif + +/* End: bn_mp_cnt_lsb.c */ + +/* Start: bn_mp_complement.c */ +#include "tommath_private.h" +#ifdef BN_MP_COMPLEMENT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = ~a */ +mp_err mp_complement(const mp_int *a, mp_int *b) +{ + mp_err err = mp_neg(a, b); + return (err == MP_OKAY) ? mp_sub_d(b, 1uL, b) : err; +} +#endif + +/* End: bn_mp_complement.c */ + +/* Start: bn_mp_copy.c */ +#include "tommath_private.h" +#ifdef BN_MP_COPY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* copy, b = a */ +mp_err mp_copy(const mp_int *a, mp_int *b) +{ + int n; + mp_digit *tmpa, *tmpb; + mp_err err; + + /* if dst == src do nothing */ + if (a == b) { + return MP_OKAY; + } + + /* grow dest */ + if (b->alloc < a->used) { + if ((err = mp_grow(b, a->used)) != MP_OKAY) { + return err; + } + } + + /* zero b and copy the parameters over */ + /* 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 */ + MP_ZERO_DIGITS(tmpb, b->used - n); + + /* copy used count and sign */ + b->used = a->used; + b->sign = a->sign; + return MP_OKAY; +} +#endif + +/* End: bn_mp_copy.c */ + +/* Start: bn_mp_count_bits.c */ +#include "tommath_private.h" +#ifdef BN_MP_COUNT_BITS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* returns the number of bits in an int */ +int mp_count_bits(const mp_int *a) +{ + int r; + mp_digit q; + + /* shortcut */ + if (MP_IS_ZERO(a)) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * MP_DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > 0u) { + ++r; + q >>= 1u; + } + return r; +} +#endif + +/* End: bn_mp_count_bits.c */ + +/* Start: bn_mp_decr.c */ +#include "tommath_private.h" +#ifdef BN_MP_DECR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Decrement "a" by one like "a--". Changes input! */ +mp_err mp_decr(mp_int *a) +{ + if (MP_IS_ZERO(a)) { + mp_set(a,1uL); + a->sign = MP_NEG; + return MP_OKAY; + } else if (a->sign == MP_NEG) { + mp_err err; + a->sign = MP_ZPOS; + if ((err = mp_incr(a)) != MP_OKAY) { + return err; + } + /* There is no -0 in LTM */ + if (!MP_IS_ZERO(a)) { + a->sign = MP_NEG; + } + return MP_OKAY; + } else if (a->dp[0] > 1uL) { + a->dp[0]--; + if (a->dp[0] == 0u) { + mp_zero(a); + } + return MP_OKAY; + } else { + return mp_sub_d(a, 1uL,a); + } +} +#endif + +/* End: bn_mp_decr.c */ + +/* Start: bn_mp_div.c */ +#include "tommath_private.h" +#ifdef BN_MP_DIV_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef BN_MP_DIV_SMALL + +/* slower bit-bang division... also smaller */ +mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) +{ + mp_int ta, tb, tq, q; + int n, n2; + mp_err err; + + /* is divisor zero ? */ + if (MP_IS_ZERO(b)) { + return MP_VAL; + } + + /* if a < b then q=0, r = a */ + if (mp_cmp_mag(a, b) == MP_LT) { + if (d != NULL) { + err = mp_copy(a, d); + } else { + err = MP_OKAY; + } + if (c != NULL) { + mp_zero(c); + } + return err; + } + + /* init our temps */ + if ((err = mp_init_multi(&ta, &tb, &tq, &q, NULL)) != MP_OKAY) { + return err; + } + + + mp_set(&tq, 1uL); + n = mp_count_bits(a) - mp_count_bits(b); + if ((err = mp_abs(a, &ta)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_abs(b, &tb)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul_2d(&tq, n, &tq)) != MP_OKAY) goto LBL_ERR; + + while (n-- >= 0) { + if (mp_cmp(&tb, &ta) != MP_GT) { + if ((err = mp_sub(&ta, &tb, &ta)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&q, &tq, &q)) != MP_OKAY) goto LBL_ERR; + } + if ((err = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) goto LBL_ERR; + if ((err = 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_IS_ZERO(c) ? MP_ZPOS : n2; + } + if (d != NULL) { + mp_exch(d, &ta); + d->sign = MP_IS_ZERO(d) ? MP_ZPOS : n; + } +LBL_ERR: + mp_clear_multi(&ta, &tb, &tq, &q, NULL); + return err; +} + +#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. +*/ +mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) +{ + mp_int q, x, y, t1, t2; + int n, t, i, norm; + mp_sign neg; + mp_err err; + + /* is divisor zero ? */ + if (MP_IS_ZERO(b)) { + return MP_VAL; + } + + /* if a < b then q=0, r = a */ + if (mp_cmp_mag(a, b) == MP_LT) { + if (d != NULL) { + err = mp_copy(a, d); + } else { + err = MP_OKAY; + } + if (c != NULL) { + mp_zero(c); + } + return err; + } + + if ((err = mp_init_size(&q, a->used + 2)) != MP_OKAY) { + return err; + } + q.used = a->used + 2; + + if ((err = mp_init(&t1)) != MP_OKAY) goto LBL_Q; + + if ((err = mp_init(&t2)) != MP_OKAY) goto LBL_T1; + + if ((err = mp_init_copy(&x, a)) != MP_OKAY) goto LBL_T2; + + if ((err = 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**MP_DIGIT_BIT] */ + norm = mp_count_bits(&y) % MP_DIGIT_BIT; + if (norm < (MP_DIGIT_BIT - 1)) { + norm = (MP_DIGIT_BIT - 1) - norm; + if ((err = mp_mul_2d(&x, norm, &x)) != MP_OKAY) goto LBL_Y; + if ((err = 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} } */ + /* y = y*b**{n-t} */ + if ((err = mp_lshd(&y, n - t)) != MP_OKAY) goto LBL_Y; + + while (mp_cmp(&x, &y) != MP_LT) { + ++(q.dp[n - t]); + if ((err = 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 << (mp_digit)MP_DIGIT_BIT) - (mp_digit)1; + } else { + mp_word tmp; + tmp = (mp_word)x.dp[i] << (mp_word)MP_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] + 1uL) & (mp_digit)MP_MASK; + do { + q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & (mp_digit)MP_MASK; + + /* find left hand */ + mp_zero(&t1); + t1.dp[0] = ((t - 1) < 0) ? 0u : y.dp[t - 1]; + t1.dp[1] = y.dp[t]; + t1.used = 2; + if ((err = mp_mul_d(&t1, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y; + + /* find right hand */ + t2.dp[0] = ((i - 2) < 0) ? 0u : x.dp[i - 2]; + t2.dp[1] = x.dp[i - 1]; /* i >= 1 always holds */ + 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 ((err = mp_mul_d(&y, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y; + + if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y; + + if ((err = 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 ((err = mp_copy(&y, &t1)) != MP_OKAY) goto LBL_Y; + if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y; + if ((err = 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) { + if ((err = mp_div_2d(&x, norm, &x, NULL)) != MP_OKAY) goto LBL_Y; + mp_exch(&x, d); + } + + err = 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 err; +} + +#endif + +#endif + +/* End: bn_mp_div.c */ + +/* Start: bn_mp_div_2.c */ +#include "tommath_private.h" +#ifdef BN_MP_DIV_2_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = a/2 */ +mp_err mp_div_2(const mp_int *a, mp_int *b) +{ + int x, oldused; + mp_digit r, rr, *tmpa, *tmpb; + mp_err err; + + /* copy */ + if (b->alloc < a->used) { + if ((err = mp_grow(b, a->used)) != MP_OKAY) { + return err; + } + } + + oldused = b->used; + b->used = a->used; + + /* 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 & 1u; + + /* shift the current digit, add in carry and store */ + *tmpb-- = (*tmpa-- >> 1) | (r << (MP_DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero excess digits */ + MP_ZERO_DIGITS(b->dp + b->used, oldused - b->used); + + b->sign = a->sign; + mp_clamp(b); + return MP_OKAY; +} +#endif + +/* End: bn_mp_div_2.c */ + +/* Start: bn_mp_div_2d.c */ +#include "tommath_private.h" +#ifdef BN_MP_DIV_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ +mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) +{ + mp_digit D, r, rr; + int x; + mp_err err; + + /* if the shift count is <= 0 then we do no work */ + if (b <= 0) { + err = mp_copy(a, c); + if (d != NULL) { + mp_zero(d); + } + return err; + } + + /* copy */ + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + /* 'a' should not be used after here - it might be the same as d */ + + /* get the remainder */ + if (d != NULL) { + if ((err = mp_mod_2d(a, b, d)) != MP_OKAY) { + return err; + } + } + + /* shift by as many digits in the bit count */ + if (b >= MP_DIGIT_BIT) { + mp_rshd(c, b / MP_DIGIT_BIT); + } + + /* shift any bit count < MP_DIGIT_BIT */ + D = (mp_digit)(b % MP_DIGIT_BIT); + if (D != 0u) { + mp_digit *tmpc, mask, shift; + + /* mask */ + mask = ((mp_digit)1 << D) - 1uL; + + /* shift for lsb */ + shift = (mp_digit)MP_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); + return MP_OKAY; +} +#endif + +/* End: bn_mp_div_2d.c */ + +/* Start: bn_mp_div_3.c */ +#include "tommath_private.h" +#ifdef BN_MP_DIV_3_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* divide by three (based on routine from MPI and the GMP manual) */ +mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) +{ + mp_int q; + mp_word w, t; + mp_digit b; + mp_err err; + int ix; + + /* b = 2**MP_DIGIT_BIT / 3 */ + b = ((mp_word)1 << (mp_word)MP_DIGIT_BIT) / (mp_word)3; + + if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { + return err; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix]; + + if (w >= 3u) { + /* multiply w by [1/3] */ + t = (w * (mp_word)b) >> (mp_word)MP_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 >= 3u) { + t += 1u; + w -= 3u; + } + } 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 err; +} + +#endif + +/* End: bn_mp_div_3.c */ + +/* Start: bn_mp_div_d.c */ +#include "tommath_private.h" +#ifdef BN_MP_DIV_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single digit division (based on routine from MPI) */ +mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) +{ + mp_int q; + mp_word w; + mp_digit t; + mp_err err; + int ix; + + /* cannot divide by zero */ + if (b == 0u) { + return MP_VAL; + } + + /* quick outs */ + if ((b == 1u) || MP_IS_ZERO(a)) { + if (d != NULL) { + *d = 0; + } + if (c != NULL) { + return mp_copy(a, c); + } + return MP_OKAY; + } + + /* power of two ? */ + if ((b & (b - 1u)) == 0u) { + ix = 1; + while ((ix < MP_DIGIT_BIT) && (b != (((mp_digit)1)<dp[0] & (((mp_digit)1<<(mp_digit)ix) - 1uL); + } + if (c != NULL) { + return mp_div_2d(a, ix, c, NULL); + } + return MP_OKAY; + } + + /* three? */ + if (MP_HAS(MP_DIV_3) && (b == 3u)) { + return mp_div_3(a, c, d); + } + + /* no easy answer [c'est la vie]. Just division */ + if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { + return err; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << (mp_word)MP_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] = t; + } + + if (d != NULL) { + *d = (mp_digit)w; + } + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return err; +} + +#endif + +/* End: bn_mp_div_d.c */ + +/* Start: bn_mp_dr_is_modulus.c */ +#include "tommath_private.h" +#ifdef BN_MP_DR_IS_MODULUS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if a number is a valid DR modulus */ +mp_bool mp_dr_is_modulus(const mp_int *a) +{ + int ix; + + /* must be at least two digits */ + if (a->used < 2) { + return MP_NO; + } + + /* 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 MP_NO; + } + } + return MP_YES; +} + +#endif + +/* End: bn_mp_dr_is_modulus.c */ + +/* Start: bn_mp_dr_reduce.c */ +#include "tommath_private.h" +#ifdef BN_MP_DR_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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 + */ +mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k) +{ + mp_err err; + int 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)MP_DIGIT_BIT)); + } + + /* set final carry */ + *tmpx1++ = mu; + + /* zero words above m */ + MP_ZERO_DIGITS(tmpx1, (x->used - m) - 1); + + /* 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) { + if ((err = s_mp_sub(x, n, x)) != MP_OKAY) { + return err; + } + goto top; + } + return MP_OKAY; +} +#endif + +/* End: bn_mp_dr_reduce.c */ + +/* Start: bn_mp_dr_setup.c */ +#include "tommath_private.h" +#ifdef BN_MP_DR_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines the setup value */ +void mp_dr_setup(const mp_int *a, mp_digit *d) +{ + /* the casts are required if MP_DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. MP_DIGIT_BIT==31] + */ + *d = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - (mp_word)a->dp[0]); +} + +#endif + +/* End: bn_mp_dr_setup.c */ + +/* Start: bn_mp_error_to_string.c */ +#include "tommath_private.h" +#ifdef BN_MP_ERROR_TO_STRING_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* return a char * string for a given code */ +const char *mp_error_to_string(mp_err code) +{ + switch (code) { + case MP_OKAY: + return "Successful"; + case MP_ERR: + return "Unknown error"; + case MP_MEM: + return "Out of heap"; + case MP_VAL: + return "Value out of range"; + case MP_ITER: + return "Max. iterations reached"; + case MP_BUF: + return "Buffer overflow"; + default: + return "Invalid error code"; + } +} + +#endif + +/* End: bn_mp_error_to_string.c */ + +/* Start: bn_mp_exch.c */ +#include "tommath_private.h" +#ifdef BN_MP_EXCH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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 + +/* End: bn_mp_exch.c */ + +/* Start: bn_mp_expt_u32.c */ +#include "tommath_private.h" +#ifdef BN_MP_EXPT_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* calculate c = a**b using a square-multiply algorithm */ +mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) +{ + mp_err err; + + mp_int g; + + if ((err = mp_init_copy(&g, a)) != MP_OKAY) { + return err; + } + + /* set initial result */ + mp_set(c, 1uL); + + while (b > 0u) { + /* if the bit is set multiply */ + if ((b & 1u) != 0u) { + if ((err = mp_mul(c, &g, c)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* square */ + if (b > 1u) { + if ((err = mp_sqr(&g, &g)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* shift to next bit */ + b >>= 1; + } + + err = MP_OKAY; + +LBL_ERR: + mp_clear(&g); + return err; +} + +#endif + +/* End: bn_mp_expt_u32.c */ + +/* Start: bn_mp_exptmod.c */ +#include "tommath_private.h" +#ifdef BN_MP_EXPTMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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) + */ +mp_err mp_exptmod(const mp_int *G, const mp_int *X, const 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) { + mp_int tmpG, tmpX; + mp_err err; + + if (!MP_HAS(MP_INVMOD)) { + return MP_VAL; + } + + if ((err = mp_init_multi(&tmpG, &tmpX, NULL)) != MP_OKAY) { + return err; + } + + /* first compute 1/G mod P */ + if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { + goto LBL_ERR; + } + + /* now get |X| */ + if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { + goto LBL_ERR; + } + + /* and now compute (1/G)**|X| instead of G**X [X < 0] */ + err = mp_exptmod(&tmpG, &tmpX, P, Y); +LBL_ERR: + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; + } + + /* modified diminished radix reduction */ + if (MP_HAS(MP_REDUCE_IS_2K_L) && MP_HAS(MP_REDUCE_2K_L) && MP_HAS(S_MP_EXPTMOD) && + (mp_reduce_is_2k_l(P) == MP_YES)) { + return s_mp_exptmod(G, X, P, Y, 1); + } + + /* is it a DR modulus? default to no */ + dr = (MP_HAS(MP_DR_IS_MODULUS) && (mp_dr_is_modulus(P) == MP_YES)) ? 1 : 0; + + /* if not, is it a unrestricted DR modulus? */ + if (MP_HAS(MP_REDUCE_IS_2K) && (dr == 0)) { + dr = (mp_reduce_is_2k(P) == MP_YES) ? 2 : 0; + } + + /* if the modulus is odd or dr != 0 use the montgomery method */ + if (MP_HAS(S_MP_EXPTMOD_FAST) && (MP_IS_ODD(P) || (dr != 0))) { + return s_mp_exptmod_fast(G, X, P, Y, dr); + } else if (MP_HAS(S_MP_EXPTMOD)) { + /* 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 + +/* End: bn_mp_exptmod.c */ + +/* Start: bn_mp_exteuclid.c */ +#include "tommath_private.h" +#ifdef BN_MP_EXTEUCLID_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Extended euclidean algorithm of (a, b) produces + a*u1 + b*u2 = u3 + */ +mp_err mp_exteuclid(const mp_int *a, const 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; + mp_err 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, 1uL); + if ((err = mp_copy(a, &u3)) != MP_OKAY) goto LBL_ERR; + + /* initialize, (v1,v2,v3) = (0,1,b) */ + mp_set(&v2, 1uL); + if ((err = mp_copy(b, &v3)) != MP_OKAY) goto LBL_ERR; + + /* loop while v3 != 0 */ + while (!MP_IS_ZERO(&v3)) { + /* q = u3/v3 */ + if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) goto LBL_ERR; + + /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ + if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) goto LBL_ERR; + + /* (u1,u2,u3) = (v1,v2,v3) */ + if ((err = mp_copy(&v1, &u1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&v2, &u2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&v3, &u3)) != MP_OKAY) goto LBL_ERR; + + /* (v1,v2,v3) = (t1,t2,t3) */ + if ((err = mp_copy(&t1, &v1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&t2, &v2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&t3, &v3)) != MP_OKAY) goto LBL_ERR; + } + + /* make sure U3 >= 0 */ + if (u3.sign == MP_NEG) { + if ((err = mp_neg(&u1, &u1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_neg(&u2, &u2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_neg(&u3, &u3)) != MP_OKAY) goto LBL_ERR; + } + + /* 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; +LBL_ERR: + mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); + return err; +} +#endif + +/* End: bn_mp_exteuclid.c */ + +/* Start: bn_mp_fread.c */ +#include "tommath_private.h" +#ifdef BN_MP_FREAD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef MP_NO_FILE +/* read a bigint from a file stream in ASCII */ +mp_err mp_fread(mp_int *a, int radix, FILE *stream) +{ + mp_err err; + mp_sign neg; + + /* if first digit is - then set negative */ + int ch = fgetc(stream); + if (ch == (int)'-') { + neg = MP_NEG; + ch = fgetc(stream); + } else { + neg = MP_ZPOS; + } + + /* no digits, return error */ + if (ch == EOF) { + return MP_ERR; + } + + /* clear a */ + mp_zero(a); + + do { + int y; + unsigned pos = (unsigned)(ch - (int)'('); + if (mp_s_rmap_reverse_sz < pos) { + break; + } + + y = (int)mp_s_rmap_reverse[pos]; + + if ((y == 0xff) || (y >= radix)) { + break; + } + + /* shift up and add */ + if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) { + return err; + } + } while ((ch = fgetc(stream)) != EOF); + + if (a->used != 0) { + a->sign = neg; + } + + return MP_OKAY; +} +#endif + +#endif + +/* End: bn_mp_fread.c */ + +/* Start: bn_mp_from_sbin.c */ +#include "tommath_private.h" +#ifdef BN_MP_FROM_SBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* read signed bin, big endian, first byte is 0==positive or 1==negative */ +mp_err mp_from_sbin(mp_int *a, const unsigned char *buf, size_t size) +{ + mp_err err; + + /* read magnitude */ + if ((err = mp_from_ubin(a, buf + 1, size - 1u)) != MP_OKAY) { + return err; + } + + /* first byte is 0 for positive, non-zero for negative */ + if (buf[0] == (unsigned char)0) { + a->sign = MP_ZPOS; + } else { + a->sign = MP_NEG; + } + + return MP_OKAY; +} +#endif + +/* End: bn_mp_from_sbin.c */ + +/* Start: bn_mp_from_ubin.c */ +#include "tommath_private.h" +#ifdef BN_MP_FROM_UBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reads a unsigned char array, assumes the msb is stored first [big endian] */ +mp_err mp_from_ubin(mp_int *a, const unsigned char *buf, size_t size) +{ + mp_err err; + + /* make sure there are at least two digits */ + if (a->alloc < 2) { + if ((err = mp_grow(a, 2)) != MP_OKAY) { + return err; + } + } + + /* zero the int */ + mp_zero(a); + + /* read the bytes in */ + while (size-- > 0u) { + if ((err = mp_mul_2d(a, 8, a)) != MP_OKAY) { + return err; + } + +#ifndef MP_8BIT + a->dp[0] |= *buf++; + a->used += 1; +#else + a->dp[0] = (*buf & MP_MASK); + a->dp[1] |= ((*buf++ >> 7) & 1u); + a->used += 2; +#endif + } + mp_clamp(a); + return MP_OKAY; +} +#endif + +/* End: bn_mp_from_ubin.c */ + +/* Start: bn_mp_fwrite.c */ +#include "tommath_private.h" +#ifdef BN_MP_FWRITE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef MP_NO_FILE +mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) +{ + char *buf; + mp_err err; + int len; + size_t written; + + /* TODO: this function is not in this PR */ + if (MP_HAS(MP_RADIX_SIZE_OVERESTIMATE)) { + /* if ((err = mp_radix_size_overestimate(&t, base, &len)) != MP_OKAY) goto LBL_ERR; */ + } else { + if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) { + return err; + } + } + + buf = (char *) MP_MALLOC((size_t)len); + if (buf == NULL) { + return MP_MEM; + } + + if ((err = mp_to_radix(a, buf, (size_t)len, &written, radix)) != MP_OKAY) { + goto LBL_ERR; + } + + if (fwrite(buf, written, 1uL, stream) != 1uL) { + err = MP_ERR; + goto LBL_ERR; + } + err = MP_OKAY; + + +LBL_ERR: + MP_FREE_BUFFER(buf, (size_t)len); + return err; +} +#endif + +#endif + +/* End: bn_mp_fwrite.c */ + +/* Start: bn_mp_gcd.c */ +#include "tommath_private.h" +#ifdef BN_MP_GCD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Greatest Common Divisor using the binary method */ +mp_err mp_gcd(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int u, v; + int k, u_lsb, v_lsb; + mp_err err; + + /* either zero than gcd is the largest */ + if (MP_IS_ZERO(a)) { + return mp_abs(b, c); + } + if (MP_IS_ZERO(b)) { + return mp_abs(a, c); + } + + /* get copies of a and b we can modify */ + if ((err = mp_init_copy(&u, a)) != MP_OKAY) { + return err; + } + + if ((err = 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 = MP_MIN(u_lsb, v_lsb); + + if (k > 0) { + /* divide the power of two out */ + if ((err = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + + if ((err = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* divide any remaining factors of two out */ + if (u_lsb != k) { + if ((err = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + if (v_lsb != k) { + if ((err = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + while (!MP_IS_ZERO(&v)) { + /* 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 ((err = s_mp_sub(&v, &u, &v)) != MP_OKAY) { + goto LBL_V; + } + + /* Divide out all factors of two */ + if ((err = 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 ((err = mp_mul_2d(&u, k, c)) != MP_OKAY) { + goto LBL_V; + } + c->sign = MP_ZPOS; + err = MP_OKAY; +LBL_V: + mp_clear(&u); +LBL_U: + mp_clear(&v); + return err; +} +#endif + +/* End: bn_mp_gcd.c */ + +/* Start: bn_mp_get_double.c */ +#include "tommath_private.h" +#ifdef BN_MP_GET_DOUBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +double mp_get_double(const mp_int *a) +{ + int i; + double d = 0.0, fac = 1.0; + for (i = 0; i < MP_DIGIT_BIT; ++i) { + fac *= 2.0; + } + for (i = a->used; i --> 0;) { + d = (d * fac) + (double)a->dp[i]; + } + return (a->sign == MP_NEG) ? -d : d; +} +#endif + +/* End: bn_mp_get_double.c */ + +/* Start: bn_mp_get_i32.c */ +#include "tommath_private.h" +#ifdef BN_MP_GET_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_i32, mp_get_mag_u32, int32_t, uint32_t) +#endif + +/* End: bn_mp_get_i32.c */ + +/* Start: bn_mp_get_i64.c */ +#include "tommath_private.h" +#ifdef BN_MP_GET_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_i64, mp_get_mag_u64, int64_t, uint64_t) +#endif + +/* End: bn_mp_get_i64.c */ + +/* Start: bn_mp_get_l.c */ +#include "tommath_private.h" +#ifdef BN_MP_GET_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_l, mp_get_mag_ul, long, unsigned long) +#endif + +/* End: bn_mp_get_l.c */ + +/* Start: bn_mp_get_ll.c */ +#include "tommath_private.h" +#ifdef BN_MP_GET_LL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_ll, mp_get_mag_ull, long long, unsigned long long) +#endif + +/* End: bn_mp_get_ll.c */ + +/* Start: bn_mp_get_mag_u32.c */ +#include "tommath_private.h" +#ifdef BN_MP_GET_MAG_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_u32, uint32_t) +#endif + +/* End: bn_mp_get_mag_u32.c */ + +/* Start: bn_mp_get_mag_u64.c */ +#include "tommath_private.h" +#ifdef BN_MP_GET_MAG_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_u64, uint64_t) +#endif + +/* End: bn_mp_get_mag_u64.c */ + +/* Start: bn_mp_get_mag_ul.c */ +#include "tommath_private.h" +#ifdef BN_MP_GET_MAG_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_ul, unsigned long) +#endif + +/* End: bn_mp_get_mag_ul.c */ + +/* Start: bn_mp_get_mag_ull.c */ +#include "tommath_private.h" +#ifdef BN_MP_GET_MAG_ULL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_ull, unsigned long long) +#endif + +/* End: bn_mp_get_mag_ull.c */ + +/* Start: bn_mp_grow.c */ +#include "tommath_private.h" +#ifdef BN_MP_GROW_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* grow as required */ +mp_err 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) { + /* 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 = (mp_digit *) MP_REALLOC(a->dp, + (size_t)a->alloc * sizeof(mp_digit), + (size_t)size * sizeof(mp_digit)); + 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; + MP_ZERO_DIGITS(a->dp + i, a->alloc - i); + } + return MP_OKAY; +} +#endif + +/* End: bn_mp_grow.c */ + +/* Start: bn_mp_incr.c */ +#include "tommath_private.h" +#ifdef BN_MP_INCR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Increment "a" by one like "a++". Changes input! */ +mp_err mp_incr(mp_int *a) +{ + if (MP_IS_ZERO(a)) { + mp_set(a,1uL); + return MP_OKAY; + } else if (a->sign == MP_NEG) { + mp_err err; + a->sign = MP_ZPOS; + if ((err = mp_decr(a)) != MP_OKAY) { + return err; + } + /* There is no -0 in LTM */ + if (!MP_IS_ZERO(a)) { + a->sign = MP_NEG; + } + return MP_OKAY; + } else if (a->dp[0] < MP_DIGIT_MAX) { + a->dp[0]++; + return MP_OKAY; + } else { + return mp_add_d(a, 1uL,a); + } +} +#endif + +/* End: bn_mp_incr.c */ + +/* Start: bn_mp_init.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* init a new mp_int */ +mp_err mp_init(mp_int *a) +{ + /* allocate memory required and clear it */ + a->dp = (mp_digit *) MP_CALLOC((size_t)MP_PREC, sizeof(mp_digit)); + if (a->dp == NULL) { + return MP_MEM; + } + + /* 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 + +/* End: bn_mp_init.c */ + +/* Start: bn_mp_init_copy.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_COPY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* creates "a" then copies b into it */ +mp_err mp_init_copy(mp_int *a, const mp_int *b) +{ + mp_err err; + + if ((err = mp_init_size(a, b->used)) != MP_OKAY) { + return err; + } + + if ((err = mp_copy(b, a)) != MP_OKAY) { + mp_clear(a); + } + + return err; +} +#endif + +/* End: bn_mp_init_copy.c */ + +/* Start: bn_mp_init_i32.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_i32, mp_set_i32, int32_t) +#endif + +/* End: bn_mp_init_i32.c */ + +/* Start: bn_mp_init_i64.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_i64, mp_set_i64, int64_t) +#endif + +/* End: bn_mp_init_i64.c */ + +/* Start: bn_mp_init_l.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_l, mp_set_l, long) +#endif + +/* End: bn_mp_init_l.c */ + +/* Start: bn_mp_init_ll.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_LL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_ll, mp_set_ll, long long) +#endif + +/* End: bn_mp_init_ll.c */ + +/* Start: bn_mp_init_multi.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_MULTI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include + +mp_err mp_init_multi(mp_int *mp, ...) +{ + mp_err err = 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; + + /* now start cleaning up */ + cur_arg = mp; + va_start(clean_args, mp); + while (n-- != 0) { + mp_clear(cur_arg); + cur_arg = va_arg(clean_args, mp_int *); + } + va_end(clean_args); + err = MP_MEM; + break; + } + n++; + cur_arg = va_arg(args, mp_int *); + } + va_end(args); + return err; /* Assumed ok, if error flagged above. */ +} + +#endif + +/* End: bn_mp_init_multi.c */ + +/* Start: bn_mp_init_set.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_SET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* initialize and set a digit */ +mp_err mp_init_set(mp_int *a, mp_digit b) +{ + mp_err err; + if ((err = mp_init(a)) != MP_OKAY) { + return err; + } + mp_set(a, b); + return err; +} +#endif + +/* End: bn_mp_init_set.c */ + +/* Start: bn_mp_init_size.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* init an mp_init for a given size */ +mp_err mp_init_size(mp_int *a, int size) +{ + size = MP_MAX(MP_MIN_PREC, size); + + /* alloc mem */ + a->dp = (mp_digit *) MP_CALLOC((size_t)size, sizeof(mp_digit)); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the members */ + a->used = 0; + a->alloc = size; + a->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif + +/* End: bn_mp_init_size.c */ + +/* Start: bn_mp_init_u32.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_u32, mp_set_u32, uint32_t) +#endif + +/* End: bn_mp_init_u32.c */ + +/* Start: bn_mp_init_u64.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_u64, mp_set_u64, uint64_t) +#endif + +/* End: bn_mp_init_u64.c */ + +/* Start: bn_mp_init_ul.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_ul, mp_set_ul, unsigned long) +#endif + +/* End: bn_mp_init_ul.c */ + +/* Start: bn_mp_init_ull.c */ +#include "tommath_private.h" +#ifdef BN_MP_INIT_ULL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_ull, mp_set_ull, unsigned long long) +#endif + +/* End: bn_mp_init_ull.c */ + +/* Start: bn_mp_invmod.c */ +#include "tommath_private.h" +#ifdef BN_MP_INVMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* hac 14.61, pp608 */ +mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) +{ + /* b cannot be negative and has to be >1 */ + if ((b->sign == MP_NEG) || (mp_cmp_d(b, 1uL) != MP_GT)) { + return MP_VAL; + } + + /* if the modulus is odd we can use a faster routine instead */ + if (MP_HAS(S_MP_INVMOD_FAST) && MP_IS_ODD(b)) { + return s_mp_invmod_fast(a, b, c); + } + + return MP_HAS(S_MP_INVMOD_SLOW) + ? s_mp_invmod_slow(a, b, c) + : MP_VAL; +} +#endif + +/* End: bn_mp_invmod.c */ + +/* Start: bn_mp_is_square.c */ +#include "tommath_private.h" +#ifdef BN_MP_IS_SQUARE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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 */ +mp_err mp_is_square(const mp_int *arg, mp_bool *ret) +{ + mp_err err; + mp_digit c; + mp_int t; + unsigned long r; + + /* Default to Non-square :) */ + *ret = MP_NO; + + if (arg->sign == MP_NEG) { + return MP_VAL; + } + + if (MP_IS_ZERO(arg)) { + return MP_OKAY; + } + + /* First check mod 128 (suppose that MP_DIGIT_BIT is at least 7) */ + if (rem_128[127u & arg->dp[0]] == (char)1) { + return MP_OKAY; + } + + /* Next check mod 105 (3*5*7) */ + if ((err = mp_mod_d(arg, 105uL, &c)) != MP_OKAY) { + return err; + } + if (rem_105[c] == (char)1) { + return MP_OKAY; + } + + + if ((err = mp_init_u32(&t, 11u*13u*17u*19u*23u*29u*31u)) != MP_OKAY) { + return err; + } + if ((err = mp_mod(arg, &t, &t)) != MP_OKAY) { + goto LBL_ERR; + } + r = mp_get_u32(&t); + /* Check for other prime modules, note it's not an ERROR but we must + * free "t" so the easiest way is to goto LBL_ERR. We know that err + * is already equal to MP_OKAY from the mp_mod call + */ + if (((1uL<<(r%11uL)) & 0x5C4uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%13uL)) & 0x9E4uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%17uL)) & 0x5CE8uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%19uL)) & 0x4F50CuL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%23uL)) & 0x7ACCA0uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%29uL)) & 0xC2EDD0CuL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%31uL)) & 0x6DE2B848uL) != 0uL) goto LBL_ERR; + + /* Final check - is sqr(sqrt(arg)) == arg ? */ + if ((err = mp_sqrt(arg, &t)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_sqr(&t, &t)) != MP_OKAY) { + goto LBL_ERR; + } + + *ret = (mp_cmp_mag(&t, arg) == MP_EQ) ? MP_YES : MP_NO; +LBL_ERR: + mp_clear(&t); + return err; +} +#endif + +/* End: bn_mp_is_square.c */ + +/* Start: bn_mp_iseven.c */ +#include "tommath_private.h" +#ifdef BN_MP_ISEVEN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_bool mp_iseven(const mp_int *a) +{ + return MP_IS_EVEN(a) ? MP_YES : MP_NO; +} +#endif + +/* End: bn_mp_iseven.c */ + +/* Start: bn_mp_isodd.c */ +#include "tommath_private.h" +#ifdef BN_MP_ISODD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_bool mp_isodd(const mp_int *a) +{ + return MP_IS_ODD(a) ? MP_YES : MP_NO; +} +#endif + +/* End: bn_mp_isodd.c */ + +/* Start: bn_mp_kronecker.c */ +#include "tommath_private.h" +#ifdef BN_MP_KRONECKER_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + Kronecker symbol (a|p) + Straightforward implementation of algorithm 1.4.10 in + Henri Cohen: "A Course in Computational Algebraic Number Theory" + + @book{cohen2013course, + title={A course in computational algebraic number theory}, + author={Cohen, Henri}, + volume={138}, + year={2013}, + publisher={Springer Science \& Business Media} + } + */ +mp_err mp_kronecker(const mp_int *a, const mp_int *p, int *c) +{ + mp_int a1, p1, r; + mp_err err; + int v, k; + + static const int table[8] = {0, 1, 0, -1, 0, -1, 0, 1}; + + if (MP_IS_ZERO(p)) { + if ((a->used == 1) && (a->dp[0] == 1u)) { + *c = 1; + } else { + *c = 0; + } + return MP_OKAY; + } + + if (MP_IS_EVEN(a) && MP_IS_EVEN(p)) { + *c = 0; + return MP_OKAY; + } + + if ((err = mp_init_copy(&a1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_init_copy(&p1, p)) != MP_OKAY) { + goto LBL_KRON_0; + } + + v = mp_cnt_lsb(&p1); + if ((err = mp_div_2d(&p1, v, &p1, NULL)) != MP_OKAY) { + goto LBL_KRON_1; + } + + if ((v & 1) == 0) { + k = 1; + } else { + k = table[a->dp[0] & 7u]; + } + + if (p1.sign == MP_NEG) { + p1.sign = MP_ZPOS; + if (a1.sign == MP_NEG) { + k = -k; + } + } + + if ((err = mp_init(&r)) != MP_OKAY) { + goto LBL_KRON_1; + } + + for (;;) { + if (MP_IS_ZERO(&a1)) { + if (mp_cmp_d(&p1, 1uL) == MP_EQ) { + *c = k; + goto LBL_KRON; + } else { + *c = 0; + goto LBL_KRON; + } + } + + v = mp_cnt_lsb(&a1); + if ((err = mp_div_2d(&a1, v, &a1, NULL)) != MP_OKAY) { + goto LBL_KRON; + } + + if ((v & 1) == 1) { + k = k * table[p1.dp[0] & 7u]; + } + + if (a1.sign == MP_NEG) { + /* + * Compute k = (-1)^((a1)*(p1-1)/4) * k + * a1.dp[0] + 1 cannot overflow because the MSB + * of the type mp_digit is not set by definition + */ + if (((a1.dp[0] + 1u) & p1.dp[0] & 2u) != 0u) { + k = -k; + } + } else { + /* compute k = (-1)^((a1-1)*(p1-1)/4) * k */ + if ((a1.dp[0] & p1.dp[0] & 2u) != 0u) { + k = -k; + } + } + + if ((err = mp_copy(&a1, &r)) != MP_OKAY) { + goto LBL_KRON; + } + r.sign = MP_ZPOS; + if ((err = mp_mod(&p1, &r, &a1)) != MP_OKAY) { + goto LBL_KRON; + } + if ((err = mp_copy(&r, &p1)) != MP_OKAY) { + goto LBL_KRON; + } + } + +LBL_KRON: + mp_clear(&r); +LBL_KRON_1: + mp_clear(&p1); +LBL_KRON_0: + mp_clear(&a1); + + return err; +} + +#endif + +/* End: bn_mp_kronecker.c */ + +/* Start: bn_mp_lcm.c */ +#include "tommath_private.h" +#ifdef BN_MP_LCM_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes least common multiple as |a*b|/(a, b) */ +mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + mp_int t1, t2; + + + if ((err = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) { + return err; + } + + /* t1 = get the GCD of the two inputs */ + if ((err = 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 ((err = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + err = mp_mul(b, &t2, c); + } else { + /* store quotient in t2 such that t2 * a is the LCM */ + if ((err = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + err = mp_mul(a, &t2, c); + } + + /* fix the sign to positive */ + c->sign = MP_ZPOS; + +LBL_T: + mp_clear_multi(&t1, &t2, NULL); + return err; +} +#endif + +/* End: bn_mp_lcm.c */ + +/* Start: bn_mp_log_u32.c */ +#include "tommath_private.h" +#ifdef BN_MP_LOG_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Compute log_{base}(a) */ +static mp_word s_pow(mp_word base, mp_word exponent) +{ + mp_word result = 1uLL; + while (exponent != 0u) { + if ((exponent & 1u) == 1u) { + result *= base; + } + exponent >>= 1; + base *= base; + } + + return result; +} + +static mp_digit s_digit_ilogb(mp_digit base, mp_digit n) +{ + mp_word bracket_low = 1uLL, bracket_mid, bracket_high, N; + mp_digit ret, high = 1uL, low = 0uL, mid; + + if (n < base) { + return 0uL; + } + if (n == base) { + return 1uL; + } + + bracket_high = (mp_word) base ; + N = (mp_word) n; + + while (bracket_high < N) { + low = high; + bracket_low = bracket_high; + high <<= 1; + bracket_high *= bracket_high; + } + + while (((mp_digit)(high - low)) > 1uL) { + mid = (low + high) >> 1; + bracket_mid = bracket_low * s_pow(base, (mp_word)(mid - low)); + + if (N < bracket_mid) { + high = mid ; + bracket_high = bracket_mid ; + } + if (N > bracket_mid) { + low = mid ; + bracket_low = bracket_mid ; + } + if (N == bracket_mid) { + return (mp_digit) mid; + } + } + + if (bracket_high == N) { + ret = high; + } else { + ret = low; + } + + return ret; +} + +/* TODO: output could be "int" because the output of mp_radix_size is int, too, + as is the output of mp_bitcount. + With the same problem: max size is INT_MAX * MP_DIGIT not INT_MAX only! +*/ +mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c) +{ + mp_err err; + mp_ord cmp; + uint32_t high, low, mid; + mp_int bracket_low, bracket_high, bracket_mid, t, bi_base; + + err = MP_OKAY; + + if (a->sign == MP_NEG) { + return MP_VAL; + } + + if (MP_IS_ZERO(a)) { + return MP_VAL; + } + + if (base < 2u) { + return MP_VAL; + } + + /* A small shortcut for bases that are powers of two. */ + if ((base & (base - 1u)) == 0u) { + int y, bit_count; + for (y=0; (y < 7) && ((base & 1u) == 0u); y++) { + base >>= 1; + } + bit_count = mp_count_bits(a) - 1; + *c = (uint32_t)(bit_count/y); + return MP_OKAY; + } + + if (a->used == 1) { + *c = (uint32_t)s_digit_ilogb(base, a->dp[0]); + return err; + } + + cmp = mp_cmp_d(a, base); + if ((cmp == MP_LT) || (cmp == MP_EQ)) { + *c = cmp == MP_EQ; + return err; + } + + if ((err = + mp_init_multi(&bracket_low, &bracket_high, + &bracket_mid, &t, &bi_base, NULL)) != MP_OKAY) { + return err; + } + + low = 0u; + mp_set(&bracket_low, 1uL); + high = 1u; + + mp_set(&bracket_high, base); + + /* + A kind of Giant-step/baby-step algorithm. + Idea shamelessly stolen from https://programmingpraxis.com/2010/05/07/integer-logarithms/2/ + The effect is asymptotic, hence needs benchmarks to test if the Giant-step should be skipped + for small n. + */ + while (mp_cmp(&bracket_high, a) == MP_LT) { + low = high; + if ((err = mp_copy(&bracket_high, &bracket_low)) != MP_OKAY) { + goto LBL_ERR; + } + high <<= 1; + if ((err = mp_sqr(&bracket_high, &bracket_high)) != MP_OKAY) { + goto LBL_ERR; + } + } + mp_set(&bi_base, base); + + while ((high - low) > 1u) { + mid = (high + low) >> 1; + + if ((err = mp_expt_u32(&bi_base, (uint32_t)(mid - low), &t)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_mul(&bracket_low, &t, &bracket_mid)) != MP_OKAY) { + goto LBL_ERR; + } + cmp = mp_cmp(a, &bracket_mid); + if (cmp == MP_LT) { + high = mid; + mp_exch(&bracket_mid, &bracket_high); + } + if (cmp == MP_GT) { + low = mid; + mp_exch(&bracket_mid, &bracket_low); + } + if (cmp == MP_EQ) { + *c = mid; + goto LBL_END; + } + } + + *c = (mp_cmp(&bracket_high, a) == MP_EQ) ? high : low; + +LBL_END: +LBL_ERR: + mp_clear_multi(&bracket_low, &bracket_high, &bracket_mid, + &t, &bi_base, NULL); + return err; +} + + +#endif + +/* End: bn_mp_log_u32.c */ + +/* Start: bn_mp_lshd.c */ +#include "tommath_private.h" +#ifdef BN_MP_LSHD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift left a certain amount of digits */ +mp_err mp_lshd(mp_int *a, int b) +{ + int x; + mp_err err; + mp_digit *top, *bottom; + + /* if its less than zero return */ + if (b <= 0) { + return MP_OKAY; + } + /* no need to shift 0 around */ + if (MP_IS_ZERO(a)) { + return MP_OKAY; + } + + /* grow to fit the new digits */ + if (a->alloc < (a->used + b)) { + if ((err = mp_grow(a, a->used + b)) != MP_OKAY) { + return err; + } + } + + /* 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 */ + MP_ZERO_DIGITS(a->dp, b); + + return MP_OKAY; +} +#endif + +/* End: bn_mp_lshd.c */ + +/* Start: bn_mp_mod.c */ +#include "tommath_private.h" +#ifdef BN_MP_MOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* c = a mod b, 0 <= c < b if b > 0, b < c <= 0 if b < 0 */ +mp_err mp_mod(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int t; + mp_err err; + + if ((err = mp_init_size(&t, b->used)) != MP_OKAY) { + return err; + } + + if ((err = mp_div(a, b, NULL, &t)) != MP_OKAY) { + goto LBL_ERR; + } + + if (MP_IS_ZERO(&t) || (t.sign == b->sign)) { + err = MP_OKAY; + mp_exch(&t, c); + } else { + err = mp_add(b, &t, c); + } + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif + +/* End: bn_mp_mod.c */ + +/* Start: bn_mp_mod_2d.c */ +#include "tommath_private.h" +#ifdef BN_MP_MOD_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* calc a value mod 2**b */ +mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c) +{ + int x; + mp_err err; + + /* 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 >= (a->used * MP_DIGIT_BIT)) { + return mp_copy(a, c); + } + + /* copy */ + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + + /* zero digits above the last digit of the modulus */ + x = (b / MP_DIGIT_BIT) + (((b % MP_DIGIT_BIT) == 0) ? 0 : 1); + MP_ZERO_DIGITS(c->dp + x, c->used - x); + + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / MP_DIGIT_BIT] &= + ((mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT)) - (mp_digit)1; + mp_clamp(c); + return MP_OKAY; +} +#endif + +/* End: bn_mp_mod_2d.c */ + +/* Start: bn_mp_mod_d.c */ +#include "tommath_private.h" +#ifdef BN_MP_MOD_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err mp_mod_d(const mp_int *a, mp_digit b, mp_digit *c) +{ + return mp_div_d(a, b, NULL, c); +} +#endif + +/* End: bn_mp_mod_d.c */ + +/* Start: bn_mp_montgomery_calc_normalization.c */ +#include "tommath_private.h" +#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * 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. + */ +mp_err mp_montgomery_calc_normalization(mp_int *a, const mp_int *b) +{ + int x, bits; + mp_err err; + + /* how many bits of last digit does b use */ + bits = mp_count_bits(b) % MP_DIGIT_BIT; + + if (b->used > 1) { + if ((err = mp_2expt(a, ((b->used - 1) * MP_DIGIT_BIT) + bits - 1)) != MP_OKAY) { + return err; + } + } else { + mp_set(a, 1uL); + bits = 1; + } + + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int)MP_DIGIT_BIT; x++) { + if ((err = mp_mul_2(a, a)) != MP_OKAY) { + return err; + } + if (mp_cmp_mag(a, b) != MP_LT) { + if ((err = s_mp_sub(a, b, a)) != MP_OKAY) { + return err; + } + } + } + + return MP_OKAY; +} +#endif + +/* End: bn_mp_montgomery_calc_normalization.c */ + +/* Start: bn_mp_montgomery_reduce.c */ +#include "tommath_private.h" +#ifdef BN_MP_MONTGOMERY_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes xR**-1 == x (mod N) via Montgomery Reduction */ +mp_err mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho) +{ + int ix, digs; + mp_err err; + 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) && + (x->used <= MP_WARRAY) && + (n->used < MP_MAXFAST)) { + return s_mp_montgomery_reduce_fast(x, n, rho); + } + + /* grow the input as required */ + if (x->alloc < digs) { + if ((err = mp_grow(x, digs)) != MP_OKAY) { + return err; + } + } + 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 */ + { + int iy; + mp_digit *tmpn, *tmpx, u; + 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)MP_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 != 0u) { + *tmpx += u; + u = *tmpx >> MP_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 + +/* End: bn_mp_montgomery_reduce.c */ + +/* Start: bn_mp_montgomery_setup.c */ +#include "tommath_private.h" +#ifdef BN_MP_MONTGOMERY_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* setups the montgomery reduction stuff */ +mp_err mp_montgomery_setup(const 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 & 1u) == 0u) { + return MP_VAL; + } + + x = (((b + 2u) & 4u) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2u - (b * x); /* here x*a==1 mod 2**8 */ +#if !defined(MP_8BIT) + x *= 2u - (b * x); /* here x*a==1 mod 2**16 */ +#endif +#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT)) + x *= 2u - (b * x); /* here x*a==1 mod 2**32 */ +#endif +#ifdef MP_64BIT + x *= 2u - (b * x); /* here x*a==1 mod 2**64 */ +#endif + + /* rho = -1/m mod b */ + *rho = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - x) & MP_MASK; + + return MP_OKAY; +} +#endif + +/* End: bn_mp_montgomery_setup.c */ + +/* Start: bn_mp_mul.c */ +#include "tommath_private.h" +#ifdef BN_MP_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* high level multiplication (handles sign) */ +mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + int min_len = MP_MIN(a->used, b->used), + max_len = MP_MAX(a->used, b->used), + digs = a->used + b->used + 1; + mp_sign neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + + if (MP_HAS(S_MP_BALANCE_MUL) && + /* Check sizes. The smaller one needs to be larger than the Karatsuba cut-off. + * The bigger one needs to be at least about one MP_KARATSUBA_MUL_CUTOFF bigger + * to make some sense, but it depends on architecture, OS, position of the + * stars... so YMMV. + * Using it to cut the input into slices small enough for fast_s_mp_mul_digs + * was actually slower on the author's machine, but YMMV. + */ + (min_len >= MP_KARATSUBA_MUL_CUTOFF) && + ((max_len / 2) >= MP_KARATSUBA_MUL_CUTOFF) && + /* Not much effect was observed below a ratio of 1:2, but again: YMMV. */ + (max_len >= (2 * min_len))) { + err = s_mp_balance_mul(a,b,c); + } else if (MP_HAS(S_MP_TOOM_MUL) && + (min_len >= MP_TOOM_MUL_CUTOFF)) { + err = s_mp_toom_mul(a, b, c); + } else if (MP_HAS(S_MP_KARATSUBA_MUL) && + (min_len >= MP_KARATSUBA_MUL_CUTOFF)) { + err = s_mp_karatsuba_mul(a, b, c); + } else if (MP_HAS(S_MP_MUL_DIGS_FAST) && + /* 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 + */ + (digs < MP_WARRAY) && + (min_len <= MP_MAXFAST)) { + err = s_mp_mul_digs_fast(a, b, c, digs); + } else if (MP_HAS(S_MP_MUL_DIGS)) { + err = s_mp_mul_digs(a, b, c, digs); + } else { + err = MP_VAL; + } + c->sign = (c->used > 0) ? neg : MP_ZPOS; + return err; +} +#endif + +/* End: bn_mp_mul.c */ + +/* Start: bn_mp_mul_2.c */ +#include "tommath_private.h" +#ifdef BN_MP_MUL_2_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = a*2 */ +mp_err mp_mul_2(const mp_int *a, mp_int *b) +{ + int x, oldused; + mp_err err; + + /* grow to accomodate result */ + if (b->alloc < (a->used + 1)) { + if ((err = mp_grow(b, a->used + 1)) != MP_OKAY) { + return err; + } + } + + oldused = b->used; + b->used = a->used; + + { + 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)(MP_DIGIT_BIT - 1); + + /* now shift up this digit, add in the carry [from the previous] */ + *tmpb++ = ((*tmpa++ << 1uL) | r) & MP_MASK; + + /* copy the carry that would be from the source + * digit into the next iteration + */ + r = rr; + } + + /* new leading digit? */ + if (r != 0u) { + /* 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 + */ + MP_ZERO_DIGITS(b->dp + b->used, oldused - b->used); + } + b->sign = a->sign; + return MP_OKAY; +} +#endif + +/* End: bn_mp_mul_2.c */ + +/* Start: bn_mp_mul_2d.c */ +#include "tommath_private.h" +#ifdef BN_MP_MUL_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift left by a certain bit count */ +mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) +{ + mp_digit d; + mp_err err; + + /* copy */ + if (a != c) { + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + } + + if (c->alloc < (c->used + (b / MP_DIGIT_BIT) + 1)) { + if ((err = mp_grow(c, c->used + (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) { + return err; + } + } + + /* shift by as many digits in the bit count */ + if (b >= MP_DIGIT_BIT) { + if ((err = mp_lshd(c, b / MP_DIGIT_BIT)) != MP_OKAY) { + return err; + } + } + + /* shift any bit count < MP_DIGIT_BIT */ + d = (mp_digit)(b % MP_DIGIT_BIT); + if (d != 0u) { + mp_digit *tmpc, shift, mask, r, rr; + int x; + + /* bitmask for carries */ + mask = ((mp_digit)1 << d) - (mp_digit)1; + + /* shift for msbs */ + shift = (mp_digit)MP_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 != 0u) { + c->dp[(c->used)++] = r; + } + } + mp_clamp(c); + return MP_OKAY; +} +#endif + +/* End: bn_mp_mul_2d.c */ + +/* Start: bn_mp_mul_d.c */ +#include "tommath_private.h" +#ifdef BN_MP_MUL_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* multiply by a digit */ +mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c) +{ + mp_digit u, *tmpa, *tmpc; + mp_word r; + mp_err err; + int ix, olduse; + + /* make sure c is big enough to hold a*b */ + if (c->alloc < (a->used + 1)) { + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + } + + /* 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)MP_DIGIT_BIT); + } + + /* store final carry [if any] and increment ix offset */ + *tmpc++ = u; + ++ix; + + /* now zero digits above the top */ + MP_ZERO_DIGITS(tmpc, olduse - ix); + + /* set used count */ + c->used = a->used + 1; + mp_clamp(c); + + return MP_OKAY; +} +#endif + +/* End: bn_mp_mul_d.c */ + +/* Start: bn_mp_mulmod.c */ +#include "tommath_private.h" +#ifdef BN_MP_MULMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* d = a * b (mod c) */ +mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) +{ + mp_err err; + mp_int t; + + if ((err = mp_init_size(&t, c->used)) != MP_OKAY) { + return err; + } + + if ((err = mp_mul(a, b, &t)) != MP_OKAY) { + goto LBL_ERR; + } + err = mp_mod(&t, c, d); + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif + +/* End: bn_mp_mulmod.c */ + +/* Start: bn_mp_neg.c */ +#include "tommath_private.h" +#ifdef BN_MP_NEG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = -a */ +mp_err mp_neg(const mp_int *a, mp_int *b) +{ + mp_err err; + if (a != b) { + if ((err = mp_copy(a, b)) != MP_OKAY) { + return err; + } + } + + if (!MP_IS_ZERO(b)) { + b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; + } else { + b->sign = MP_ZPOS; + } + + return MP_OKAY; +} +#endif + +/* End: bn_mp_neg.c */ + +/* Start: bn_mp_or.c */ +#include "tommath_private.h" +#ifdef BN_MP_OR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* two complement or */ +mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c) +{ + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + mp_sign csign = ((a->sign == MP_NEG) || (b->sign == MP_NEG)) ? MP_NEG : MP_ZPOS; + + if (c->alloc < used) { + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + } + + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (a->sign == MP_NEG) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (b->sign == MP_NEG) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x | y; + + /* convert to to sign-magnitude if negative */ + if (csign == MP_NEG) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = csign; + mp_clamp(c); + return MP_OKAY; +} +#endif + +/* End: bn_mp_or.c */ + +/* Start: bn_mp_pack.c */ +#include "tommath_private.h" +#ifdef BN_MP_PACK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on gmp's mpz_export. + * see http://gmplib.org/manual/Integer-Import-and-Export.html + */ +mp_err mp_pack(void *rop, size_t maxcount, size_t *written, mp_order order, size_t size, + mp_endian endian, size_t nails, const mp_int *op) +{ + mp_err err; + size_t odd_nails, nail_bytes, i, j, count; + unsigned char odd_nail_mask; + + mp_int t; + + count = mp_pack_count(op, nails, size); + + if (count > maxcount) { + return MP_BUF; + } + + if ((err = mp_init_copy(&t, op)) != MP_OKAY) { + return err; + } + + if (endian == MP_NATIVE_ENDIAN) { + MP_GET_ENDIANNESS(endian); + } + + odd_nails = (nails % 8u); + odd_nail_mask = 0xff; + for (i = 0u; i < odd_nails; ++i) { + odd_nail_mask ^= (unsigned char)(1u << (7u - i)); + } + nail_bytes = nails / 8u; + + for (i = 0u; i < count; ++i) { + for (j = 0u; j < size; ++j) { + unsigned char *byte = (unsigned char *)rop + + (((order == MP_LSB_FIRST) ? i : ((count - 1u) - i)) * size) + + ((endian == MP_LITTLE_ENDIAN) ? j : ((size - 1u) - j)); + + if (j >= (size - nail_bytes)) { + *byte = 0; + continue; + } + + *byte = (unsigned char)((j == ((size - nail_bytes) - 1u)) ? (t.dp[0] & odd_nail_mask) : (t.dp[0] & 0xFFuL)); + + if ((err = mp_div_2d(&t, (j == ((size - nail_bytes) - 1u)) ? (int)(8u - odd_nails) : 8, &t, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + } + } + + if (written != NULL) { + *written = count; + } + err = MP_OKAY; + +LBL_ERR: + mp_clear(&t); + return err; +} + +#endif + +/* End: bn_mp_pack.c */ + +/* Start: bn_mp_pack_count.c */ +#include "tommath_private.h" +#ifdef BN_MP_PACK_COUNT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +size_t mp_pack_count(const mp_int *a, size_t nails, size_t size) +{ + size_t bits = (size_t)mp_count_bits(a); + return ((bits / ((size * 8u) - nails)) + (((bits % ((size * 8u) - nails)) != 0u) ? 1u : 0u)); +} + +#endif + +/* End: bn_mp_pack_count.c */ + +/* Start: bn_mp_prime_fermat.c */ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_FERMAT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. + */ +mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, mp_bool *result) +{ + mp_int t; + mp_err err; + + /* default to composite */ + *result = MP_NO; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1uL) != 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 + +/* End: bn_mp_prime_fermat.c */ + +/* Start: bn_mp_prime_frobenius_underwood.c */ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_FROBENIUS_UNDERWOOD_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * See file bn_mp_prime_is_prime.c or the documentation in doc/bn.tex for the details + */ +#ifndef LTM_USE_ONLY_MR + +#ifdef MP_8BIT +/* + * floor of positive solution of + * (2^16)-1 = (a+4)*(2*a+5) + * TODO: Both values are smaller than N^(1/4), would have to use a bigint + * for a instead but any a biger than about 120 are already so rare that + * it is possible to ignore them and still get enough pseudoprimes. + * But it is still a restriction of the set of available pseudoprimes + * which makes this implementation less secure if used stand-alone. + */ +#define LTM_FROBENIUS_UNDERWOOD_A 177 +#else +#define LTM_FROBENIUS_UNDERWOOD_A 32764 +#endif +mp_err mp_prime_frobenius_underwood(const mp_int *N, mp_bool *result) +{ + mp_int T1z, T2z, Np1z, sz, tz; + + int a, ap2, length, i, j; + mp_err err; + + *result = MP_NO; + + if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, NULL)) != MP_OKAY) { + return err; + } + + for (a = 0; a < LTM_FROBENIUS_UNDERWOOD_A; a++) { + /* TODO: That's ugly! No, really, it is! */ + if ((a==2) || (a==4) || (a==7) || (a==8) || (a==10) || + (a==14) || (a==18) || (a==23) || (a==26) || (a==28)) { + continue; + } + /* (32764^2 - 4) < 2^31, no bigint for >MP_8BIT needed) */ + mp_set_u32(&T1z, (uint32_t)a); + + if ((err = mp_sqr(&T1z, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + + if ((err = mp_sub_d(&T1z, 4uL, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + + if ((err = mp_kronecker(&T1z, N, &j)) != MP_OKAY) goto LBL_FU_ERR; + + if (j == -1) { + break; + } + + if (j == 0) { + /* composite */ + goto LBL_FU_ERR; + } + } + /* Tell it a composite and set return value accordingly */ + if (a >= LTM_FROBENIUS_UNDERWOOD_A) { + err = MP_ITER; + goto LBL_FU_ERR; + } + /* Composite if N and (a+4)*(2*a+5) are not coprime */ + mp_set_u32(&T1z, (uint32_t)((a+4)*((2*a)+5))); + + if ((err = mp_gcd(N, &T1z, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + + if (!((T1z.used == 1) && (T1z.dp[0] == 1u))) goto LBL_FU_ERR; + + ap2 = a + 2; + if ((err = mp_add_d(N, 1uL, &Np1z)) != MP_OKAY) goto LBL_FU_ERR; + + mp_set(&sz, 1uL); + mp_set(&tz, 2uL); + length = mp_count_bits(&Np1z); + + for (i = length - 2; i >= 0; i--) { + /* + * temp = (sz*(a*sz+2*tz))%N; + * tz = ((tz-sz)*(tz+sz))%N; + * sz = temp; + */ + if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_FU_ERR; + + /* a = 0 at about 50% of the cases (non-square and odd input) */ + if (a != 0) { + if ((err = mp_mul_d(&sz, (mp_digit)a, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_add(&T1z, &T2z, &T2z)) != MP_OKAY) goto LBL_FU_ERR; + } + + if ((err = mp_mul(&T2z, &sz, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_sub(&tz, &sz, &T2z)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_add(&sz, &tz, &sz)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_mul(&sz, &T2z, &tz)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_mod(&tz, N, &tz)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_mod(&T1z, N, &sz)) != MP_OKAY) goto LBL_FU_ERR; + if (s_mp_get_bit(&Np1z, (unsigned int)i) == MP_YES) { + /* + * temp = (a+2) * sz + tz + * tz = 2 * tz - sz + * sz = temp + */ + if (a == 0) { + if ((err = mp_mul_2(&sz, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + } else { + if ((err = mp_mul_d(&sz, (mp_digit)ap2, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + } + if ((err = mp_add(&T1z, &tz, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_FU_ERR; + if ((err = mp_sub(&T2z, &sz, &tz)) != MP_OKAY) goto LBL_FU_ERR; + mp_exch(&sz, &T1z); + } + } + + mp_set_u32(&T1z, (uint32_t)((2 * a) + 5)); + if ((err = mp_mod(&T1z, N, &T1z)) != MP_OKAY) goto LBL_FU_ERR; + if (MP_IS_ZERO(&sz) && (mp_cmp(&tz, &T1z) == MP_EQ)) { + *result = MP_YES; + } + +LBL_FU_ERR: + mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, NULL); + return err; +} + +#endif +#endif + +/* End: bn_mp_prime_frobenius_underwood.c */ + +/* Start: bn_mp_prime_is_prime.c */ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_IS_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* portable integer log of two with small footprint */ +static unsigned int s_floor_ilog2(int value) +{ + unsigned int r = 0; + while ((value >>= 1) != 0) { + r++; + } + return r; +} + + +mp_err mp_prime_is_prime(const mp_int *a, int t, mp_bool *result) +{ + mp_int b; + int ix, p_max = 0, size_a, len; + mp_bool res; + mp_err err; + unsigned int fips_rand, mask; + + /* default to no */ + *result = MP_NO; + + /* Some shortcuts */ + /* N > 3 */ + if (a->used == 1) { + if ((a->dp[0] == 0u) || (a->dp[0] == 1u)) { + *result = MP_NO; + return MP_OKAY; + } + if (a->dp[0] == 2u) { + *result = MP_YES; + return MP_OKAY; + } + } + + /* N must be odd */ + if (MP_IS_EVEN(a)) { + return MP_OKAY; + } + /* N is not a perfect square: floor(sqrt(N))^2 != N */ + if ((err = mp_is_square(a, &res)) != MP_OKAY) { + return err; + } + if (res != MP_NO) { + return MP_OKAY; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < PRIVATE_MP_PRIME_TAB_SIZE; ix++) { + if (mp_cmp_d(a, s_mp_prime_tab[ix]) == MP_EQ) { + *result = MP_YES; + return MP_OKAY; + } + } +#ifdef MP_8BIT + /* The search in the loop above was exhaustive in this case */ + if ((a->used == 1) && (PRIVATE_MP_PRIME_TAB_SIZE >= 31)) { + return MP_OKAY; + } +#endif + + /* first perform trial division */ + if ((err = s_mp_prime_is_divisible(a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res == MP_YES) { + return MP_OKAY; + } + + /* + Run the Miller-Rabin test with base 2 for the BPSW test. + */ + if ((err = mp_init_set(&b, 2uL)) != MP_OKAY) { + return err; + } + + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (res == MP_NO) { + goto LBL_B; + } + /* + Rumours have it that Mathematica does a second M-R test with base 3. + Other rumours have it that their strong L-S test is slightly different. + It does not hurt, though, beside a bit of extra runtime. + */ + b.dp[0]++; + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (res == MP_NO) { + goto LBL_B; + } + + /* + * Both, the Frobenius-Underwood test and the the Lucas-Selfridge test are quite + * slow so if speed is an issue, define LTM_USE_ONLY_MR to use M-R tests with + * bases 2, 3 and t random bases. + */ +#ifndef LTM_USE_ONLY_MR + if (t >= 0) { + /* + * Use a Frobenius-Underwood test instead of the Lucas-Selfridge test for + * MP_8BIT (It is unknown if the Lucas-Selfridge test works with 16-bit + * integers but the necesssary analysis is on the todo-list). + */ +#if defined (MP_8BIT) || defined (LTM_USE_FROBENIUS_TEST) + err = mp_prime_frobenius_underwood(a, &res); + if ((err != MP_OKAY) && (err != MP_ITER)) { + goto LBL_B; + } + if (res == MP_NO) { + goto LBL_B; + } +#else + if ((err = mp_prime_strong_lucas_selfridge(a, &res)) != MP_OKAY) { + goto LBL_B; + } + if (res == MP_NO) { + goto LBL_B; + } +#endif + } +#endif + + /* run at least one Miller-Rabin test with a random base */ + if (t == 0) { + t = 1; + } + + /* + Only recommended if the input range is known to be < 3317044064679887385961981 + + It uses the bases necessary for a deterministic M-R test if the input is + smaller than 3317044064679887385961981 + The caller has to check the size. + TODO: can be made a bit finer grained but comparing is not free. + */ + if (t < 0) { + /* + Sorenson, Jonathan; Webster, Jonathan (2015). + "Strong Pseudoprimes to Twelve Prime Bases". + */ + /* 0x437ae92817f9fc85b7e5 = 318665857834031151167461 */ + if ((err = mp_read_radix(&b, "437ae92817f9fc85b7e5", 16)) != MP_OKAY) { + goto LBL_B; + } + + if (mp_cmp(a, &b) == MP_LT) { + p_max = 12; + } else { + /* 0x2be6951adc5b22410a5fd = 3317044064679887385961981 */ + if ((err = mp_read_radix(&b, "2be6951adc5b22410a5fd", 16)) != MP_OKAY) { + goto LBL_B; + } + + if (mp_cmp(a, &b) == MP_LT) { + p_max = 13; + } else { + err = MP_VAL; + goto LBL_B; + } + } + + /* we did bases 2 and 3 already, skip them */ + for (ix = 2; ix < p_max; ix++) { + mp_set(&b, s_mp_prime_tab[ix]); + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (res == MP_NO) { + goto LBL_B; + } + } + } + /* + Do "t" M-R tests with random bases between 3 and "a". + See Fips 186.4 p. 126ff + */ + else if (t > 0) { + /* + * The mp_digit's have a defined bit-size but the size of the + * array a.dp is a simple 'int' and this library can not assume full + * compliance to the current C-standard (ISO/IEC 9899:2011) because + * it gets used for small embeded processors, too. Some of those MCUs + * have compilers that one cannot call standard compliant by any means. + * Hence the ugly type-fiddling in the following code. + */ + size_a = mp_count_bits(a); + mask = (1u << s_floor_ilog2(size_a)) - 1u; + /* + Assuming the General Rieman hypothesis (never thought to write that in a + comment) the upper bound can be lowered to 2*(log a)^2. + E. Bach, "Explicit bounds for primality testing and related problems," + Math. Comp. 55 (1990), 355-380. + + size_a = (size_a/10) * 7; + len = 2 * (size_a * size_a); + + E.g.: a number of size 2^2048 would be reduced to the upper limit + + floor(2048/10)*7 = 1428 + 2 * 1428^2 = 4078368 + + (would have been ~4030331.9962 with floats and natural log instead) + That number is smaller than 2^28, the default bit-size of mp_digit. + */ + + /* + How many tests, you might ask? Dana Jacobsen of Math::Prime::Util fame + does exactly 1. In words: one. Look at the end of _GMP_is_prime() in + Math-Prime-Util-GMP-0.50/primality.c if you do not believe it. + + The function mp_rand() goes to some length to use a cryptographically + good PRNG. That also means that the chance to always get the same base + in the loop is non-zero, although very low. + If the BPSW test and/or the addtional Frobenious test have been + performed instead of just the Miller-Rabin test with the bases 2 and 3, + a single extra test should suffice, so such a very unlikely event + will not do much harm. + + To preemptivly answer the dangling question: no, a witness does not + need to be prime. + */ + for (ix = 0; ix < t; ix++) { + /* mp_rand() guarantees the first digit to be non-zero */ + if ((err = mp_rand(&b, 1)) != MP_OKAY) { + goto LBL_B; + } + /* + * Reduce digit before casting because mp_digit might be bigger than + * an unsigned int and "mask" on the other side is most probably not. + */ + fips_rand = (unsigned int)(b.dp[0] & (mp_digit) mask); +#ifdef MP_8BIT + /* + * One 8-bit digit is too small, so concatenate two if the size of + * unsigned int allows for it. + */ + if ((MP_SIZEOF_BITS(unsigned int)/2) >= MP_SIZEOF_BITS(mp_digit)) { + if ((err = mp_rand(&b, 1)) != MP_OKAY) { + goto LBL_B; + } + fips_rand <<= MP_SIZEOF_BITS(mp_digit); + fips_rand |= (unsigned int) b.dp[0]; + fips_rand &= mask; + } +#endif + if (fips_rand > (unsigned int)(INT_MAX - MP_DIGIT_BIT)) { + len = INT_MAX / MP_DIGIT_BIT; + } else { + len = (((int)fips_rand + MP_DIGIT_BIT) / MP_DIGIT_BIT); + } + /* Unlikely. */ + if (len < 0) { + ix--; + continue; + } + /* + * As mentioned above, one 8-bit digit is too small and + * although it can only happen in the unlikely case that + * an "unsigned int" is smaller than 16 bit a simple test + * is cheap and the correction even cheaper. + */ +#ifdef MP_8BIT + /* All "a" < 2^8 have been caught before */ + if (len == 1) { + len++; + } +#endif + if ((err = mp_rand(&b, len)) != MP_OKAY) { + goto LBL_B; + } + /* + * That number might got too big and the witness has to be + * smaller than "a" + */ + len = mp_count_bits(&b); + if (len >= size_a) { + len = (len - size_a) + 1; + if ((err = mp_div_2d(&b, len, &b, NULL)) != MP_OKAY) { + goto LBL_B; + } + } + /* Although the chance for b <= 3 is miniscule, try again. */ + if (mp_cmp_d(&b, 3uL) != MP_GT) { + ix--; + continue; + } + 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 + +/* End: bn_mp_prime_is_prime.c */ + +/* Start: bn_mp_prime_miller_rabin.c */ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_MILLER_RABIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. + */ +mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, mp_bool *result) +{ + mp_int n1, y, r; + mp_err err; + int s, j; + + /* default */ + *result = MP_NO; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1uL) != 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, 1uL, &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, 1uL) != 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, 1uL) == 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 + +/* End: bn_mp_prime_miller_rabin.c */ + +/* Start: bn_mp_prime_next_prime.c */ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_NEXT_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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 + */ +mp_err mp_prime_next_prime(mp_int *a, int t, int bbs_style) +{ + int x, y; + mp_ord cmp; + mp_err err; + mp_bool res = MP_NO; + mp_digit res_tab[PRIVATE_MP_PRIME_TAB_SIZE], step, kstep; + mp_int b; + + /* force positive */ + a->sign = MP_ZPOS; + + /* simple algo if a is less than the largest prime in the table */ + if (mp_cmp_d(a, s_mp_prime_tab[PRIVATE_MP_PRIME_TAB_SIZE-1]) == MP_LT) { + /* find which prime it is bigger than "a" */ + for (x = 0; x < PRIVATE_MP_PRIME_TAB_SIZE; x++) { + cmp = mp_cmp_d(a, s_mp_prime_tab[x]); + if (cmp == MP_EQ) { + continue; + } + if (cmp != MP_GT) { + if ((bbs_style == 1) && ((s_mp_prime_tab[x] & 3u) != 3u)) { + /* try again until we get a prime congruent to 3 mod 4 */ + continue; + } else { + mp_set(a, s_mp_prime_tab[x]); + 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] & 3u) != 3u) { + if ((err = mp_sub_d(a, (a->dp[0] & 3u) + 1u, a)) != MP_OKAY) { + return err; + } + } + } else { + if (MP_IS_EVEN(a)) { + /* force odd */ + if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) { + return err; + } + } + } + + /* generate the restable */ + for (x = 1; x < PRIVATE_MP_PRIME_TAB_SIZE; x++) { + if ((err = mp_mod_d(a, s_mp_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 < PRIVATE_MP_PRIME_TAB_SIZE; x++) { + /* add the step to each residue */ + res_tab[x] += kstep; + + /* subtract the modulus [instead of using division] */ + if (res_tab[x] >= s_mp_prime_tab[x]) { + res_tab[x] -= s_mp_prime_tab[x]; + } + + /* set flag if zero */ + if (res_tab[x] == 0u) { + y = 1; + } + } + } while ((y == 1) && (step < (((mp_digit)1 << MP_DIGIT_BIT) - kstep))); + + /* add the step */ + if ((err = mp_add_d(a, step, a)) != MP_OKAY) { + goto LBL_ERR; + } + + /* if didn't pass sieve and step == MP_MAX then skip test */ + if ((y == 1) && (step >= (((mp_digit)1 << MP_DIGIT_BIT) - kstep))) { + continue; + } + + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { + goto LBL_ERR; + } + if (res == MP_YES) { + break; + } + } + + err = MP_OKAY; +LBL_ERR: + mp_clear(&b); + return err; +} + +#endif + +/* End: bn_mp_prime_next_prime.c */ + +/* Start: bn_mp_prime_rabin_miller_trials.c */ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +static const struct { + int k, t; +} sizes[] = { + { 80, -1 }, /* Use deterministic algorithm for size <= 80 bits */ + { 81, 37 }, /* max. error = 2^(-96)*/ + { 96, 32 }, /* max. error = 2^(-96)*/ + { 128, 40 }, /* max. error = 2^(-112)*/ + { 160, 35 }, /* max. error = 2^(-112)*/ + { 256, 27 }, /* max. error = 2^(-128)*/ + { 384, 16 }, /* max. error = 2^(-128)*/ + { 512, 18 }, /* max. error = 2^(-160)*/ + { 768, 11 }, /* max. error = 2^(-160)*/ + { 896, 10 }, /* max. error = 2^(-160)*/ + { 1024, 12 }, /* max. error = 2^(-192)*/ + { 1536, 8 }, /* max. error = 2^(-192)*/ + { 2048, 6 }, /* max. error = 2^(-192)*/ + { 3072, 4 }, /* max. error = 2^(-192)*/ + { 4096, 5 }, /* max. error = 2^(-256)*/ + { 5120, 4 }, /* max. error = 2^(-256)*/ + { 6144, 4 }, /* max. error = 2^(-256)*/ + { 8192, 3 }, /* max. error = 2^(-256)*/ + { 9216, 3 }, /* max. error = 2^(-256)*/ + { 10240, 2 } /* For bigger keysizes use always at least 2 Rounds */ +}; + +/* 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; +} + + +#endif + +/* End: bn_mp_prime_rabin_miller_trials.c */ + +/* Start: bn_mp_prime_rand.c */ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * MP_PRIME_BBS - make prime congruent to 3 mod 4 + * MP_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS) + * MP_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! */ +mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat) +{ + unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb; + int bsize, maskOR_msb_offset; + mp_bool res; + mp_err err; + + /* sanity check the input */ + if ((size <= 1) || (t <= 0)) { + return MP_VAL; + } + + /* MP_PRIME_SAFE implies MP_PRIME_BBS */ + if ((flags & MP_PRIME_SAFE) != 0) { + flags |= MP_PRIME_BBS; + } + + /* calc the byte size */ + bsize = (size>>3) + ((size&7)?1:0); + + /* we need a buffer of bsize bytes */ + tmp = (unsigned char *) MP_MALLOC((size_t)bsize); + if (tmp == NULL) { + return MP_MEM; + } + + /* calc the maskAND value for the MSbyte*/ + maskAND = ((size&7) == 0) ? 0xFFu : (unsigned char)(0xFFu >> (8 - (size & 7))); + + /* calc the maskOR_msb */ + maskOR_msb = 0; + maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0; + if ((flags & MP_PRIME_2MSB_ON) != 0) { + maskOR_msb |= (unsigned char)(0x80 >> ((9 - size) & 7)); + } + + /* get the maskOR_lsb */ + maskOR_lsb = 1u; + if ((flags & MP_PRIME_BBS) != 0) { + maskOR_lsb |= 3u; + } + + do { + /* read the bytes */ + if (cb(tmp, bsize, dat) != bsize) { + err = MP_VAL; + goto error; + } + + /* work over the MSbyte */ + tmp[0] &= maskAND; + tmp[0] |= (unsigned char)(1 << ((size - 1) & 7)); + + /* mix in the maskORs */ + tmp[maskOR_msb_offset] |= maskOR_msb; + tmp[bsize-1] |= maskOR_lsb; + + /* read it in */ + /* TODO: casting only for now until all lengths have been changed to the type "size_t"*/ + if ((err = mp_from_ubin(a, tmp, (size_t)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 & MP_PRIME_SAFE) != 0) { + /* see if (a-1)/2 is prime */ + if ((err = mp_sub_d(a, 1uL, 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 & MP_PRIME_SAFE) != 0) { + /* restore a to the original value */ + if ((err = mp_mul_2(a, a)) != MP_OKAY) { + goto error; + } + if ((err = mp_add_d(a, 1uL, a)) != MP_OKAY) { + goto error; + } + } + + err = MP_OKAY; +error: + MP_FREE_BUFFER(tmp, (size_t)bsize); + return err; +} + +static int s_mp_rand_cb(unsigned char *dst, int len, void *dat) +{ + (void)dat; + if (len <= 0) { + return len; + } + if (s_mp_rand_source(dst, (size_t)len) != MP_OKAY) { + return 0; + } + return len; +} + +mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) +{ + return s_mp_prime_random_ex(a, t, size, flags, s_mp_rand_cb, NULL); +} + +#endif + +/* End: bn_mp_prime_rand.c */ + +/* Start: bn_mp_prime_strong_lucas_selfridge.c */ +#include "tommath_private.h" +#ifdef BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * See file bn_mp_prime_is_prime.c or the documentation in doc/bn.tex for the details + */ +#ifndef LTM_USE_ONLY_MR + +/* + * 8-bit is just too small. You can try the Frobenius test + * but that frobenius test can fail, too, for the same reason. + */ +#ifndef MP_8BIT + +/* + * multiply bigint a with int d and put the result in c + * Like mp_mul_d() but with a signed long as the small input + */ +static mp_err s_mp_mul_si(const mp_int *a, int32_t d, mp_int *c) +{ + mp_int t; + mp_err err; + + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } + + /* + * mp_digit might be smaller than a long, which excludes + * the use of mp_mul_d() here. + */ + mp_set_i32(&t, d); + err = mp_mul(a, &t, c); + mp_clear(&t); + return err; +} +/* + Strong Lucas-Selfridge test. + returns MP_YES if it is a strong L-S prime, MP_NO if it is composite + + Code ported from Thomas Ray Nicely's implementation of the BPSW test + at http://www.trnicely.net/misc/bpsw.html + + Freeware copyright (C) 2016 Thomas R. Nicely . + Released into the public domain by the author, who disclaims any legal + liability arising from its use + + The multi-line comments are made by Thomas R. Nicely and are copied verbatim. + Additional comments marked "CZ" (without the quotes) are by the code-portist. + + (If that name sounds familiar, he is the guy who found the fdiv bug in the + Pentium (P5x, I think) Intel processor) +*/ +mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, mp_bool *result) +{ + /* CZ TODO: choose better variable names! */ + mp_int Dz, gcd, Np1, Uz, Vz, U2mz, V2mz, Qmz, Q2mz, Qkdz, T1z, T2z, T3z, T4z, Q2kdz; + /* CZ TODO: Some of them need the full 32 bit, hence the (temporary) exclusion of MP_8BIT */ + int32_t D, Ds, J, sign, P, Q, r, s, u, Nbits; + mp_err err; + mp_bool oddness; + + *result = MP_NO; + /* + Find the first element D in the sequence {5, -7, 9, -11, 13, ...} + such that Jacobi(D,N) = -1 (Selfridge's algorithm). Theory + indicates that, if N is not a perfect square, D will "nearly + always" be "small." Just in case, an overflow trap for D is + included. + */ + + if ((err = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz, + NULL)) != MP_OKAY) { + return err; + } + + D = 5; + sign = 1; + + for (;;) { + Ds = sign * D; + sign = -sign; + mp_set_u32(&Dz, (uint32_t)D); + if ((err = mp_gcd(a, &Dz, &gcd)) != MP_OKAY) goto LBL_LS_ERR; + + /* if 1 < GCD < N then N is composite with factor "D", and + Jacobi(D,N) is technically undefined (but often returned + as zero). */ + if ((mp_cmp_d(&gcd, 1uL) == MP_GT) && (mp_cmp(&gcd, a) == MP_LT)) { + goto LBL_LS_ERR; + } + if (Ds < 0) { + Dz.sign = MP_NEG; + } + if ((err = mp_kronecker(&Dz, a, &J)) != MP_OKAY) goto LBL_LS_ERR; + + if (J == -1) { + break; + } + D += 2; + + if (D > (INT_MAX - 2)) { + err = MP_VAL; + goto LBL_LS_ERR; + } + } + + + + P = 1; /* Selfridge's choice */ + Q = (1 - Ds) / 4; /* Required so D = P*P - 4*Q */ + + /* NOTE: The conditions (a) N does not divide Q, and + (b) D is square-free or not a perfect square, are included by + some authors; e.g., "Prime numbers and computer methods for + factorization," Hans Riesel (2nd ed., 1994, Birkhauser, Boston), + p. 130. For this particular application of Lucas sequences, + these conditions were found to be immaterial. */ + + /* Now calculate N - Jacobi(D,N) = N + 1 (even), and calculate the + odd positive integer d and positive integer s for which + N + 1 = 2^s*d (similar to the step for N - 1 in Miller's test). + The strong Lucas-Selfridge test then returns N as a strong + Lucas probable prime (slprp) if any of the following + conditions is met: U_d=0, V_d=0, V_2d=0, V_4d=0, V_8d=0, + V_16d=0, ..., etc., ending with V_{2^(s-1)*d}=V_{(N+1)/2}=0 + (all equalities mod N). Thus d is the highest index of U that + must be computed (since V_2m is independent of U), compared + to U_{N+1} for the standard Lucas-Selfridge test; and no + index of V beyond (N+1)/2 is required, just as in the + standard Lucas-Selfridge test. However, the quantity Q^d must + be computed for use (if necessary) in the latter stages of + the test. The result is that the strong Lucas-Selfridge test + has a running time only slightly greater (order of 10 %) than + that of the standard Lucas-Selfridge test, while producing + only (roughly) 30 % as many pseudoprimes (and every strong + Lucas pseudoprime is also a standard Lucas pseudoprime). Thus + the evidence indicates that the strong Lucas-Selfridge test is + more effective than the standard Lucas-Selfridge test, and a + Baillie-PSW test based on the strong Lucas-Selfridge test + should be more reliable. */ + + if ((err = mp_add_d(a, 1uL, &Np1)) != MP_OKAY) goto LBL_LS_ERR; + s = mp_cnt_lsb(&Np1); + + /* CZ + * This should round towards zero because + * Thomas R. Nicely used GMP's mpz_tdiv_q_2exp() + * and mp_div_2d() is equivalent. Additionally: + * dividing an even number by two does not produce + * any leftovers. + */ + if ((err = mp_div_2d(&Np1, s, &Dz, NULL)) != MP_OKAY) goto LBL_LS_ERR; + /* We must now compute U_d and V_d. Since d is odd, the accumulated + values U and V are initialized to U_1 and V_1 (if the target + index were even, U and V would be initialized instead to U_0=0 + and V_0=2). The values of U_2m and V_2m are also initialized to + U_1 and V_1; the FOR loop calculates in succession U_2 and V_2, + U_4 and V_4, U_8 and V_8, etc. If the corresponding bits + (1, 2, 3, ...) of t are on (the zero bit having been accounted + for in the initialization of U and V), these values are then + combined with the previous totals for U and V, using the + composition formulas for addition of indices. */ + + mp_set(&Uz, 1uL); /* U=U_1 */ + mp_set(&Vz, (mp_digit)P); /* V=V_1 */ + mp_set(&U2mz, 1uL); /* U_1 */ + mp_set(&V2mz, (mp_digit)P); /* V_1 */ + + mp_set_i32(&Qmz, Q); + if ((err = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) goto LBL_LS_ERR; + /* Initializes calculation of Q^d */ + mp_set_i32(&Qkdz, Q); + + Nbits = mp_count_bits(&Dz); + + for (u = 1; u < Nbits; u++) { /* zero bit off, already accounted for */ + /* Formulas for doubling of indices (carried out mod N). Note that + * the indices denoted as "2m" are actually powers of 2, specifically + * 2^(ul-1) beginning each loop and 2^ul ending each loop. + * + * U_2m = U_m*V_m + * V_2m = V_m*V_m - 2*Q^m + */ + + if ((err = mp_mul(&U2mz, &V2mz, &U2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&U2mz, a, &U2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sqr(&V2mz, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sub(&V2mz, &Q2mz, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&V2mz, a, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + + /* Must calculate powers of Q for use in V_2m, also for Q^d later */ + if ((err = mp_sqr(&Qmz, &Qmz)) != MP_OKAY) goto LBL_LS_ERR; + + /* prevents overflow */ /* CZ still necessary without a fixed prealloc'd mem.? */ + if ((err = mp_mod(&Qmz, a, &Qmz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) goto LBL_LS_ERR; + + if (s_mp_get_bit(&Dz, (unsigned int)u) == MP_YES) { + /* Formulas for addition of indices (carried out mod N); + * + * U_(m+n) = (U_m*V_n + U_n*V_m)/2 + * V_(m+n) = (V_m*V_n + D*U_m*U_n)/2 + * + * Be careful with division by 2 (mod N)! + */ + if ((err = mp_mul(&U2mz, &Vz, &T1z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&Uz, &V2mz, &T2z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&V2mz, &Vz, &T3z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&U2mz, &Uz, &T4z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = s_mp_mul_si(&T4z, Ds, &T4z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_add(&T1z, &T2z, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if (MP_IS_ODD(&Uz)) { + if ((err = mp_add(&Uz, a, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + } + /* CZ + * This should round towards negative infinity because + * Thomas R. Nicely used GMP's mpz_fdiv_q_2exp(). + * But mp_div_2() does not do so, it is truncating instead. + */ + oddness = MP_IS_ODD(&Uz) ? MP_YES : MP_NO; + if ((err = mp_div_2(&Uz, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if ((Uz.sign == MP_NEG) && (oddness != MP_NO)) { + if ((err = mp_sub_d(&Uz, 1uL, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + } + if ((err = mp_add(&T3z, &T4z, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if (MP_IS_ODD(&Vz)) { + if ((err = mp_add(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + } + oddness = MP_IS_ODD(&Vz) ? MP_YES : MP_NO; + if ((err = mp_div_2(&Vz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if ((Vz.sign == MP_NEG) && (oddness != MP_NO)) { + if ((err = mp_sub_d(&Vz, 1uL, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + } + if ((err = mp_mod(&Uz, a, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + + /* Calculating Q^d for later use */ + if ((err = mp_mul(&Qkdz, &Qmz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + } + } + + /* If U_d or V_d is congruent to 0 mod N, then N is a prime or a + strong Lucas pseudoprime. */ + if (MP_IS_ZERO(&Uz) || MP_IS_ZERO(&Vz)) { + *result = MP_YES; + goto LBL_LS_ERR; + } + + /* NOTE: Ribenboim ("The new book of prime number records," 3rd ed., + 1995/6) omits the condition V0 on p.142, but includes it on + p. 130. The condition is NECESSARY; otherwise the test will + return false negatives---e.g., the primes 29 and 2000029 will be + returned as composite. */ + + /* Otherwise, we must compute V_2d, V_4d, V_8d, ..., V_{2^(s-1)*d} + by repeated use of the formula V_2m = V_m*V_m - 2*Q^m. If any of + these are congruent to 0 mod N, then N is a prime or a strong + Lucas pseudoprime. */ + + /* Initialize 2*Q^(d*2^r) for V_2m */ + if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR; + + for (r = 1; r < s; r++) { + if ((err = mp_sqr(&Vz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sub(&Vz, &Q2kdz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if (MP_IS_ZERO(&Vz)) { + *result = MP_YES; + goto LBL_LS_ERR; + } + /* Calculate Q^{d*2^r} for next r (final iteration irrelevant). */ + if (r < (s - 1)) { + if ((err = mp_sqr(&Qkdz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR; + } + } +LBL_LS_ERR: + mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, NULL); + return err; +} +#endif +#endif +#endif + +/* End: bn_mp_prime_strong_lucas_selfridge.c */ + +/* Start: bn_mp_radix_size.c */ +#include "tommath_private.h" +#ifdef BN_MP_RADIX_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* returns size of ASCII representation */ +mp_err mp_radix_size(const mp_int *a, int radix, int *size) +{ + mp_err err; + int digs; + mp_int t; + mp_digit d; + + *size = 0; + + /* make sure the radix is in range */ + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + if (MP_IS_ZERO(a)) { + *size = 2; + return MP_OKAY; + } + + /* special case for binary */ + if (radix == 2) { + *size = (mp_count_bits(a) + ((a->sign == MP_NEG) ? 1 : 0) + 1); + 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 ((err = mp_init_copy(&t, a)) != MP_OKAY) { + return err; + } + + /* force temp to positive */ + t.sign = MP_ZPOS; + + /* fetch out all of the digits */ + while (!MP_IS_ZERO(&t)) { + if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) { + goto LBL_ERR; + } + ++digs; + } + + /* return digs + 1, the 1 is for the NULL byte that would be required. */ + *size = digs + 1; + err = MP_OKAY; + +LBL_ERR: + mp_clear(&t); + return err; +} + +#endif + +/* End: bn_mp_radix_size.c */ + +/* Start: bn_mp_radix_smap.c */ +#include "tommath_private.h" +#ifdef BN_MP_RADIX_SMAP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* chars used in radix conversions */ +const char *const mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +const uint8_t mp_s_rmap_reverse[] = { + 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, /* ()*+,-./ */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ + 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */ + 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, /* @ABCDEFG */ + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, /* HIJKLMNO */ + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, /* PQRSTUVW */ + 0x21, 0x22, 0x23, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */ + 0xff, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, /* `abcdefg */ + 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, /* hijklmno */ + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, /* pqrstuvw */ + 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, /* xyz{|}~. */ +}; +const size_t mp_s_rmap_reverse_sz = sizeof(mp_s_rmap_reverse); +#endif + +/* End: bn_mp_radix_smap.c */ + +/* Start: bn_mp_rand.c */ +#include "tommath_private.h" +#ifdef BN_MP_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err(*s_mp_rand_source)(void *out, size_t size) = s_mp_rand_platform; + +void mp_rand_source(mp_err(*source)(void *out, size_t size)) +{ + s_mp_rand_source = (source == NULL) ? s_mp_rand_platform : source; +} + +mp_err mp_rand(mp_int *a, int digits) +{ + int i; + mp_err err; + + mp_zero(a); + + if (digits <= 0) { + return MP_OKAY; + } + + if ((err = mp_grow(a, digits)) != MP_OKAY) { + return err; + } + + if ((err = s_mp_rand_source(a->dp, (size_t)digits * sizeof(mp_digit))) != MP_OKAY) { + return err; + } + + /* TODO: We ensure that the highest digit is nonzero. Should this be removed? */ + while ((a->dp[digits - 1] & MP_MASK) == 0u) { + if ((err = s_mp_rand_source(a->dp + digits - 1, sizeof(mp_digit))) != MP_OKAY) { + return err; + } + } + + a->used = digits; + for (i = 0; i < digits; ++i) { + a->dp[i] &= MP_MASK; + } + + return MP_OKAY; +} +#endif + +/* End: bn_mp_rand.c */ + +/* Start: bn_mp_read_radix.c */ +#include "tommath_private.h" +#ifdef BN_MP_READ_RADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define MP_TOUPPER(c) ((((c) >= 'a') && ((c) <= 'z')) ? (((c) + 'A') - 'a') : (c)) + +/* read a string [ASCII] in a given radix */ +mp_err mp_read_radix(mp_int *a, const char *str, int radix) +{ + mp_err err; + int y; + mp_sign neg; + unsigned pos; + 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 != '\0') { + /* 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 = (radix <= 36) ? (char)MP_TOUPPER((int)*str) : *str; + pos = (unsigned)(ch - '('); + if (mp_s_rmap_reverse_sz < pos) { + break; + } + y = (int)mp_s_rmap_reverse[pos]; + + /* 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 == 0xff) || (y >= radix)) { + break; + } + if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) { + return err; + } + ++str; + } + + /* if an illegal character was found, fail. */ + if (!((*str == '\0') || (*str == '\r') || (*str == '\n'))) { + mp_zero(a); + return MP_VAL; + } + + /* set the sign only if a != 0 */ + if (!MP_IS_ZERO(a)) { + a->sign = neg; + } + return MP_OKAY; +} +#endif + +/* End: bn_mp_read_radix.c */ + +/* Start: bn_mp_reduce.c */ +#include "tommath_private.h" +#ifdef BN_MP_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reduces x mod m, assumes 0 < x < m**2, mu is + * precomputed via mp_reduce_setup. + * From HAC pp.604 Algorithm 14.42 + */ +mp_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu) +{ + mp_int q; + mp_err err; + int um = m->used; + + /* q = x */ + if ((err = mp_init_copy(&q, x)) != MP_OKAY) { + return err; + } + + /* q1 = x / b**(k-1) */ + mp_rshd(&q, um - 1); + + /* according to HAC this optimization is ok */ + if ((mp_digit)um > ((mp_digit)1 << (MP_DIGIT_BIT - 1))) { + if ((err = mp_mul(&q, mu, &q)) != MP_OKAY) { + goto CLEANUP; + } + } else if (MP_HAS(S_MP_MUL_HIGH_DIGS)) { + if ((err = s_mp_mul_high_digs(&q, mu, &q, um)) != MP_OKAY) { + goto CLEANUP; + } + } else if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST)) { + if ((err = s_mp_mul_high_digs_fast(&q, mu, &q, um)) != MP_OKAY) { + goto CLEANUP; + } + } else { + err = MP_VAL; + goto CLEANUP; + } + + /* q3 = q2 / b**(k+1) */ + mp_rshd(&q, um + 1); + + /* x = x mod b**(k+1), quick (no division) */ + if ((err = mp_mod_2d(x, MP_DIGIT_BIT * (um + 1), x)) != MP_OKAY) { + goto CLEANUP; + } + + /* q = q * m mod b**(k+1), quick (no division) */ + if ((err = s_mp_mul_digs(&q, m, &q, um + 1)) != MP_OKAY) { + goto CLEANUP; + } + + /* x = x - q */ + if ((err = mp_sub(x, &q, x)) != MP_OKAY) { + goto CLEANUP; + } + + /* If x < 0, add b**(k+1) to it */ + if (mp_cmp_d(x, 0uL) == MP_LT) { + mp_set(&q, 1uL); + if ((err = mp_lshd(&q, um + 1)) != MP_OKAY) { + goto CLEANUP; + } + if ((err = mp_add(x, &q, x)) != MP_OKAY) { + goto CLEANUP; + } + } + + /* Back off if it's too big */ + while (mp_cmp(x, m) != MP_LT) { + if ((err = s_mp_sub(x, m, x)) != MP_OKAY) { + goto CLEANUP; + } + } + +CLEANUP: + mp_clear(&q); + + return err; +} +#endif + +/* End: bn_mp_reduce.c */ + +/* Start: bn_mp_reduce_2k.c */ +#include "tommath_private.h" +#ifdef BN_MP_REDUCE_2K_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reduces a modulo n where n is of the form 2**p - d */ +mp_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d) +{ + mp_int q; + mp_err err; + int p; + + if ((err = mp_init(&q)) != MP_OKAY) { + return err; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((err = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + if (d != 1u) { + /* q = q * d */ + if ((err = mp_mul_d(&q, d, &q)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* a = a + q */ + if ((err = s_mp_add(a, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + if ((err = s_mp_sub(a, n, a)) != MP_OKAY) { + goto LBL_ERR; + } + goto top; + } + +LBL_ERR: + mp_clear(&q); + return err; +} + +#endif + +/* End: bn_mp_reduce_2k.c */ + +/* Start: bn_mp_reduce_2k_l.c */ +#include "tommath_private.h" +#ifdef BN_MP_REDUCE_2K_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. +*/ +mp_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d) +{ + mp_int q; + mp_err err; + int p; + + if ((err = mp_init(&q)) != MP_OKAY) { + return err; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((err = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + /* q = q * d */ + if ((err = mp_mul(&q, d, &q)) != MP_OKAY) { + goto LBL_ERR; + } + + /* a = a + q */ + if ((err = s_mp_add(a, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + if ((err = s_mp_sub(a, n, a)) != MP_OKAY) { + goto LBL_ERR; + } + goto top; + } + +LBL_ERR: + mp_clear(&q); + return err; +} + +#endif + +/* End: bn_mp_reduce_2k_l.c */ + +/* Start: bn_mp_reduce_2k_setup.c */ +#include "tommath_private.h" +#ifdef BN_MP_REDUCE_2K_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines the setup value */ +mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d) +{ + mp_err err; + mp_int tmp; + int p; + + if ((err = mp_init(&tmp)) != MP_OKAY) { + return err; + } + + p = mp_count_bits(a); + if ((err = mp_2expt(&tmp, p)) != MP_OKAY) { + mp_clear(&tmp); + return err; + } + + if ((err = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + mp_clear(&tmp); + return err; + } + + *d = tmp.dp[0]; + mp_clear(&tmp); + return MP_OKAY; +} +#endif + +/* End: bn_mp_reduce_2k_setup.c */ + +/* Start: bn_mp_reduce_2k_setup_l.c */ +#include "tommath_private.h" +#ifdef BN_MP_REDUCE_2K_SETUP_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines the setup value */ +mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d) +{ + mp_err err; + mp_int tmp; + + if ((err = mp_init(&tmp)) != MP_OKAY) { + return err; + } + + if ((err = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = s_mp_sub(&tmp, a, d)) != MP_OKAY) { + goto LBL_ERR; + } + +LBL_ERR: + mp_clear(&tmp); + return err; +} +#endif + +/* End: bn_mp_reduce_2k_setup_l.c */ + +/* Start: bn_mp_reduce_is_2k.c */ +#include "tommath_private.h" +#ifdef BN_MP_REDUCE_IS_2K_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if mp_reduce_2k can be used */ +mp_bool mp_reduce_is_2k(const 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 = MP_DIGIT_BIT; ix < iy; ix++) { + if ((a->dp[iw] & iz) == 0u) { + return MP_NO; + } + iz <<= 1; + if (iz > MP_DIGIT_MAX) { + ++iw; + iz = 1; + } + } + return MP_YES; + } else { + return MP_YES; + } +} + +#endif + +/* End: bn_mp_reduce_is_2k.c */ + +/* Start: bn_mp_reduce_is_2k_l.c */ +#include "tommath_private.h" +#ifdef BN_MP_REDUCE_IS_2K_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if reduce_2k_l can be used */ +mp_bool mp_reduce_is_2k_l(const 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_DIGIT_MAX) { + ++iy; + } + } + return (iy >= (a->used/2)) ? MP_YES : MP_NO; + } else { + return MP_NO; + } +} + +#endif + +/* End: bn_mp_reduce_is_2k_l.c */ + +/* Start: bn_mp_reduce_setup.c */ +#include "tommath_private.h" +#ifdef BN_MP_REDUCE_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* pre-calculate the value required for Barrett reduction + * For a given modulus "b" it calulates the value required in "a" + */ +mp_err mp_reduce_setup(mp_int *a, const mp_int *b) +{ + mp_err err; + if ((err = mp_2expt(a, b->used * 2 * MP_DIGIT_BIT)) != MP_OKAY) { + return err; + } + return mp_div(a, b, a, NULL); +} +#endif + +/* End: bn_mp_reduce_setup.c */ + +/* Start: bn_mp_root_u32.c */ +#include "tommath_private.h" +#ifdef BN_MP_ROOT_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. + */ +mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c) +{ + mp_int t1, t2, t3, a_; + mp_ord cmp; + int ilog2; + mp_err err; + + /* input must be positive if b is even */ + if (((b & 1u) == 0u) && (a->sign == MP_NEG)) { + return MP_VAL; + } + + if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) { + return err; + } + + /* if a is negative fudge the sign but keep track */ + a_ = *a; + a_.sign = MP_ZPOS; + + /* Compute seed: 2^(log_2(n)/b + 2)*/ + ilog2 = mp_count_bits(a); + + /* + If "b" is larger than INT_MAX it is also larger than + log_2(n) because the bit-length of the "n" is measured + with an int and hence the root is always < 2 (two). + */ + if (b > (uint32_t)(INT_MAX/2)) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + + /* "b" is smaller than INT_MAX, we can cast safely */ + if (ilog2 < (int)b) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + ilog2 = ilog2 / ((int)b); + if (ilog2 == 0) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + /* Start value must be larger than root */ + ilog2 += 2; + if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY) goto LBL_ERR; + do { + /* t1 = t2 */ + if ((err = mp_copy(&t2, &t1)) != MP_OKAY) goto LBL_ERR; + + /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ + + /* t3 = t1**(b-1) */ + if ((err = mp_expt_u32(&t1, b - 1u, &t3)) != MP_OKAY) goto LBL_ERR; + + /* numerator */ + /* t2 = t1**b */ + if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY) goto LBL_ERR; + + /* t2 = t1**b - a */ + if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY) goto LBL_ERR; + + /* denominator */ + /* t3 = t1**(b-1) * b */ + if ((err = mp_mul_d(&t3, b, &t3)) != MP_OKAY) goto LBL_ERR; + + /* t3 = (t1**b - a)/(b * t1**(b-1)) */ + if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY) goto LBL_ERR; + + /* + Number of rounds is at most log_2(root). If it is more it + got stuck, so break out of the loop and do the rest manually. + */ + if (ilog2-- == 0) { + break; + } + } while (mp_cmp(&t1, &t2) != MP_EQ); + + /* result can be off by a few so check */ + /* Loop beneath can overshoot by one if found root is smaller than actual root */ + for (;;) { + if ((err = mp_expt_u32(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; + cmp = mp_cmp(&t2, &a_); + if (cmp == MP_EQ) { + err = MP_OKAY; + goto LBL_ERR; + } + if (cmp == MP_LT) { + if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; + } else { + break; + } + } + /* correct overshoot from above or from recurrence */ + for (;;) { + if ((err = mp_expt_u32(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; + if (mp_cmp(&t2, &a_) == MP_GT) { + if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; + } else { + break; + } + } + + /* set the result */ + mp_exch(&t1, c); + + /* set the sign of the result */ + c->sign = a->sign; + + err = MP_OKAY; + +LBL_ERR: + mp_clear_multi(&t1, &t2, &t3, NULL); + return err; +} + +#endif + +/* End: bn_mp_root_u32.c */ + +/* Start: bn_mp_rshd.c */ +#include "tommath_private.h" +#ifdef BN_MP_RSHD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift right a certain amount of digits */ +void mp_rshd(mp_int *a, int b) +{ + int x; + mp_digit *bottom, *top; + + /* 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; + } + + /* 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 */ + MP_ZERO_DIGITS(bottom, a->used - x); + + /* remove excess digits */ + a->used -= b; +} +#endif + +/* End: bn_mp_rshd.c */ + +/* Start: bn_mp_sbin_size.c */ +#include "tommath_private.h" +#ifdef BN_MP_SBIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* get the size for an signed equivalent */ +size_t mp_sbin_size(const mp_int *a) +{ + return 1u + mp_ubin_size(a); +} +#endif + +/* End: bn_mp_sbin_size.c */ + +/* Start: bn_mp_set.c */ +#include "tommath_private.h" +#ifdef BN_MP_SET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* set to a digit */ +void mp_set(mp_int *a, mp_digit b) +{ + a->dp[0] = b & MP_MASK; + a->sign = MP_ZPOS; + a->used = (a->dp[0] != 0u) ? 1 : 0; + MP_ZERO_DIGITS(a->dp + a->used, a->alloc - a->used); +} +#endif + +/* End: bn_mp_set.c */ + +/* Start: bn_mp_set_double.c */ +#include "tommath_private.h" +#ifdef BN_MP_SET_DOUBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) +mp_err mp_set_double(mp_int *a, double b) +{ + uint64_t frac; + int exp; + mp_err err; + union { + double dbl; + uint64_t bits; + } cast; + cast.dbl = b; + + exp = (int)((unsigned)(cast.bits >> 52) & 0x7FFu); + frac = (cast.bits & ((1uLL << 52) - 1uLL)) | (1uLL << 52); + + if (exp == 0x7FF) { /* +-inf, NaN */ + return MP_VAL; + } + exp -= 1023 + 52; + + mp_set_u64(a, frac); + + err = (exp < 0) ? mp_div_2d(a, -exp, a, NULL) : mp_mul_2d(a, exp, a); + if (err != MP_OKAY) { + return err; + } + + if (((cast.bits >> 63) != 0uLL) && !MP_IS_ZERO(a)) { + a->sign = MP_NEG; + } + + return MP_OKAY; +} +#else +/* pragma message() not supported by several compilers (in mostly older but still used versions) */ +# ifdef _MSC_VER +# pragma message("mp_set_double implementation is only available on platforms with IEEE754 floating point format") +# else +# warning "mp_set_double implementation is only available on platforms with IEEE754 floating point format" +# endif +#endif +#endif + +/* End: bn_mp_set_double.c */ + +/* Start: bn_mp_set_i32.c */ +#include "tommath_private.h" +#ifdef BN_MP_SET_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_i32, mp_set_u32, int32_t, uint32_t) +#endif + +/* End: bn_mp_set_i32.c */ + +/* Start: bn_mp_set_i64.c */ +#include "tommath_private.h" +#ifdef BN_MP_SET_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_i64, mp_set_u64, int64_t, uint64_t) +#endif + +/* End: bn_mp_set_i64.c */ + +/* Start: bn_mp_set_l.c */ +#include "tommath_private.h" +#ifdef BN_MP_SET_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_l, mp_set_ul, long, unsigned long) +#endif + +/* End: bn_mp_set_l.c */ + +/* Start: bn_mp_set_ll.c */ +#include "tommath_private.h" +#ifdef BN_MP_SET_LL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_ll, mp_set_ull, long long, unsigned long long) +#endif + +/* End: bn_mp_set_ll.c */ + +/* Start: bn_mp_set_u32.c */ +#include "tommath_private.h" +#ifdef BN_MP_SET_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_u32, uint32_t) +#endif + +/* End: bn_mp_set_u32.c */ + +/* Start: bn_mp_set_u64.c */ +#include "tommath_private.h" +#ifdef BN_MP_SET_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_u64, uint64_t) +#endif + +/* End: bn_mp_set_u64.c */ + +/* Start: bn_mp_set_ul.c */ +#include "tommath_private.h" +#ifdef BN_MP_SET_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_ul, unsigned long) +#endif + +/* End: bn_mp_set_ul.c */ + +/* Start: bn_mp_set_ull.c */ +#include "tommath_private.h" +#ifdef BN_MP_SET_ULL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_ull, unsigned long long) +#endif + +/* End: bn_mp_set_ull.c */ + +/* Start: bn_mp_shrink.c */ +#include "tommath_private.h" +#ifdef BN_MP_SHRINK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shrink a bignum */ +mp_err mp_shrink(mp_int *a) +{ + mp_digit *tmp; + int alloc = MP_MAX(MP_MIN_PREC, a->used); + if (a->alloc != alloc) { + if ((tmp = (mp_digit *) MP_REALLOC(a->dp, + (size_t)a->alloc * sizeof(mp_digit), + (size_t)alloc * sizeof(mp_digit))) == NULL) { + return MP_MEM; + } + a->dp = tmp; + a->alloc = alloc; + } + return MP_OKAY; +} +#endif + +/* End: bn_mp_shrink.c */ + +/* Start: bn_mp_signed_rsh.c */ +#include "tommath_private.h" +#ifdef BN_MP_SIGNED_RSH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift right by a certain bit count with sign extension */ +mp_err mp_signed_rsh(const mp_int *a, int b, mp_int *c) +{ + mp_err res; + if (a->sign == MP_ZPOS) { + return mp_div_2d(a, b, c, NULL); + } + + res = mp_add_d(a, 1uL, c); + if (res != MP_OKAY) { + return res; + } + + res = mp_div_2d(c, b, c, NULL); + return (res == MP_OKAY) ? mp_sub_d(c, 1uL, c) : res; +} +#endif + +/* End: bn_mp_signed_rsh.c */ + +/* Start: bn_mp_sqr.c */ +#include "tommath_private.h" +#ifdef BN_MP_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes b = a*a */ +mp_err mp_sqr(const mp_int *a, mp_int *b) +{ + mp_err err; + if (MP_HAS(S_MP_TOOM_SQR) && /* use Toom-Cook? */ + (a->used >= MP_TOOM_SQR_CUTOFF)) { + err = s_mp_toom_sqr(a, b); + } else if (MP_HAS(S_MP_KARATSUBA_SQR) && /* Karatsuba? */ + (a->used >= MP_KARATSUBA_SQR_CUTOFF)) { + err = s_mp_karatsuba_sqr(a, b); + } else if (MP_HAS(S_MP_SQR_FAST) && /* can we use the fast comba multiplier? */ + (((a->used * 2) + 1) < MP_WARRAY) && + (a->used < (MP_MAXFAST / 2))) { + err = s_mp_sqr_fast(a, b); + } else if (MP_HAS(S_MP_SQR)) { + err = s_mp_sqr(a, b); + } else { + err = MP_VAL; + } + b->sign = MP_ZPOS; + return err; +} +#endif + +/* End: bn_mp_sqr.c */ + +/* Start: bn_mp_sqrmod.c */ +#include "tommath_private.h" +#ifdef BN_MP_SQRMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* c = a * a (mod b) */ +mp_err mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + mp_int t; + + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } + + if ((err = mp_sqr(a, &t)) != MP_OKAY) { + goto LBL_ERR; + } + err = mp_mod(&t, b, c); + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif + +/* End: bn_mp_sqrmod.c */ + +/* Start: bn_mp_sqrt.c */ +#include "tommath_private.h" +#ifdef BN_MP_SQRT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* this function is less generic than mp_n_root, simpler and faster */ +mp_err mp_sqrt(const mp_int *arg, mp_int *ret) +{ + mp_err err; + mp_int t1, t2; + + /* must be positive */ + if (arg->sign == MP_NEG) { + return MP_VAL; + } + + /* easy out */ + if (MP_IS_ZERO(arg)) { + mp_zero(ret); + return MP_OKAY; + } + + if ((err = mp_init_copy(&t1, arg)) != MP_OKAY) { + return err; + } + + if ((err = mp_init(&t2)) != MP_OKAY) { + goto E2; + } + + /* First approx. (not very bad for large arg) */ + mp_rshd(&t1, t1.used/2); + + /* t1 > 0 */ + if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { + goto E1; + } + if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { + goto E1; + } + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) { + goto E1; + } + /* And now t1 > sqrt(arg) */ + do { + if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { + goto E1; + } + if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { + goto E1; + } + if ((err = 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 err; +} + +#endif + +/* End: bn_mp_sqrt.c */ + +/* Start: bn_mp_sqrtmod_prime.c */ +#include "tommath_private.h" +#ifdef BN_MP_SQRTMOD_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Tonelli-Shanks algorithm + * https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm + * https://gmplib.org/list-archives/gmp-discuss/2013-April/005300.html + * + */ + +mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) +{ + mp_err err; + int legendre; + mp_int t1, C, Q, S, Z, M, T, R, two; + mp_digit i; + + /* first handle the simple cases */ + if (mp_cmp_d(n, 0uL) == MP_EQ) { + mp_zero(ret); + return MP_OKAY; + } + if (mp_cmp_d(prime, 2uL) == MP_EQ) return MP_VAL; /* prime must be odd */ + if ((err = mp_kronecker(n, prime, &legendre)) != MP_OKAY) return err; + if (legendre == -1) return MP_VAL; /* quadratic non-residue mod prime */ + + if ((err = mp_init_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL)) != MP_OKAY) { + return err; + } + + /* SPECIAL CASE: if prime mod 4 == 3 + * compute directly: err = n^(prime+1)/4 mod prime + * Handbook of Applied Cryptography algorithm 3.36 + */ + if ((err = mp_mod_d(prime, 4uL, &i)) != MP_OKAY) goto cleanup; + if (i == 3u) { + if ((err = mp_add_d(prime, 1uL, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_exptmod(n, &t1, prime, ret)) != MP_OKAY) goto cleanup; + err = MP_OKAY; + goto cleanup; + } + + /* NOW: Tonelli-Shanks algorithm */ + + /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */ + if ((err = mp_copy(prime, &Q)) != MP_OKAY) goto cleanup; + if ((err = mp_sub_d(&Q, 1uL, &Q)) != MP_OKAY) goto cleanup; + /* Q = prime - 1 */ + mp_zero(&S); + /* S = 0 */ + while (MP_IS_EVEN(&Q)) { + if ((err = mp_div_2(&Q, &Q)) != MP_OKAY) goto cleanup; + /* Q = Q / 2 */ + if ((err = mp_add_d(&S, 1uL, &S)) != MP_OKAY) goto cleanup; + /* S = S + 1 */ + } + + /* find a Z such that the Legendre symbol (Z|prime) == -1 */ + mp_set_u32(&Z, 2u); + /* Z = 2 */ + for (;;) { + if ((err = mp_kronecker(&Z, prime, &legendre)) != MP_OKAY) goto cleanup; + if (legendre == -1) break; + if ((err = mp_add_d(&Z, 1uL, &Z)) != MP_OKAY) goto cleanup; + /* Z = Z + 1 */ + } + + if ((err = mp_exptmod(&Z, &Q, prime, &C)) != MP_OKAY) goto cleanup; + /* C = Z ^ Q mod prime */ + if ((err = mp_add_d(&Q, 1uL, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto cleanup; + /* t1 = (Q + 1) / 2 */ + if ((err = mp_exptmod(n, &t1, prime, &R)) != MP_OKAY) goto cleanup; + /* R = n ^ ((Q + 1) / 2) mod prime */ + if ((err = mp_exptmod(n, &Q, prime, &T)) != MP_OKAY) goto cleanup; + /* T = n ^ Q mod prime */ + if ((err = mp_copy(&S, &M)) != MP_OKAY) goto cleanup; + /* M = S */ + mp_set_u32(&two, 2u); + + for (;;) { + if ((err = mp_copy(&T, &t1)) != MP_OKAY) goto cleanup; + i = 0; + for (;;) { + if (mp_cmp_d(&t1, 1uL) == MP_EQ) break; + if ((err = mp_exptmod(&t1, &two, prime, &t1)) != MP_OKAY) goto cleanup; + i++; + } + if (i == 0u) { + if ((err = mp_copy(&R, ret)) != MP_OKAY) goto cleanup; + err = MP_OKAY; + goto cleanup; + } + if ((err = mp_sub_d(&M, i, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto cleanup; + if ((err = mp_exptmod(&two, &t1, prime, &t1)) != MP_OKAY) goto cleanup; + /* t1 = 2 ^ (M - i - 1) */ + if ((err = mp_exptmod(&C, &t1, prime, &t1)) != MP_OKAY) goto cleanup; + /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ + if ((err = mp_sqrmod(&t1, prime, &C)) != MP_OKAY) goto cleanup; + /* C = (t1 * t1) mod prime */ + if ((err = mp_mulmod(&R, &t1, prime, &R)) != MP_OKAY) goto cleanup; + /* R = (R * t1) mod prime */ + if ((err = mp_mulmod(&T, &C, prime, &T)) != MP_OKAY) goto cleanup; + /* T = (T * C) mod prime */ + mp_set(&M, i); + /* M = i */ + } + +cleanup: + mp_clear_multi(&t1, &C, &Q, &S, &Z, &M, &T, &R, &two, NULL); + return err; +} + +#endif + +/* End: bn_mp_sqrtmod_prime.c */ + +/* Start: bn_mp_sub.c */ +#include "tommath_private.h" +#ifdef BN_MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* high level subtraction (handles signs) */ +mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_sign sa = a->sign, sb = b->sign; + mp_err err; + + 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; + err = 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 */ + err = 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 */ + err = s_mp_sub(b, a, c); + } + } + return err; +} + +#endif + +/* End: bn_mp_sub.c */ + +/* Start: bn_mp_sub_d.c */ +#include "tommath_private.h" +#ifdef BN_MP_SUB_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single digit subtraction */ +mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c) +{ + mp_digit *tmpa, *tmpc; + mp_err err; + int ix, oldused; + + /* grow c as required */ + if (c->alloc < (a->used + 1)) { + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + } + + /* if a is negative just do an unsigned + * addition [with fudged signs] + */ + if (a->sign == MP_NEG) { + mp_int a_ = *a; + a_.sign = MP_ZPOS; + err = mp_add_d(&a_, b, c); + c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return err; + } + + /* 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 { + mp_digit mu = b; + + /* positive/size */ + c->sign = MP_ZPOS; + c->used = a->used; + + /* subtract digits, mu is carry */ + for (ix = 0; ix < a->used; ix++) { + *tmpc = *tmpa++ - mu; + mu = *tmpc >> (MP_SIZEOF_BITS(mp_digit) - 1u); + *tmpc++ &= MP_MASK; + } + } + + /* zero excess digits */ + MP_ZERO_DIGITS(tmpc, oldused - ix); + + mp_clamp(c); + return MP_OKAY; +} + +#endif + +/* End: bn_mp_sub_d.c */ + +/* Start: bn_mp_submod.c */ +#include "tommath_private.h" +#ifdef BN_MP_SUBMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* d = a - b (mod c) */ +mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) +{ + mp_err err; + mp_int t; + + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } + + if ((err = mp_sub(a, b, &t)) != MP_OKAY) { + goto LBL_ERR; + } + err = mp_mod(&t, c, d); + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif + +/* End: bn_mp_submod.c */ + +/* Start: bn_mp_to_radix.c */ +#include "tommath_private.h" +#ifdef BN_MP_TO_RADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* stores a bignum as a ASCII string in a given radix (2..64) + * + * Stores upto "size - 1" chars and always a NULL byte, puts the number of characters + * written, including the '\0', in "written". + */ +mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) +{ + size_t digs; + mp_err err; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of radix and size*/ + if (maxlen < 2u) { + return MP_BUF; + } + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + /* quick out if its zero */ + if (MP_IS_ZERO(a)) { + *str++ = '0'; + *str = '\0'; + if (written != NULL) { + *written = 2u; + } + return MP_OKAY; + } + + if ((err = mp_init_copy(&t, a)) != MP_OKAY) { + return err; + } + + /* 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 = 0u; + while (!MP_IS_ZERO(&t)) { + if (--maxlen < 1u) { + /* no more room */ + err = MP_BUF; + goto LBL_ERR; + } + if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) { + goto LBL_ERR; + } + *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 + */ + s_mp_reverse((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + digs++; + + if (written != NULL) { + *written = (a->sign == MP_NEG) ? (digs + 1u): digs; + } + +LBL_ERR: + mp_clear(&t); + return err; +} + +#endif + +/* End: bn_mp_to_radix.c */ + +/* Start: bn_mp_to_sbin.c */ +#include "tommath_private.h" +#ifdef BN_MP_TO_SBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* store in signed [big endian] format */ +mp_err mp_to_sbin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) +{ + mp_err err; + if (maxlen == 0u) { + return MP_BUF; + } + if ((err = mp_to_ubin(a, buf + 1, maxlen - 1u, written)) != MP_OKAY) { + return err; + } + if (written != NULL) { + (*written)++; + } + buf[0] = (a->sign == MP_ZPOS) ? (unsigned char)0 : (unsigned char)1; + return MP_OKAY; +} +#endif + +/* End: bn_mp_to_sbin.c */ + +/* Start: bn_mp_to_ubin.c */ +#include "tommath_private.h" +#ifdef BN_MP_TO_UBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* store in unsigned [big endian] format */ +mp_err mp_to_ubin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) +{ + size_t x, count; + mp_err err; + mp_int t; + + count = mp_ubin_size(a); + if (count > maxlen) { + return MP_BUF; + } + + if ((err = mp_init_copy(&t, a)) != MP_OKAY) { + return err; + } + + for (x = count; x --> 0u;) { +#ifndef MP_8BIT + buf[x] = (unsigned char)(t.dp[0] & 255u); +#else + buf[x] = (unsigned char)(t.dp[0] | ((t.dp[1] & 1u) << 7)); +#endif + if ((err = mp_div_2d(&t, 8, &t, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + } + + if (written != NULL) { + *written = count; + } + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif + +/* End: bn_mp_to_ubin.c */ + +/* Start: bn_mp_ubin_size.c */ +#include "tommath_private.h" +#ifdef BN_MP_UBIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* get the size for an unsigned equivalent */ +size_t mp_ubin_size(const mp_int *a) +{ + size_t size = (size_t)mp_count_bits(a); + return (size / 8u) + (((size & 7u) != 0u) ? 1u : 0u); +} +#endif + +/* End: bn_mp_ubin_size.c */ + +/* Start: bn_mp_unpack.c */ +#include "tommath_private.h" +#ifdef BN_MP_UNPACK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on gmp's mpz_import. + * see http://gmplib.org/manual/Integer-Import-and-Export.html + */ +mp_err mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size, + mp_endian endian, size_t nails, const void *op) +{ + mp_err err; + size_t odd_nails, nail_bytes, i, j; + unsigned char odd_nail_mask; + + mp_zero(rop); + + if (endian == MP_NATIVE_ENDIAN) { + MP_GET_ENDIANNESS(endian); + } + + odd_nails = (nails % 8u); + odd_nail_mask = 0xff; + for (i = 0; i < odd_nails; ++i) { + odd_nail_mask ^= (unsigned char)(1u << (7u - i)); + } + nail_bytes = nails / 8u; + + for (i = 0; i < count; ++i) { + for (j = 0; j < (size - nail_bytes); ++j) { + unsigned char byte = *((const unsigned char *)op + + (((order == MP_MSB_FIRST) ? i : ((count - 1u) - i)) * size) + + ((endian == MP_BIG_ENDIAN) ? (j + nail_bytes) : (((size - 1u) - j) - nail_bytes))); + + if ((err = mp_mul_2d(rop, (j == 0u) ? (int)(8u - odd_nails) : 8, rop)) != MP_OKAY) { + return err; + } + + rop->dp[0] |= (j == 0u) ? (mp_digit)(byte & odd_nail_mask) : (mp_digit)byte; + rop->used += 1; + } + } + + mp_clamp(rop); + + return MP_OKAY; +} + +#endif + +/* End: bn_mp_unpack.c */ + +/* Start: bn_mp_xor.c */ +#include "tommath_private.h" +#ifdef BN_MP_XOR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* two complement xor */ +mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c) +{ + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + mp_sign csign = (a->sign != b->sign) ? MP_NEG : MP_ZPOS; + + if (c->alloc < used) { + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + } + + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (a->sign == MP_NEG) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (b->sign == MP_NEG) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x ^ y; + + /* convert to to sign-magnitude if negative */ + if (csign == MP_NEG) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = csign; + mp_clamp(c); + return MP_OKAY; +} +#endif + +/* End: bn_mp_xor.c */ + +/* Start: bn_mp_zero.c */ +#include "tommath_private.h" +#ifdef BN_MP_ZERO_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* set to zero */ +void mp_zero(mp_int *a) +{ + a->sign = MP_ZPOS; + a->used = 0; + MP_ZERO_DIGITS(a->dp, a->alloc); +} +#endif + +/* End: bn_mp_zero.c */ + +/* Start: bn_prime_tab.c */ +#include "tommath_private.h" +#ifdef BN_PRIME_TAB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +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 +}; + +#if defined(__GNUC__) && __GNUC__ >= 4 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +const mp_digit *s_mp_prime_tab = ltm_prime_tab; +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) && _MSC_VER >= 1500 +#pragma warning(push) +#pragma warning(disable: 4996) +const mp_digit *s_mp_prime_tab = ltm_prime_tab; +#pragma warning(pop) +#else +const mp_digit *s_mp_prime_tab = ltm_prime_tab; +#endif + +#endif + +/* End: bn_prime_tab.c */ + +/* Start: bn_s_mp_add.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_ADD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* low level addition, based on HAC pp.594, Algorithm 14.7 */ +mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) +{ + const mp_int *x; + mp_err err; + int olduse, 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 ((err = mp_grow(c, max + 1)) != MP_OKAY) { + return err; + } + } + + /* get old used digit count and set new one */ + olduse = c->used; + c->used = max + 1; + + { + mp_digit u, *tmpa, *tmpb, *tmpc; + 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)MP_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)MP_DIGIT_BIT; + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + } + + /* add carry */ + *tmpc++ = u; + + /* clear digits above oldused */ + MP_ZERO_DIGITS(tmpc, olduse - c->used); + } + + mp_clamp(c); + return MP_OKAY; +} +#endif + +/* End: bn_s_mp_add.c */ + +/* Start: bn_s_mp_balance_mul.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_BALANCE_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single-digit multiplication with the smaller number as the single-digit */ +mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + int count, len_a, len_b, nblocks, i, j, bsize; + mp_int a0, tmp, A, B, r; + mp_err err; + + len_a = a->used; + len_b = b->used; + + nblocks = MP_MAX(a->used, b->used) / MP_MIN(a->used, b->used); + bsize = MP_MIN(a->used, b->used) ; + + if ((err = mp_init_size(&a0, bsize + 2)) != MP_OKAY) { + return err; + } + if ((err = mp_init_multi(&tmp, &r, NULL)) != MP_OKAY) { + mp_clear(&a0); + return err; + } + + /* Make sure that A is the larger one*/ + if (len_a < len_b) { + B = *a; + A = *b; + } else { + A = *a; + B = *b; + } + + for (i = 0, j=0; i < nblocks; i++) { + /* Cut a slice off of a */ + a0.used = 0; + for (count = 0; count < bsize; count++) { + a0.dp[count] = A.dp[ j++ ]; + a0.used++; + } + mp_clamp(&a0); + /* Multiply with b */ + if ((err = mp_mul(&a0, &B, &tmp)) != MP_OKAY) { + goto LBL_ERR; + } + /* Shift tmp to the correct position */ + if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) { + goto LBL_ERR; + } + /* Add to output. No carry needed */ + if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* The left-overs; there are always left-overs */ + if (j < A.used) { + a0.used = 0; + for (count = 0; j < A.used; count++) { + a0.dp[count] = A.dp[ j++ ]; + a0.used++; + } + mp_clamp(&a0); + if ((err = mp_mul(&a0, &B, &tmp)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) { + goto LBL_ERR; + } + } + + mp_exch(&r,c); +LBL_ERR: + mp_clear_multi(&a0, &tmp, &r,NULL); + return err; +} +#endif + +/* End: bn_s_mp_balance_mul.c */ + +/* Start: bn_s_mp_exptmod.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_EXPTMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef MP_LOW_MEM +# define TAB_SIZE 32 +# define MAX_WINSIZE 5 +#else +# define TAB_SIZE 256 +# define MAX_WINSIZE 0 +#endif + +mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) +{ + mp_int M[TAB_SIZE], res, mu; + mp_digit buf; + mp_err err; + int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + mp_err(*redux)(mp_int *x, const mp_int *m, const mp_int *mu); + + /* 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; + } + + winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize; + + /* 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[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU; + + for (x = 0; x < (winsize - 1); x++) { + /* square it */ + if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)], + &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU; + + /* reduce modulo P */ + if ((err = redux(&M[(size_t)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, 1uL); + + /* 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)MP_DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (buf >> (mp_digit)(MP_DIGIT_BIT - 1)) & 1uL; + 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 + +/* End: bn_s_mp_exptmod.c */ + +/* Start: bn_s_mp_exptmod_fast.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_EXPTMOD_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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 +# define MAX_WINSIZE 5 +#else +# define TAB_SIZE 256 +# define MAX_WINSIZE 0 +#endif + +mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) +{ + mp_int M[TAB_SIZE], res; + mp_digit buf, mp; + int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + mp_err err; + + /* 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. + */ + mp_err(*redux)(mp_int *x, const mp_int *n, mp_digit rho); + + /* 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; + } + + winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize; + + /* init M array */ + /* init first cell */ + if ((err = mp_init_size(&M[1], P->alloc)) != 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_size(&M[x], P->alloc)) != 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) { + if (MP_HAS(MP_MONTGOMERY_SETUP)) { + /* now setup montgomery */ + if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) goto LBL_M; + } else { + err = MP_VAL; + goto LBL_M; + } + + /* automatically pick the comba one if available (saves quite a few calls/ifs) */ + if (MP_HAS(S_MP_MONTGOMERY_REDUCE_FAST) && + (((P->used * 2) + 1) < MP_WARRAY) && + (P->used < MP_MAXFAST)) { + redux = s_mp_montgomery_reduce_fast; + } else if (MP_HAS(MP_MONTGOMERY_REDUCE)) { + /* use slower baseline Montgomery method */ + redux = mp_montgomery_reduce; + } else { + err = MP_VAL; + goto LBL_M; + } + } else if (redmode == 1) { + if (MP_HAS(MP_DR_SETUP) && MP_HAS(MP_DR_REDUCE)) { + /* 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; + } + } else if (MP_HAS(MP_REDUCE_2K_SETUP) && MP_HAS(MP_REDUCE_2K)) { + /* 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; + } + + /* setup result */ + if ((err = mp_init_size(&res, P->alloc)) != 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) { + if (MP_HAS(MP_MONTGOMERY_CALC_NORMALIZATION)) { + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization(&res, P)) != MP_OKAY) goto LBL_RES; + + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod(G, &res, P, &M[1])) != MP_OKAY) goto LBL_RES; + } else { + err = MP_VAL; + goto LBL_RES; + } + } else { + mp_set(&res, 1uL); + 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[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_RES; + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_RES; + if ((err = redux(&M[(size_t)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)MP_DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (mp_digit)(buf >> (MP_DIGIT_BIT - 1)) & 1uL; + 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 + +/* End: bn_s_mp_exptmod_fast.c */ + +/* Start: bn_s_mp_get_bit.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_GET_BIT_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Get bit at position b and return MP_YES if the bit is 1, MP_NO if it is 0 */ +mp_bool s_mp_get_bit(const mp_int *a, unsigned int b) +{ + mp_digit bit; + int limb = (int)(b / MP_DIGIT_BIT); + + if (limb >= a->used) { + return MP_NO; + } + + bit = (mp_digit)1 << (b % MP_DIGIT_BIT); + return ((a->dp[limb] & bit) != 0u) ? MP_YES : MP_NO; +} + +#endif + +/* End: bn_s_mp_get_bit.c */ + +/* Start: bn_s_mp_invmod_fast.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_INVMOD_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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 + */ +mp_err s_mp_invmod_fast(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x, y, u, v, B, D; + mp_sign neg; + mp_err err; + + /* 2. [modified] b must be odd */ + if (MP_IS_EVEN(b)) { + return MP_VAL; + } + + /* init all our temps */ + if ((err = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { + return err; + } + + /* x == modulus, y == value to invert */ + if ((err = mp_copy(b, &x)) != MP_OKAY) goto LBL_ERR; + + /* we need y = |a| */ + if ((err = mp_mod(a, b, &y)) != MP_OKAY) goto LBL_ERR; + + /* if one of x,y is zero return an error! */ + if (MP_IS_ZERO(&x) || MP_IS_ZERO(&y)) { + err = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR; + mp_set(&D, 1uL); + +top: + /* 4. while u is even do */ + while (MP_IS_EVEN(&u)) { + /* 4.1 u = u/2 */ + if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR; + + /* 4.2 if B is odd then */ + if (MP_IS_ODD(&B)) { + if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR; + } + /* B = B/2 */ + if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR; + } + + /* 5. while v is even do */ + while (MP_IS_EVEN(&v)) { + /* 5.1 v = v/2 */ + if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR; + + /* 5.2 if D is odd then */ + if (MP_IS_ODD(&D)) { + /* D = (D-x)/2 */ + if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR; + } + /* D = D/2 */ + if ((err = 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 ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR; + } else { + /* v - v - u, D = D - B */ + if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* if not zero goto step 4 */ + if (!MP_IS_ZERO(&u)) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d(&v, 1uL) != MP_EQ) { + err = MP_VAL; + goto LBL_ERR; + } + + /* b is now the inverse */ + neg = a->sign; + while (D.sign == MP_NEG) { + if ((err = mp_add(&D, b, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* too big */ + while (mp_cmp_mag(&D, b) != MP_LT) { + if ((err = mp_sub(&D, b, &D)) != MP_OKAY) goto LBL_ERR; + } + + mp_exch(&D, c); + c->sign = neg; + err = MP_OKAY; + +LBL_ERR: + mp_clear_multi(&x, &y, &u, &v, &B, &D, NULL); + return err; +} +#endif + +/* End: bn_s_mp_invmod_fast.c */ + +/* Start: bn_s_mp_invmod_slow.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_INVMOD_SLOW_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* hac 14.61, pp608 */ +mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x, y, u, v, A, B, C, D; + mp_err err; + + /* b cannot be negative */ + if ((b->sign == MP_NEG) || MP_IS_ZERO(b)) { + return MP_VAL; + } + + /* init temps */ + if ((err = mp_init_multi(&x, &y, &u, &v, + &A, &B, &C, &D, NULL)) != MP_OKAY) { + return err; + } + + /* x = a, y = b */ + if ((err = mp_mod(a, b, &x)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(b, &y)) != MP_OKAY) goto LBL_ERR; + + /* 2. [modified] if x,y are both even then return an error! */ + if (MP_IS_EVEN(&x) && MP_IS_EVEN(&y)) { + err = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR; + mp_set(&A, 1uL); + mp_set(&D, 1uL); + +top: + /* 4. while u is even do */ + while (MP_IS_EVEN(&u)) { + /* 4.1 u = u/2 */ + if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR; + + /* 4.2 if A or B is odd then */ + if (MP_IS_ODD(&A) || MP_IS_ODD(&B)) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((err = mp_add(&A, &y, &A)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR; + } + /* A = A/2, B = B/2 */ + if ((err = mp_div_2(&A, &A)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR; + } + + /* 5. while v is even do */ + while (MP_IS_EVEN(&v)) { + /* 5.1 v = v/2 */ + if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR; + + /* 5.2 if C or D is odd then */ + if (MP_IS_ODD(&C) || MP_IS_ODD(&D)) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((err = mp_add(&C, &y, &C)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR; + } + /* C = C/2, D = D/2 */ + if ((err = mp_div_2(&C, &C)) != MP_OKAY) goto LBL_ERR; + if ((err = 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 ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&A, &C, &A)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR; + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&C, &A, &C)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* if not zero goto step 4 */ + if (!MP_IS_ZERO(&u)) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d(&v, 1uL) != MP_EQ) { + err = MP_VAL; + goto LBL_ERR; + } + + /* if its too low */ + while (mp_cmp_d(&C, 0uL) == MP_LT) { + if ((err = mp_add(&C, b, &C)) != MP_OKAY) goto LBL_ERR; + } + + /* too big */ + while (mp_cmp_mag(&C, b) != MP_LT) { + if ((err = mp_sub(&C, b, &C)) != MP_OKAY) goto LBL_ERR; + } + + /* C is now the inverse */ + mp_exch(&C, c); + err = MP_OKAY; +LBL_ERR: + mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL); + return err; +} +#endif + +/* End: bn_s_mp_invmod_slow.c */ + +/* Start: bn_s_mp_karatsuba_mul.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_KARATSUBA_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* c = |a| * |b| using Karatsuba Multiplication using + * three half size multiplications + * + * Let B represent the radix [e.g. 2**MP_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. + */ +mp_err s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x0, x1, y0, y1, t1, x0y0, x1y1; + int B; + mp_err err = MP_MEM; /* default the return code to an error */ + + /* min # of digits */ + B = MP_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 LBL_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; + + { + int x; + 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))<used; + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if (mp_init_size(&x0, B) != MP_OKAY) + goto LBL_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; + + { + int x; + 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))<used > MP_WARRAY) { + return MP_VAL; + } + + /* get old used count */ + olduse = x->used; + + /* grow a as required */ + if (x->alloc < (n->used + 1)) { + if ((err = mp_grow(x, n->used + 1)) != MP_OKAY) { + return err; + } + } + + /* first we have to get the digits of the input into + * an array of double precision words W[...] + */ + { + mp_word *_W; + 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] */ + if (ix < ((n->used * 2) + 1)) { + MP_ZERO_BUFFER(_W, sizeof(mp_word) * (size_t)(((n->used * 2) + 1) - ix)); + } + } + + /* 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) + */ + mp_digit mu; + mu = ((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 + */ + { + int iy; + mp_digit *tmpn; + 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)MP_DIGIT_BIT; + } + + /* now we have to propagate the carries and + * shift the words downward [all those least + * significant digits we zeroed]. + */ + { + mp_digit *tmpx; + 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)MP_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++ = *_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 + */ + MP_ZERO_DIGITS(tmpx, olduse - ix); + } + + /* 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 + +/* End: bn_s_mp_montgomery_reduce_fast.c */ + +/* Start: bn_s_mp_mul_digs.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_MUL_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. + */ +mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + mp_int t; + mp_err err; + int 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) && + (MP_MIN(a->used, b->used) < MP_MAXFAST)) { + return s_mp_mul_digs_fast(a, b, c, digs); + } + + if ((err = mp_init_size(&t, digs)) != MP_OKAY) { + return err; + } + 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 = MP_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)MP_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 + +/* End: bn_s_mp_mul_digs.c */ + +/* Start: bn_s_mp_mul_digs_fast.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_MUL_DIGS_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. + * + */ +mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + int olduse, pa, ix, iz; + mp_err err; + mp_digit W[MP_WARRAY]; + mp_word _W; + + /* grow the destination as required */ + if (c->alloc < digs) { + if ((err = mp_grow(c, digs)) != MP_OKAY) { + return err; + } + } + + /* number of output digits to produce */ + pa = MP_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 = MP_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 = MP_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)MP_DIGIT_BIT; + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + mp_digit *tmpc; + tmpc = c->dp; + for (ix = 0; 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] */ + MP_ZERO_DIGITS(tmpc, olduse - ix); + } + mp_clamp(c); + return MP_OKAY; +} +#endif + +/* End: bn_s_mp_mul_digs_fast.c */ + +/* Start: bn_s_mp_mul_high_digs.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_MUL_HIGH_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* multiplies |a| * |b| and does not compute the lower digs digits + * [meant to get the higher part of the product] + */ +mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + mp_int t; + int pa, pb, ix, iy; + mp_err err; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + /* can we use the fast multiplier? */ + if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST) + && ((a->used + b->used + 1) < MP_WARRAY) + && (MP_MIN(a->used, b->used) < MP_MAXFAST)) { + return s_mp_mul_high_digs_fast(a, b, c, digs); + } + + if ((err = mp_init_size(&t, a->used + b->used + 1)) != MP_OKAY) { + return err; + } + 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)MP_DIGIT_BIT); + } + *tmpt = u; + } + mp_clamp(&t); + mp_exch(&t, c); + mp_clear(&t); + return MP_OKAY; +} +#endif + +/* End: bn_s_mp_mul_high_digs.c */ + +/* Start: bn_s_mp_mul_high_digs_fast.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_MUL_HIGH_DIGS_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. + */ +mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + int olduse, pa, ix, iz; + mp_err err; + mp_digit W[MP_WARRAY]; + mp_word _W; + + /* grow the destination as required */ + pa = a->used + b->used; + if (c->alloc < pa) { + if ((err = mp_grow(c, pa)) != MP_OKAY) { + return err; + } + } + + /* 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 = MP_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 = MP_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)MP_DIGIT_BIT; + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + 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] */ + MP_ZERO_DIGITS(tmpc, olduse - ix); + } + mp_clamp(c); + return MP_OKAY; +} +#endif + +/* End: bn_s_mp_mul_high_digs_fast.c */ + +/* Start: bn_s_mp_prime_is_divisible.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_PRIME_IS_DIVISIBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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 + */ +mp_err s_mp_prime_is_divisible(const mp_int *a, mp_bool *result) +{ + int ix; + mp_err err; + mp_digit res; + + /* default to not */ + *result = MP_NO; + + for (ix = 0; ix < PRIVATE_MP_PRIME_TAB_SIZE; ix++) { + /* what is a mod LBL_prime_tab[ix] */ + if ((err = mp_mod_d(a, s_mp_prime_tab[ix], &res)) != MP_OKAY) { + return err; + } + + /* is the residue zero? */ + if (res == 0u) { + *result = MP_YES; + return MP_OKAY; + } + } + + return MP_OKAY; +} +#endif + +/* End: bn_s_mp_prime_is_divisible.c */ + +/* Start: bn_s_mp_rand_jenkins.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_RAND_JENKINS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Bob Jenkins' http://burtleburtle.net/bob/rand/smallprng.html */ +/* Chosen for speed and a good "mix" */ +typedef struct { + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; +} ranctx; + +static ranctx jenkins_x; + +#define rot(x,k) (((x)<<(k))|((x)>>(64-(k)))) +static uint64_t s_rand_jenkins_val(void) +{ + uint64_t e = jenkins_x.a - rot(jenkins_x.b, 7); + jenkins_x.a = jenkins_x.b ^ rot(jenkins_x.c, 13); + jenkins_x.b = jenkins_x.c + rot(jenkins_x.d, 37); + jenkins_x.c = jenkins_x.d + e; + jenkins_x.d = e + jenkins_x.a; + return jenkins_x.d; +} + +void s_mp_rand_jenkins_init(uint64_t seed) +{ + uint64_t i; + jenkins_x.a = 0xf1ea5eedULL; + jenkins_x.b = jenkins_x.c = jenkins_x.d = seed; + for (i = 0uLL; i < 20uLL; ++i) { + (void)s_rand_jenkins_val(); + } +} + +mp_err s_mp_rand_jenkins(void *p, size_t n) +{ + char *q = (char *)p; + while (n > 0u) { + int i; + uint64_t x = s_rand_jenkins_val(); + for (i = 0; (i < 8) && (n > 0u); ++i, --n) { + *q++ = (char)(x & 0xFFuLL); + x >>= 8; + } + } + return MP_OKAY; +} + +#endif + +/* End: bn_s_mp_rand_jenkins.c */ + +/* Start: bn_s_mp_rand_platform.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_RAND_PLATFORM_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* First the OS-specific special cases + * - *BSD + * - Windows + */ +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +#define BN_S_READ_ARC4RANDOM_C +static mp_err s_read_arc4random(void *p, size_t n) +{ + arc4random_buf(p, n); + return MP_OKAY; +} +#endif + +#if defined(_WIN32) || defined(_WIN32_WCE) +#define BN_S_READ_WINCSP_C + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif +#ifdef _WIN32_WCE +#define UNDER_CE +#define ARM +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#include + +static mp_err s_read_wincsp(void *p, size_t n) +{ + static HCRYPTPROV hProv = 0; + if (hProv == 0) { + HCRYPTPROV h = 0; + if (!CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL, + (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && + !CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) { + return MP_ERR; + } + hProv = h; + } + return CryptGenRandom(hProv, (DWORD)n, (BYTE *)p) == TRUE ? MP_OKAY : MP_ERR; +} +#endif /* WIN32 */ + +#if !defined(BN_S_READ_WINCSP_C) && defined(__linux__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2, 25) +#define BN_S_READ_GETRANDOM_C +#include +#include + +static mp_err s_read_getrandom(void *p, size_t n) +{ + char *q = (char *)p; + while (n > 0u) { + ssize_t ret = getrandom(q, n, 0); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + return MP_ERR; + } + q += ret; + n -= (size_t)ret; + } + return MP_OKAY; +} +#endif +#endif + +/* We assume all platforms besides windows provide "/dev/urandom". + * In case yours doesn't, define MP_NO_DEV_URANDOM at compile-time. + */ +#if !defined(BN_S_READ_WINCSP_C) && !defined(MP_NO_DEV_URANDOM) +#define BN_S_READ_URANDOM_C +#ifndef MP_DEV_URANDOM +#define MP_DEV_URANDOM "/dev/urandom" +#endif +#include +#include +#include + +static mp_err s_read_urandom(void *p, size_t n) +{ + int fd; + char *q = (char *)p; + + do { + fd = open(MP_DEV_URANDOM, O_RDONLY); + } while ((fd == -1) && (errno == EINTR)); + if (fd == -1) return MP_ERR; + + while (n > 0u) { + ssize_t ret = read(fd, p, n); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + close(fd); + return MP_ERR; + } + q += ret; + n -= (size_t)ret; + } + + close(fd); + return MP_OKAY; +} +#endif + +#if defined(MP_PRNG_ENABLE_LTM_RNG) +#define BN_S_READ_LTM_RNG +unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); +void (*ltm_rng_callback)(void); + +static mp_err s_read_ltm_rng(void *p, size_t n) +{ + unsigned long res; + if (ltm_rng == NULL) return MP_ERR; + res = ltm_rng(p, n, ltm_rng_callback); + if (res != n) return MP_ERR; + return MP_OKAY; +} +#endif + +mp_err s_read_arc4random(void *p, size_t n); +mp_err s_read_wincsp(void *p, size_t n); +mp_err s_read_getrandom(void *p, size_t n); +mp_err s_read_urandom(void *p, size_t n); +mp_err s_read_ltm_rng(void *p, size_t n); + +mp_err s_mp_rand_platform(void *p, size_t n) +{ + mp_err err = MP_ERR; + if ((err != MP_OKAY) && MP_HAS(S_READ_ARC4RANDOM)) err = s_read_arc4random(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_GETRANDOM)) err = s_read_getrandom(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_URANDOM)) err = s_read_urandom(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_LTM_RNG)) err = s_read_ltm_rng(p, n); + return err; +} + +#endif + +/* End: bn_s_mp_rand_platform.c */ + +/* Start: bn_s_mp_reverse.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_REVERSE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reverse an array, used for radix code */ +void s_mp_reverse(unsigned char *s, size_t len) +{ + size_t ix, iy; + unsigned char t; + + ix = 0u; + iy = len - 1u; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} +#endif + +/* End: bn_s_mp_reverse.c */ + +/* Start: bn_s_mp_sqr.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ +mp_err s_mp_sqr(const mp_int *a, mp_int *b) +{ + mp_int t; + int ix, iy, pa; + mp_err err; + mp_word r; + mp_digit u, tmpx, *tmpt; + + pa = a->used; + if ((err = mp_init_size(&t, (2 * pa) + 1)) != MP_OKAY) { + return err; + } + + /* 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)MP_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)MP_DIGIT_BIT); + } + /* propagate upwards */ + while (u != 0uL) { + r = (mp_word)*tmpt + (mp_word)u; + *tmpt++ = (mp_digit)(r & (mp_word)MP_MASK); + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + } + + mp_clamp(&t); + mp_exch(&t, b); + mp_clear(&t); + return MP_OKAY; +} +#endif + +/* End: bn_s_mp_sqr.c */ + +/* Start: bn_s_mp_sqr_fast.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_SQR_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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. +*/ + +mp_err s_mp_sqr_fast(const mp_int *a, mp_int *b) +{ + int olduse, pa, ix, iz; + mp_digit W[MP_WARRAY], *tmpx; + mp_word W1; + mp_err err; + + /* grow the destination as required */ + pa = a->used + a->used; + if (b->alloc < pa) { + if ((err = mp_grow(b, pa)) != MP_OKAY) { + return err; + } + } + + /* 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 = MP_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 = MP_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 = MP_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 (((unsigned)ix & 1u) == 0u) { + _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)MP_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] */ + MP_ZERO_DIGITS(tmpb, olduse - ix); + } + mp_clamp(b); + return MP_OKAY; +} +#endif + +/* End: bn_s_mp_sqr_fast.c */ + +/* Start: bn_s_mp_sub.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ +mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) +{ + int olduse, min, max; + mp_err err; + + /* find sizes */ + min = b->used; + max = a->used; + + /* init result */ + if (c->alloc < max) { + if ((err = mp_grow(c, max)) != MP_OKAY) { + return err; + } + } + olduse = c->used; + c->used = max; + + { + mp_digit u, *tmpa, *tmpb, *tmpc; + 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_SIZEOF_BITS(mp_digit) - 1u); + + /* 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_SIZEOF_BITS(mp_digit) - 1u); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* clear digits above used (since we may not have grown result above) */ + MP_ZERO_DIGITS(tmpc, olduse - c->used); + } + + mp_clamp(c); + return MP_OKAY; +} + +#endif + +/* End: bn_s_mp_sub.c */ + +/* Start: bn_s_mp_toom_mul.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_TOOM_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* 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...). +*/ + +/* + This file contains code from J. Arndt's book "Matters Computational" + and the accompanying FXT-library with permission of the author. +*/ + +/* + Setup from + + Chung, Jaewook, and M. Anwar Hasan. "Asymmetric squaring formulae." + 18th IEEE Symposium on Computer Arithmetic (ARITH'07). IEEE, 2007. + + The interpolation from above needed one temporary variable more + than the interpolation here: + + Bodrato, Marco, and Alberto Zanoni. "What about Toom-Cook matrices optimality." + Centro Vito Volterra Universita di Roma Tor Vergata (2006) +*/ + +mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int S1, S2, T1, a0, a1, a2, b0, b1, b2; + int B, count; + mp_err err; + + /* init temps */ + if ((err = mp_init_multi(&S1, &S2, &T1, NULL)) != MP_OKAY) { + return err; + } + + /* B */ + B = MP_MIN(a->used, b->used) / 3; + + /** a = a2 * x^2 + a1 * x + a0; */ + if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0; + + for (count = 0; count < B; count++) { + a0.dp[count] = a->dp[count]; + a0.used++; + } + mp_clamp(&a0); + if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1; + for (; count < (2 * B); count++) { + a1.dp[count - B] = a->dp[count]; + a1.used++; + } + mp_clamp(&a1); + if ((err = mp_init_size(&a2, B + (a->used - (3 * B)))) != MP_OKAY) goto LBL_ERRa2; + for (; count < a->used; count++) { + a2.dp[count - (2 * B)] = a->dp[count]; + a2.used++; + } + mp_clamp(&a2); + + /** b = b2 * x^2 + b1 * x + b0; */ + if ((err = mp_init_size(&b0, B)) != MP_OKAY) goto LBL_ERRb0; + for (count = 0; count < B; count++) { + b0.dp[count] = b->dp[count]; + b0.used++; + } + mp_clamp(&b0); + if ((err = mp_init_size(&b1, B)) != MP_OKAY) goto LBL_ERRb1; + for (; count < (2 * B); count++) { + b1.dp[count - B] = b->dp[count]; + b1.used++; + } + mp_clamp(&b1); + if ((err = mp_init_size(&b2, B + (b->used - (3 * B)))) != MP_OKAY) goto LBL_ERRb2; + for (; count < b->used; count++) { + b2.dp[count - (2 * B)] = b->dp[count]; + b2.used++; + } + mp_clamp(&b2); + + /** \\ S1 = (a2+a1+a0) * (b2+b1+b0); */ + /** T1 = a2 + a1; */ + if ((err = mp_add(&a2, &a1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = T1 + a0; */ + if ((err = mp_add(&T1, &a0, &S2)) != MP_OKAY) goto LBL_ERR; + + /** c = b2 + b1; */ + if ((err = mp_add(&b2, &b1, c)) != MP_OKAY) goto LBL_ERR; + + /** S1 = c + b0; */ + if ((err = mp_add(c, &b0, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 * S2; */ + if ((err = mp_mul(&S1, &S2, &S1)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = (4*a2+2*a1+a0) * (4*b2+2*b1+b0); */ + /** T1 = T1 + a2; */ + if ((err = mp_add(&T1, &a2, &T1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = T1 << 1; */ + if ((err = mp_mul_2(&T1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = T1 + a0; */ + if ((err = mp_add(&T1, &a0, &T1)) != MP_OKAY) goto LBL_ERR; + + /** c = c + b2; */ + if ((err = mp_add(c, &b2, c)) != MP_OKAY) goto LBL_ERR; + + /** c = c << 1; */ + if ((err = mp_mul_2(c, c)) != MP_OKAY) goto LBL_ERR; + + /** c = c + b0; */ + if ((err = mp_add(c, &b0, c)) != MP_OKAY) goto LBL_ERR; + + /** S2 = T1 * c; */ + if ((err = mp_mul(&T1, c, &S2)) != MP_OKAY) goto LBL_ERR; + + /** \\S3 = (a2-a1+a0) * (b2-b1+b0); */ + /** a1 = a2 - a1; */ + if ((err = mp_sub(&a2, &a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 + a0; */ + if ((err = mp_add(&a1, &a0, &a1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = b2 - b1; */ + if ((err = mp_sub(&b2, &b1, &b1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = b1 + b0; */ + if ((err = mp_add(&b1, &b0, &b1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 * b1; */ + if ((err = mp_mul(&a1, &b1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = a2 * b2; */ + if ((err = mp_mul(&a2, &b2, &b1)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = (S2 - S3)/3; */ + /** S2 = S2 - a1; */ + if ((err = mp_sub(&S2, &a1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 / 3; \\ this is an exact division */ + if ((err = mp_div_3(&S2, &S2, NULL)) != MP_OKAY) goto LBL_ERR; + + /** a1 = S1 - a1; */ + if ((err = mp_sub(&S1, &a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 >> 1; */ + if ((err = mp_div_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a0 = a0 * b0; */ + if ((err = mp_mul(&a0, &b0, &a0)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - a0; */ + if ((err = mp_sub(&S1, &a0, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 - S1; */ + if ((err = mp_sub(&S2, &S1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 >> 1; */ + if ((err = mp_div_2(&S2, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - a1; */ + if ((err = mp_sub(&S1, &a1, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - b1; */ + if ((err = mp_sub(&S1, &b1, &S1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = b1 << 1; */ + if ((err = mp_mul_2(&b1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 - T1; */ + if ((err = mp_sub(&S2, &T1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 - S2; */ + if ((err = mp_sub(&a1, &S2, &a1)) != MP_OKAY) goto LBL_ERR; + + + /** P = b1*x^4+ S2*x^3+ S1*x^2+ a1*x + a0; */ + if ((err = mp_lshd(&b1, 4 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&S2, 3 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &S2, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&S1, 2 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &S1, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a1, 1 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &a1, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &a0, c)) != MP_OKAY) goto LBL_ERR; + + /** a * b - P */ + + +LBL_ERR: + mp_clear(&b2); +LBL_ERRb2: + mp_clear(&b1); +LBL_ERRb1: + mp_clear(&b0); +LBL_ERRb0: + mp_clear(&a2); +LBL_ERRa2: + mp_clear(&a1); +LBL_ERRa1: + mp_clear(&a0); +LBL_ERRa0: + mp_clear_multi(&S1, &S2, &T1, NULL); + return err; +} + +#endif + +/* End: bn_s_mp_toom_mul.c */ + +/* Start: bn_s_mp_toom_sqr.c */ +#include "tommath_private.h" +#ifdef BN_S_MP_TOOM_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* squaring using Toom-Cook 3-way algorithm */ + +/* + This file contains code from J. Arndt's book "Matters Computational" + and the accompanying FXT-library with permission of the author. +*/ + +/* squaring using Toom-Cook 3-way algorithm */ +/* + Setup and interpolation from algorithm SQR_3 in + + Chung, Jaewook, and M. Anwar Hasan. "Asymmetric squaring formulae." + 18th IEEE Symposium on Computer Arithmetic (ARITH'07). IEEE, 2007. + +*/ +mp_err s_mp_toom_sqr(const mp_int *a, mp_int *b) +{ + mp_int S0, a0, a1, a2; + mp_digit *tmpa, *tmpc; + int B, count; + mp_err err; + + + /* init temps */ + if ((err = mp_init(&S0)) != MP_OKAY) { + return err; + } + + /* B */ + B = a->used / 3; + + /** a = a2 * x^2 + a1 * x + a0; */ + if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0; + + a0.used = B; + if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1; + a1.used = B; + if ((err = mp_init_size(&a2, B + (a->used - (3 * B)))) != MP_OKAY) goto LBL_ERRa2; + + tmpa = a->dp; + tmpc = a0.dp; + for (count = 0; count < B; count++) { + *tmpc++ = *tmpa++; + } + tmpc = a1.dp; + for (; count < (2 * B); count++) { + *tmpc++ = *tmpa++; + } + tmpc = a2.dp; + for (; count < a->used; count++) { + *tmpc++ = *tmpa++; + a2.used++; + } + mp_clamp(&a0); + mp_clamp(&a1); + mp_clamp(&a2); + + /** S0 = a0^2; */ + if ((err = mp_sqr(&a0, &S0)) != MP_OKAY) goto LBL_ERR; + + /** \\S1 = (a2 + a1 + a0)^2 */ + /** \\S2 = (a2 - a1 + a0)^2 */ + /** \\S1 = a0 + a2; */ + /** a0 = a0 + a2; */ + if ((err = mp_add(&a0, &a2, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S1 - a1; */ + /** b = a0 - a1; */ + if ((err = mp_sub(&a0, &a1, b)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1 + a1; */ + /** a0 = a0 + a1; */ + if ((err = mp_add(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1^2; */ + /** a0 = a0^2; */ + if ((err = mp_sqr(&a0, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S2^2; */ + /** b = b^2; */ + if ((err = mp_sqr(b, b)) != MP_OKAY) goto LBL_ERR; + + /** \\ S3 = 2 * a1 * a2 */ + /** \\S3 = a1 * a2; */ + /** a1 = a1 * a2; */ + if ((err = mp_mul(&a1, &a2, &a1)) != MP_OKAY) goto LBL_ERR; + /** \\S3 = S3 << 1; */ + /** a1 = a1 << 1; */ + if ((err = mp_mul_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** \\S4 = a2^2; */ + /** a2 = a2^2; */ + if ((err = mp_sqr(&a2, &a2)) != MP_OKAY) goto LBL_ERR; + + /** \\ tmp = (S1 + S2)/2 */ + /** \\tmp = S1 + S2; */ + /** b = a0 + b; */ + if ((err = mp_add(&a0, b, b)) != MP_OKAY) goto LBL_ERR; + /** \\tmp = tmp >> 1; */ + /** b = b >> 1; */ + if ((err = mp_div_2(b, b)) != MP_OKAY) goto LBL_ERR; + + /** \\ S1 = S1 - tmp - S3 */ + /** \\S1 = S1 - tmp; */ + /** a0 = a0 - b; */ + if ((err = mp_sub(&a0, b, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1 - S3; */ + /** a0 = a0 - a1; */ + if ((err = mp_sub(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = tmp - S4 -S0 */ + /** \\S2 = tmp - S4; */ + /** b = b - a2; */ + if ((err = mp_sub(b, &a2, b)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S2 - S0; */ + /** b = b - S0; */ + if ((err = mp_sub(b, &S0, b)) != MP_OKAY) goto LBL_ERR; + + + /** \\P = S4*x^4 + S3*x^3 + S2*x^2 + S1*x + S0; */ + /** P = a2*x^4 + a1*x^3 + b*x^2 + a0*x + S0; */ + + if ((err = mp_lshd(&a2, 4 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a1, 3 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(b, 2 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a0, 1 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&a2, &a1, &a2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&a2, b, b)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(b, &a0, b)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(b, &S0, b)) != MP_OKAY) goto LBL_ERR; + /** a^2 - P */ + + +LBL_ERR: + mp_clear(&a2); +LBL_ERRa2: + mp_clear(&a1); +LBL_ERRa1: + mp_clear(&a0); +LBL_ERRa0: + mp_clear(&S0); + + return err; +} + +#endif + +/* End: bn_s_mp_toom_sqr.c */ + + +/* EOF */ diff --git a/lib/hcrypto/libtommath/pretty.build b/lib/hcrypto/libtommath/pretty.build deleted file mode 100644 index 0f5081902..000000000 --- a/lib/hcrypto/libtommath/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"; diff --git a/lib/hcrypto/libtommath/testme.sh b/lib/hcrypto/libtommath/testme.sh new file mode 100755 index 000000000..40fa32d50 --- /dev/null +++ b/lib/hcrypto/libtommath/testme.sh @@ -0,0 +1,394 @@ +#!/bin/bash +# +# return values of this script are: +# 0 success +# 128 a test failed +# >0 the number of timed-out tests +# 255 parsing of parameters failed + +set -e + +if [ -f /proc/cpuinfo ] +then + MAKE_JOBS=$(( ($(cat /proc/cpuinfo | grep -E '^processor[[:space:]]*:' | tail -n -1 | cut -d':' -f2) + 1) * 2 + 1 )) +else + MAKE_JOBS=8 +fi + +ret=0 +TEST_CFLAGS="" + +_help() +{ + echo "Usage options for $(basename $0) [--with-cc=arg [other options]]" + echo + echo "Executing this script without any parameter will only run the default" + echo "configuration that has automatically been determined for the" + echo "architecture you're running." + echo + echo " --with-cc=* The compiler(s) to use for the tests" + echo " This is an option that will be iterated." + echo + echo " --test-vs-mtest=* Run test vs. mtest for '*' operations." + echo " Only the first of each options will be" + echo " taken into account." + echo + echo "To be able to specify options a compiler has to be given with" + echo "the option --with-cc=compilername" + echo "All other options will be tested with all MP_xBIT configurations." + echo + echo " --with-{m64,m32,mx32} The architecture(s) to build and test" + echo " for, e.g. --with-mx32." + echo " This is an option that will be iterated," + echo " multiple selections are possible." + echo " The mx32 architecture is not supported" + echo " by clang and will not be executed." + echo + echo " --cflags=* Give an option to the compiler," + echo " e.g. --cflags=-g" + echo " This is an option that will always be" + echo " passed as parameter to CC." + echo + echo " --make-option=* Give an option to make," + echo " e.g. --make-option=\"-f makefile.shared\"" + echo " This is an option that will always be" + echo " passed as parameter to make." + echo + echo " --with-low-mp Also build&run tests with -DMP_{8,16,32}BIT." + echo + echo " --mtest-real-rand Use real random data when running mtest." + echo + echo " --with-valgrind" + echo " --with-valgrind=* Run in valgrind (slow!)." + echo + echo " --with-travis-valgrind Run with valgrind on Travis on specific branches." + echo + echo " --valgrind-options Additional Valgrind options" + echo " Some of the options like e.g.:" + echo " --track-origins=yes add a lot of extra" + echo " runtime and may trigger the 30 minutes" + echo " timeout." + echo + echo "Godmode:" + echo + echo " --all Choose all architectures and gcc and clang" + echo " as compilers but does not run valgrind." + echo + echo " --format Runs the various source-code formatters" + echo " and generators and checks if the sources" + echo " are clean." + echo + echo " -h" + echo " --help This message" + echo + echo " -v" + echo " --version Prints the version. It is just the number" + echo " of git commits to this file, no deeper" + echo " meaning attached" + exit 0 +} + +_die() +{ + echo "error $2 while $1" + if [ "$2" != "124" ] + then + exit 128 + else + echo "assuming timeout while running test - continue" + local _tail="" + which tail >/dev/null && _tail="tail -n 1 test_${suffix}.log" && \ + echo "last line of test_"${suffix}".log was:" && $_tail && echo "" + ret=$(( $ret + 1 )) + fi +} + +_make() +{ + echo -ne " Compile $1 $2" + suffix=$(echo ${1}${2} | tr ' ' '_') + CC="$1" CFLAGS="$2 $TEST_CFLAGS" make -j$MAKE_JOBS $3 $MAKE_OPTIONS > /dev/null 2>gcc_errors_${suffix}.log + errcnt=$(wc -l < gcc_errors_${suffix}.log) + if [[ ${errcnt} -gt 1 ]]; then + echo " failed" + cat gcc_errors_${suffix}.log + exit 128 + fi +} + + +_runtest() +{ + make clean > /dev/null + local _timeout="" + which timeout >/dev/null && _timeout="timeout --foreground 90" + if [[ "$MAKE_OPTIONS" =~ "tune" ]] + then + # "make tune" will run "tune_it.sh" automatically, hence "autotune", but it cannot + # get switched off without some effort, so we just let it run twice for testing purposes + echo -e "\rRun autotune $1 $2" + _make "$1" "$2" "" + $_timeout $TUNE_CMD > test_${suffix}.log || _die "running autotune" $? + else + _make "$1" "$2" "test" + echo -e "\rRun test $1 $2" + $_timeout ./test > test_${suffix}.log || _die "running tests" $? + fi +} + +# This is not much more of a C&P of _runtest with a different timeout +# and the additional valgrind call. +# TODO: merge +_runvalgrind() +{ + make clean > /dev/null + local _timeout="" + # 30 minutes? Yes. Had it at 20 minutes and the Valgrind run needed over 25 minutes. + # A bit too close for comfort. + which timeout >/dev/null && _timeout="timeout --foreground 1800" +echo "MAKE_OPTIONS = \"$MAKE_OPTIONS\"" + if [[ "$MAKE_OPTIONS" =~ "tune" ]] + then +echo "autotune branch" + _make "$1" "$2" "" + # The shell used for /bin/sh is DASH 0.5.7-4ubuntu1 on the author's machine which fails valgrind, so + # we just run on instance of etc/tune with the same options as in etc/tune_it.sh + echo -e "\rRun etc/tune $1 $2 once inside valgrind" + $_timeout $VALGRIND_BIN $VALGRIND_OPTS $TUNE_CMD > test_${suffix}.log || _die "running etc/tune" $? + else + _make "$1" "$2" "test" + echo -e "\rRun test $1 $2 inside valgrind" + $_timeout $VALGRIND_BIN $VALGRIND_OPTS ./test > test_${suffix}.log || _die "running tests" $? + fi +} + + +_banner() +{ + echo "uname="$(uname -a) + [[ "$#" != "0" ]] && (echo $1=$($1 -dumpversion)) || true +} + +_exit() +{ + if [ "$ret" == "0" ] + then + echo "Tests successful" + else + echo "$ret tests timed out" + fi + + exit $ret +} + +ARCHFLAGS="" +COMPILERS="" +CFLAGS="" +WITH_LOW_MP="" +TEST_VS_MTEST="" +MTEST_RAND="" +# timed with an AMD A8-6600K +# 25 minutes +#VALGRIND_OPTS=" --track-origins=yes --leak-check=full --show-leak-kinds=all --error-exitcode=1 " +# 9 minutes (14 minutes with --test-vs-mtest=333333 --mtest-real-rand) +VALGRIND_OPTS=" --leak-check=full --show-leak-kinds=all --error-exitcode=1 " +#VALGRIND_OPTS="" +VALGRIND_BIN="" +CHECK_FORMAT="" +TUNE_CMD="./etc/tune -t -r 10 -L 3" + +alive_pid=0 + +function kill_alive() { + disown $alive_pid || true + kill $alive_pid 2>/dev/null +} + +function start_alive_printing() { + [ "$alive_pid" == "0" ] || return 0; + for i in `seq 1 10` ; do sleep 300 && echo "Tests still in Progress..."; done & + alive_pid=$! + trap kill_alive EXIT +} + +while [ $# -gt 0 ]; +do + case $1 in + "--with-m64" | "--with-m32" | "--with-mx32") + ARCHFLAGS="$ARCHFLAGS ${1:6}" + ;; + --with-cc=*) + COMPILERS="$COMPILERS ${1#*=}" + ;; + --cflags=*) + CFLAGS="$CFLAGS ${1#*=}" + ;; + --valgrind-options=*) + VALGRIND_OPTS="$VALGRIND_OPTS ${1#*=}" + ;; + --with-valgrind*) + if [[ ${1#*d} != "" ]] + then + VALGRIND_BIN="${1#*=}" + else + VALGRIND_BIN="valgrind" + fi + start_alive_printing + ;; + --with-travis-valgrind*) + if [[ ("$TRAVIS_BRANCH" == "develop" && "$TRAVIS_PULL_REQUEST" == "false") || "$TRAVIS_BRANCH" == *"valgrind"* || "$TRAVIS_COMMIT_MESSAGE" == *"valgrind"* ]] + then + if [[ ${1#*d} != "" ]] + then + VALGRIND_BIN="${1#*=}" + else + VALGRIND_BIN="valgrind" + fi + start_alive_printing + fi + ;; + --make-option=*) + MAKE_OPTIONS="$MAKE_OPTIONS ${1#*=}" + ;; + --with-low-mp) + WITH_LOW_MP="1" + ;; + --test-vs-mtest=*) + TEST_VS_MTEST="${1#*=}" + if ! [ "$TEST_VS_MTEST" -eq "$TEST_VS_MTEST" ] 2> /dev/null + then + echo "--test-vs-mtest Parameter has to be int" + exit 255 + fi + start_alive_printing + ;; + --mtest-real-rand) + MTEST_RAND="-DLTM_MTEST_REAL_RAND" + ;; + --format) + CHECK_FORMAT="1" + ;; + --all) + COMPILERS="gcc clang" + ARCHFLAGS="-m64 -m32 -mx32" + ;; + --help | -h) + _help + ;; + --version | -v) + echo $(git rev-list HEAD --count -- testme.sh) || echo "Unknown. Please run in original libtommath git repository." + exit 0 + ;; + *) + echo "Ignoring option ${1}" + ;; + esac + shift +done + +function _check_git() { + git update-index --refresh >/dev/null || true + git diff-index --quiet HEAD -- . || ( echo "FAILURE: $*" && exit 1 ) +} + +if [[ "$CHECK_FORMAT" == "1" ]] +then + make astyle + _check_git "make astyle" + perl helper.pl --update-files + _check_git "helper.pl --update-files" + perl helper.pl --check-all + _check_git "helper.pl --check-all" + exit $? +fi + +[[ "$VALGRIND_BIN" == "" ]] && VALGRIND_OPTS="" + +# default to CC environment variable if no compiler is defined but some other options +if [[ "$COMPILERS" == "" ]] && [[ "$ARCHFLAGS$MAKE_OPTIONS$CFLAGS" != "" ]] +then + COMPILERS="$CC" +# default to CC environment variable and run only default config if no option is given +elif [[ "$COMPILERS" == "" ]] +then + _banner "$CC" + if [[ "$VALGRIND_BIN" != "" ]] + then + _runvalgrind "$CC" "" + else + _runtest "$CC" "" + fi + _exit +fi + + +archflags=( $ARCHFLAGS ) +compilers=( $COMPILERS ) + +# choosing a compiler without specifying an architecture will use the default architecture +if [ "${#archflags[@]}" == "0" ] +then + archflags[0]=" " +fi + +_banner + +if [[ "$TEST_VS_MTEST" != "" ]] +then + make clean > /dev/null + _make "${compilers[0]} ${archflags[0]}" "$CFLAGS" "mtest_opponent" + echo + _make "gcc" "$MTEST_RAND" "mtest" + echo + echo "Run test vs. mtest for $TEST_VS_MTEST iterations" + _timeout="" + which timeout >/dev/null && _timeout="timeout --foreground 1800" + $_timeout ./mtest/mtest $TEST_VS_MTEST | $VALGRIND_BIN $VALGRIND_OPTS ./mtest_opponent > valgrind_test.log 2> test_vs_mtest_err.log + retval=$? + head -n 5 valgrind_test.log + tail -n 2 valgrind_test.log + exit $retval +fi + +for i in "${compilers[@]}" +do + if [ -z "$(which $i)" ] + then + echo "Skipped compiler $i, file not found" + continue + fi + compiler_version=$(echo "$i="$($i -dumpversion)) + if [ "$compiler_version" == "clang=4.2.1" ] + then + # one of my versions of clang complains about some stuff in stdio.h and stdarg.h ... + TEST_CFLAGS="-Wno-typedef-redefinition" + else + TEST_CFLAGS="" + fi + echo $compiler_version + + for a in "${archflags[@]}" + do + if [[ $(expr "$i" : "clang") -ne 0 && "$a" == "-mx32" ]] + then + echo "clang -mx32 tests skipped" + continue + fi + if [[ "$VALGRIND_BIN" != "" ]] + then + _runvalgrind "$i $a" "$CFLAGS" + [ "$WITH_LOW_MP" != "1" ] && continue + _runvalgrind "$i $a" "-DMP_8BIT $CFLAGS" + _runvalgrind "$i $a" "-DMP_16BIT $CFLAGS" + _runvalgrind "$i $a" "-DMP_32BIT $CFLAGS" + else + _runtest "$i $a" "$CFLAGS" + [ "$WITH_LOW_MP" != "1" ] && continue + _runtest "$i $a" "-DMP_8BIT $CFLAGS" + _runtest "$i $a" "-DMP_16BIT $CFLAGS" + _runtest "$i $a" "-DMP_32BIT $CFLAGS" + fi + done +done + +_exit diff --git a/lib/hcrypto/libtommath/tombc/grammar.txt b/lib/hcrypto/libtommath/tombc/grammar.txt deleted file mode 100644 index a780e759d..000000000 --- a/lib/hcrypto/libtommath/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/lib/hcrypto/libtommath/tommath.def b/lib/hcrypto/libtommath/tommath.def new file mode 100644 index 000000000..229fae49a --- /dev/null +++ b/lib/hcrypto/libtommath/tommath.def @@ -0,0 +1,145 @@ +; libtommath +; +; Use this command to produce a 32-bit .lib file, for use in any MSVC version +; lib -machine:X86 -name:libtommath.dll -def:tommath.def -out:tommath.lib +; Use this command to produce a 64-bit .lib file, for use in any MSVC version +; lib -machine:X64 -name:libtommath.dll -def:tommath.def -out:tommath.lib +; +EXPORTS + mp_2expt + mp_abs + mp_add + mp_add_d + mp_addmod + mp_and + mp_clamp + mp_clear + mp_clear_multi + mp_cmp + mp_cmp_d + mp_cmp_mag + mp_cnt_lsb + mp_complement + mp_copy + mp_count_bits + mp_decr + mp_div + mp_div_2 + mp_div_2d + mp_div_3 + mp_div_d + mp_dr_is_modulus + mp_dr_reduce + mp_dr_setup + mp_error_to_string + mp_exch + mp_expt_u32 + mp_exptmod + mp_exteuclid + mp_fread + mp_from_sbin + mp_from_ubin + mp_fwrite + mp_gcd + mp_get_double + mp_get_i32 + mp_get_i64 + mp_get_int + mp_get_l + mp_get_ll + mp_get_long + mp_get_long_long + mp_get_mag_u32 + mp_get_mag_u64 + mp_get_mag_ul + mp_get_mag_ull + mp_grow + mp_incr + mp_init + mp_init_copy + mp_init_i32 + mp_init_i64 + mp_init_l + mp_init_ll + mp_init_multi + mp_init_set + mp_init_set_int + mp_init_size + mp_init_u32 + mp_init_u64 + mp_init_ul + mp_init_ull + mp_invmod + mp_is_square + mp_iseven + mp_isodd + mp_kronecker + mp_lcm + mp_log_u32 + mp_lshd + mp_mod + mp_mod_2d + mp_mod_d + mp_montgomery_calc_normalization + mp_montgomery_reduce + mp_montgomery_setup + mp_mul + mp_mul_2 + mp_mul_2d + mp_mul_d + mp_mulmod + mp_neg + mp_or + mp_pack + mp_pack_count + mp_prime_fermat + mp_prime_frobenius_underwood + mp_prime_is_prime + mp_prime_miller_rabin + mp_prime_next_prime + mp_prime_rabin_miller_trials + mp_prime_rand + mp_prime_strong_lucas_selfridge + mp_radix_size + mp_rand + mp_read_radix + mp_reduce + mp_reduce_2k + mp_reduce_2k_l + mp_reduce_2k_setup + mp_reduce_2k_setup_l + mp_reduce_is_2k + mp_reduce_is_2k_l + mp_reduce_setup + mp_root_u32 + mp_rshd + mp_sbin_size + mp_set + mp_set_double + mp_set_i32 + mp_set_i64 + mp_set_int + mp_set_l + mp_set_ll + mp_set_long + mp_set_long_long + mp_set_u32 + mp_set_u64 + mp_set_ul + mp_set_ull + mp_shrink + mp_signed_rsh + mp_sqr + mp_sqrmod + mp_sqrt + mp_sqrtmod_prime + mp_sub + mp_sub_d + mp_submod + mp_to_radix + mp_to_sbin + mp_to_ubin + mp_ubin_size + mp_unpack + mp_xor + mp_zero diff --git a/lib/hcrypto/libtommath/tommath.h b/lib/hcrypto/libtommath/tommath.h index e5d8d5367..e87bb086c 100644 --- a/lib/hcrypto/libtommath/tommath.h +++ b/lib/hcrypto/libtommath/tommath.h @@ -1,497 +1,692 @@ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is a library that provides multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library was designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * 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 - */ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + #ifndef BN_H_ #define BN_H_ -#include -#include -#include -#include +#include +#include #include -#include - -#ifndef MIN - #define MIN(x,y) ((x)<(y)?(x):(y)) +#ifdef LTM_NO_FILE +# warning LTM_NO_FILE has been deprecated, use MP_NO_FILE. +# define MP_NO_FILE #endif -#ifndef MAX - #define MAX(x,y) ((x)>(y)?(x):(y)) +#ifndef MP_NO_FILE +# include +#endif + +#ifdef MP_8BIT +# ifdef _MSC_VER +# pragma message("8-bit (MP_8BIT) support is deprecated and will be dropped completely in the next version.") +# else +# warning "8-bit (MP_8BIT) support is deprecated and will be dropped completely in the next version." +# endif #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 +/* MS Visual C++ doesn't have a 128bit type for words, so fall back to 32bit MPI's (where words are 64bit) */ +#if (defined(_MSC_VER) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__)) && !defined(MP_64BIT) +# define MP_32BIT +#endif /* detect 64-bit mode if possible */ -#if defined(__x86_64__) && !defined(__ILP32__) - #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT)) - #define MP_64BIT - #endif +#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \ + defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ + defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \ + defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ + defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \ + defined(__LP64__) || defined(_LP64) || defined(__64BIT__) +# if !(defined(MP_64BIT) || defined(MP_32BIT) || defined(MP_16BIT) || defined(MP_8BIT)) +# if defined(__GNUC__) && !defined(__hppa) +/* we support 128bit integers only via: __attribute__((mode(TI))) */ +# define MP_64BIT +# else +/* otherwise we fall back to MP_32BIT even on 64bit platforms */ +# define MP_32BIT +# endif +# endif +#endif + +#ifdef MP_DIGIT_BIT +# error Defining MP_DIGIT_BIT is disallowed, use MP_8/16/31/32/64BIT #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 + * A "mp_digit" must be able to hold MP_DIGIT_BIT + 1 bits + * A "mp_word" must be able to hold 2*MP_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; +typedef uint8_t mp_digit; +typedef uint16_t private_mp_word; +# define MP_DIGIT_BIT 7 #elif defined(MP_16BIT) - typedef unsigned short mp_digit; - typedef unsigned long mp_word; +typedef uint16_t mp_digit; +typedef uint32_t private_mp_word; +# define MP_DIGIT_BIT 15 #elif defined(MP_64BIT) - /* for GCC only on supported platforms */ -#ifndef CRYPT - typedef unsigned long long ulong64; - typedef signed long long long64; +/* for GCC only on supported platforms */ +typedef uint64_t mp_digit; +#if defined(__GNUC__) +typedef unsigned long private_mp_word __attribute__((mode(TI))); #endif - - typedef unsigned long mp_digit; - typedef unsigned long mp_word __attribute__ ((mode(TI))); - - #define DIGIT_BIT 60 +# define MP_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 +typedef uint32_t mp_digit; +typedef uint64_t private_mp_word; +# ifdef MP_31BIT +/* + * This is an extension that uses 31-bit digits. + * Please be aware that not all functions support this size, especially s_mp_mul_digs_fast + * will be reduced to work on small numbers only: + * Up to 8 limbs, 248 bits instead of up to 512 limbs, 15872 bits with MP_28BIT. + */ +# define MP_DIGIT_BIT 31 +# else +/* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */ +# define MP_DIGIT_BIT 28 +# define MP_28BIT +# endif #endif - typedef unsigned long mp_digit; - typedef ulong64 mp_word; +/* mp_word is a private type */ +#define mp_word MP_DEPRECATED_PRAGMA("mp_word has been made private") private_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 MP_SIZEOF_MP_DIGIT (MP_DEPRECATED_PRAGMA("MP_SIZEOF_MP_DIGIT has been deprecated, use sizeof (mp_digit)") sizeof (mp_digit)) -/* 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_MASK ((((mp_digit)1)<<((mp_digit)MP_DIGIT_BIT))-((mp_digit)1)) #define MP_DIGIT_MAX MP_MASK -/* equalities */ +/* Primality generation flags */ +#define MP_PRIME_BBS 0x0001 /* BBS style prime */ +#define MP_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ +#define MP_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ + +#define LTM_PRIME_BBS (MP_DEPRECATED_PRAGMA("LTM_PRIME_BBS has been deprecated, use MP_PRIME_BBS") MP_PRIME_BBS) +#define LTM_PRIME_SAFE (MP_DEPRECATED_PRAGMA("LTM_PRIME_SAFE has been deprecated, use MP_PRIME_SAFE") MP_PRIME_SAFE) +#define LTM_PRIME_2MSB_ON (MP_DEPRECATED_PRAGMA("LTM_PRIME_2MSB_ON has been deprecated, use MP_PRIME_2MSB_ON") MP_PRIME_2MSB_ON) + +#ifdef MP_USE_ENUMS +typedef enum { + MP_ZPOS = 0, /* positive */ + MP_NEG = 1 /* negative */ +} mp_sign; +typedef enum { + MP_LT = -1, /* less than */ + MP_EQ = 0, /* equal */ + MP_GT = 1 /* greater than */ +} mp_ord; +typedef enum { + MP_NO = 0, + MP_YES = 1 +} mp_bool; +typedef enum { + MP_OKAY = 0, /* no error */ + MP_ERR = -1, /* unknown error */ + MP_MEM = -2, /* out of mem */ + MP_VAL = -3, /* invalid input */ + MP_ITER = -4, /* maximum iterations reached */ + MP_BUF = -5 /* buffer overflow, supplied buffer too small */ +} mp_err; +typedef enum { + MP_LSB_FIRST = -1, + MP_MSB_FIRST = 1 +} mp_order; +typedef enum { + MP_LITTLE_ENDIAN = -1, + MP_NATIVE_ENDIAN = 0, + MP_BIG_ENDIAN = 1 +} mp_endian; +#else +typedef int mp_sign; +#define MP_ZPOS 0 /* positive integer */ +#define MP_NEG 1 /* negative */ +typedef int mp_ord; #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 */ +typedef int mp_bool; +#define MP_YES 1 +#define MP_NO 0 +typedef int mp_err; +#define MP_OKAY 0 /* no error */ +#define MP_ERR -1 /* unknown error */ #define MP_MEM -2 /* out of mem */ #define MP_VAL -3 /* invalid input */ -#define MP_RANGE MP_VAL +#define MP_RANGE (MP_DEPRECATED_PRAGMA("MP_RANGE has been deprecated in favor of MP_VAL") MP_VAL) +#define MP_ITER -4 /* maximum iterations reached */ +#define MP_BUF -5 /* buffer overflow, supplied buffer too small */ +typedef int mp_order; +#define MP_LSB_FIRST -1 +#define MP_MSB_FIRST 1 +typedef int mp_endian; +#define MP_LITTLE_ENDIAN -1 +#define MP_NATIVE_ENDIAN 0 +#define MP_BIG_ENDIAN 1 +#endif -#define MP_YES 1 /* yes response */ -#define MP_NO 0 /* no response */ +/* tunable cutoffs */ -/* 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; +#ifndef MP_FIXED_CUTOFFS +extern int +KARATSUBA_MUL_CUTOFF, +KARATSUBA_SQR_CUTOFF, +TOOM_MUL_CUTOFF, +TOOM_SQR_CUTOFF; +#endif /* 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 +# ifndef MP_LOW_MEM +# define PRIVATE_MP_PREC 32 /* default digits of precision */ +# elif defined(MP_8BIT) +# define PRIVATE_MP_PREC 16 /* default digits of precision */ +# else +# define PRIVATE_MP_PREC 8 /* default digits of precision */ +# endif +# define MP_PREC (MP_DEPRECATED_PRAGMA("MP_PREC is an internal macro") PRIVATE_MP_PREC) #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)) +#define PRIVATE_MP_WARRAY (int)(1uLL << (((CHAR_BIT * sizeof(private_mp_word)) - (2 * MP_DIGIT_BIT)) + 1)) +#define MP_WARRAY (MP_DEPRECATED_PRAGMA("MP_WARRAY is an internal macro") PRIVATE_MP_WARRAY) + +#if defined(__GNUC__) && __GNUC__ >= 4 +# define MP_NULL_TERMINATED __attribute__((sentinel)) +#else +# define MP_NULL_TERMINATED +#endif + +/* + * MP_WUR - warn unused result + * --------------------------- + * + * The result of functions annotated with MP_WUR must be + * checked and cannot be ignored. + * + * Most functions in libtommath return an error code. + * This error code must be checked in order to prevent crashes or invalid + * results. + * + * If you still want to avoid the error checks for quick and dirty programs + * without robustness guarantees, you can `#define MP_WUR` before including + * tommath.h, disabling the warnings. + */ +#ifndef MP_WUR +# if defined(__GNUC__) && __GNUC__ >= 4 +# define MP_WUR __attribute__((warn_unused_result)) +# else +# define MP_WUR +# endif +#endif + +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405) +# define MP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x))) +# define PRIVATE_MP_DEPRECATED_PRAGMA(s) _Pragma(#s) +# define MP_DEPRECATED_PRAGMA(s) PRIVATE_MP_DEPRECATED_PRAGMA(GCC warning s) +#elif defined(_MSC_VER) && _MSC_VER >= 1500 +# define MP_DEPRECATED(x) __declspec(deprecated("replaced by " #x)) +# define MP_DEPRECATED_PRAGMA(s) __pragma(message(s)) +#else +# define MP_DEPRECATED(s) +# define MP_DEPRECATED_PRAGMA(s) +#endif + +#define DIGIT_BIT (MP_DEPRECATED_PRAGMA("DIGIT_BIT macro is deprecated, MP_DIGIT_BIT instead") MP_DIGIT_BIT) +#define USED(m) (MP_DEPRECATED_PRAGMA("USED macro is deprecated, use z->used instead") (m)->used) +#define DIGIT(m, k) (MP_DEPRECATED_PRAGMA("DIGIT macro is deprecated, use z->dp instead") (m)->dp[(k)]) +#define SIGN(m) (MP_DEPRECATED_PRAGMA("SIGN macro is deprecated, use z->sign instead") (m)->sign) /* the infamous mp_int structure */ typedef struct { - int used, alloc, sign; - mp_digit *dp; + int used, alloc; + mp_sign 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); +typedef int private_mp_prime_callback(unsigned char *dst, int len, void *dat); +typedef private_mp_prime_callback MP_DEPRECATED(mp_rand_source) ltm_prime_callback; - -#define USED(m) ((m)->used) -#define DIGIT(m,k) ((m)->dp[(k)]) -#define SIGN(m) ((m)->sign) - -/* error code to const char* string */ -const char *mp_error_to_string(int code); +/* error code to char* string */ +const char *mp_error_to_string(mp_err code) MP_WUR; /* ---> init and deinit bignum functions <--- */ /* init a bignum */ -int mp_init(mp_int *a); +mp_err mp_init(mp_int *a) MP_WUR; /* free a bignum */ void mp_clear(mp_int *a); /* init a null terminated series of arguments */ -int mp_init_multi(mp_int *mp, ...); +mp_err mp_init_multi(mp_int *mp, ...) MP_NULL_TERMINATED MP_WUR; /* clear a null terminated series of arguments */ -void mp_clear_multi(mp_int *mp, ...); +void mp_clear_multi(mp_int *mp, ...) MP_NULL_TERMINATED; /* exchange two ints */ void mp_exch(mp_int *a, mp_int *b); /* shrink ram required for a bignum */ -int mp_shrink(mp_int *a); +mp_err mp_shrink(mp_int *a) MP_WUR; /* grow an int to a given size */ -int mp_grow(mp_int *a, int size); +mp_err mp_grow(mp_int *a, int size) MP_WUR; /* init to a given number of digits */ -int mp_init_size(mp_int *a, int size); +mp_err mp_init_size(mp_int *a, int size) MP_WUR; /* ---> 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) -#define mp_isneg(a) (((a)->sign) ? MP_YES : MP_NO) +mp_bool mp_iseven(const mp_int *a) MP_WUR; +mp_bool mp_isodd(const mp_int *a) MP_WUR; +#define mp_isneg(a) (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO) /* set to zero */ void mp_zero(mp_int *a); -/* set to zero, multi */ -void mp_zero_multi(mp_int *a, ...); +/* get and set doubles */ +double mp_get_double(const mp_int *a) MP_WUR; +mp_err mp_set_double(mp_int *a, double b) MP_WUR; -/* set to a digit */ +/* get integer, set integer and init with integer (int32_t) */ +int32_t mp_get_i32(const mp_int *a) MP_WUR; +void mp_set_i32(mp_int *a, int32_t b); +mp_err mp_init_i32(mp_int *a, int32_t b) MP_WUR; + +/* get integer, set integer and init with integer, behaves like two complement for negative numbers (uint32_t) */ +#define mp_get_u32(a) ((uint32_t)mp_get_i32(a)) +void mp_set_u32(mp_int *a, uint32_t b); +mp_err mp_init_u32(mp_int *a, uint32_t b) MP_WUR; + +/* get integer, set integer and init with integer (int64_t) */ +int64_t mp_get_i64(const mp_int *a) MP_WUR; +void mp_set_i64(mp_int *a, int64_t b); +mp_err mp_init_i64(mp_int *a, int64_t b) MP_WUR; + +/* get integer, set integer and init with integer, behaves like two complement for negative numbers (uint64_t) */ +#define mp_get_u64(a) ((uint64_t)mp_get_i64(a)) +void mp_set_u64(mp_int *a, uint64_t b); +mp_err mp_init_u64(mp_int *a, uint64_t b) MP_WUR; + +/* get magnitude */ +uint32_t mp_get_mag_u32(const mp_int *a) MP_WUR; +uint64_t mp_get_mag_u64(const mp_int *a) MP_WUR; +unsigned long mp_get_mag_ul(const mp_int *a) MP_WUR; +unsigned long long mp_get_mag_ull(const mp_int *a) MP_WUR; + +/* get integer, set integer (long) */ +long mp_get_l(const mp_int *a) MP_WUR; +void mp_set_l(mp_int *a, long b); +mp_err mp_init_l(mp_int *a, long b) MP_WUR; + +/* get integer, set integer (unsigned long) */ +#define mp_get_ul(a) ((unsigned long)mp_get_l(a)) +void mp_set_ul(mp_int *a, unsigned long b); +mp_err mp_init_ul(mp_int *a, unsigned long b) MP_WUR; + +/* get integer, set integer (long long) */ +long long mp_get_ll(const mp_int *a) MP_WUR; +void mp_set_ll(mp_int *a, long long b); +mp_err mp_init_ll(mp_int *a, long long b) MP_WUR; + +/* get integer, set integer (unsigned long long) */ +#define mp_get_ull(a) ((unsigned long long)mp_get_ll(a)) +void mp_set_ull(mp_int *a, unsigned long long b); +mp_err mp_init_ull(mp_int *a, unsigned long long b) MP_WUR; + +/* set to single unsigned digit, up to MP_DIGIT_MAX */ void mp_set(mp_int *a, mp_digit b); +mp_err mp_init_set(mp_int *a, mp_digit b) MP_WUR; -/* 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); +/* get integer, set integer and init with integer (deprecated) */ +MP_DEPRECATED(mp_get_mag_u32/mp_get_u32) unsigned long mp_get_int(const mp_int *a) MP_WUR; +MP_DEPRECATED(mp_get_mag_ul/mp_get_ul) unsigned long mp_get_long(const mp_int *a) MP_WUR; +MP_DEPRECATED(mp_get_mag_ull/mp_get_ull) unsigned long long mp_get_long_long(const mp_int *a) MP_WUR; +MP_DEPRECATED(mp_set_ul) mp_err mp_set_int(mp_int *a, unsigned long b); +MP_DEPRECATED(mp_set_ul) mp_err mp_set_long(mp_int *a, unsigned long b); +MP_DEPRECATED(mp_set_ull) mp_err mp_set_long_long(mp_int *a, unsigned long long b); +MP_DEPRECATED(mp_init_ul) mp_err mp_init_set_int(mp_int *a, unsigned long b) MP_WUR; /* copy, b = a */ -int mp_copy(mp_int *a, mp_int *b); +mp_err mp_copy(const mp_int *a, mp_int *b) MP_WUR; /* inits and copies, a = b */ -int mp_init_copy(mp_int *a, mp_int *b); +mp_err mp_init_copy(mp_int *a, const mp_int *b) MP_WUR; /* trim unused digits */ void mp_clamp(mp_int *a); + +/* export binary data */ +MP_DEPRECATED(mp_pack) mp_err mp_export(void *rop, size_t *countp, int order, size_t size, + int endian, size_t nails, const mp_int *op) MP_WUR; + +/* import binary data */ +MP_DEPRECATED(mp_unpack) mp_err mp_import(mp_int *rop, size_t count, int order, + size_t size, int endian, size_t nails, + const void *op) MP_WUR; + +/* unpack binary data */ +mp_err mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size, mp_endian endian, + size_t nails, const void *op) MP_WUR; + +/* pack binary data */ +size_t mp_pack_count(const mp_int *a, size_t nails, size_t size) MP_WUR; +mp_err mp_pack(void *rop, size_t maxcount, size_t *written, mp_order order, size_t size, + mp_endian endian, size_t nails, const mp_int *op) MP_WUR; + /* ---> 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); +mp_err mp_lshd(mp_int *a, int b) MP_WUR; -/* c = a / 2**b */ -int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d); +/* c = a / 2**b, implemented as c = a >> b */ +mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) MP_WUR; /* b = a/2 */ -int mp_div_2(mp_int *a, mp_int *b); +mp_err mp_div_2(const mp_int *a, mp_int *b) MP_WUR; -/* c = a * 2**b */ -int mp_mul_2d(mp_int *a, int b, mp_int *c); +/* a/3 => 3c + d == a */ +mp_err mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR; + +/* c = a * 2**b, implemented as c = a << b */ +mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) MP_WUR; /* b = a*2 */ -int mp_mul_2(mp_int *a, mp_int *b); +mp_err mp_mul_2(const mp_int *a, mp_int *b) MP_WUR; -/* c = a mod 2**d */ -int mp_mod_2d(mp_int *a, int b, mp_int *c); +/* c = a mod 2**b */ +mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c) MP_WUR; /* computes a = 2**b */ -int mp_2expt(mp_int *a, int b); +mp_err mp_2expt(mp_int *a, int b) MP_WUR; /* Counts the number of lsbs which are zero before the first zero bit */ -int mp_cnt_lsb(mp_int *a); +int mp_cnt_lsb(const mp_int *a) MP_WUR; /* I Love Earth! */ -/* makes a pseudo-random int of a given size */ -int mp_rand(mp_int *a, int digits); +/* makes a pseudo-random mp_int of a given size */ +mp_err mp_rand(mp_int *a, int digits) MP_WUR; +/* makes a pseudo-random small int of a given size */ +MP_DEPRECATED(mp_rand) mp_err mp_rand_digit(mp_digit *r) MP_WUR; +/* use custom random data source instead of source provided the platform */ +void mp_rand_source(mp_err(*source)(void *out, size_t size)); + +#ifdef MP_PRNG_ENABLE_LTM_RNG +# warning MP_PRNG_ENABLE_LTM_RNG has been deprecated, use mp_rand_source instead. +/* A last resort to provide random data on systems without any of the other + * implemented ways to gather entropy. + * It is compatible with `rng_get_bytes()` from libtomcrypt so you could + * provide that one and then set `ltm_rng = rng_get_bytes;` */ +extern unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); +extern void (*ltm_rng_callback)(void); +#endif /* ---> 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); +/* Checks the bit at position b and returns MP_YES + * if the bit is 1, MP_NO if it is 0 and MP_VAL + * in case of error + */ +MP_DEPRECATED(s_mp_get_bit) int mp_get_bit(const mp_int *a, int b) MP_WUR; -/* c = a AND b */ -int mp_and(mp_int *a, mp_int *b, mp_int *c); +/* c = a XOR b (two complement) */ +MP_DEPRECATED(mp_xor) mp_err mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = a OR b (two complement) */ +MP_DEPRECATED(mp_or) mp_err mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = a AND b (two complement) */ +MP_DEPRECATED(mp_and) mp_err mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* b = ~a (bitwise not, two complement) */ +mp_err mp_complement(const mp_int *a, mp_int *b) MP_WUR; + +/* right shift with sign extension */ +MP_DEPRECATED(mp_signed_rsh) mp_err mp_tc_div_2d(const mp_int *a, int b, mp_int *c) MP_WUR; +mp_err mp_signed_rsh(const mp_int *a, int b, mp_int *c) MP_WUR; /* ---> Basic arithmetic <--- */ /* b = -a */ -int mp_neg(mp_int *a, mp_int *b); +mp_err mp_neg(const mp_int *a, mp_int *b) MP_WUR; /* b = |a| */ -int mp_abs(mp_int *a, mp_int *b); +mp_err mp_abs(const mp_int *a, mp_int *b) MP_WUR; /* compare a to b */ -int mp_cmp(mp_int *a, mp_int *b); +mp_ord mp_cmp(const mp_int *a, const mp_int *b) MP_WUR; /* compare |a| to |b| */ -int mp_cmp_mag(mp_int *a, mp_int *b); +mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b) MP_WUR; /* c = a + b */ -int mp_add(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* c = a - b */ -int mp_sub(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* c = a * b */ -int mp_mul(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* b = a*a */ -int mp_sqr(mp_int *a, mp_int *b); +mp_err mp_sqr(const mp_int *a, mp_int *b) MP_WUR; /* a/b => cb + d == a */ -int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d); +mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) MP_WUR; /* c = a mod b, 0 <= c < b */ -int mp_mod(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_mod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* Increment "a" by one like "a++". Changes input! */ +mp_err mp_incr(mp_int *a) MP_WUR; + +/* Decrement "a" by one like "a--". Changes input! */ +mp_err mp_decr(mp_int *a) MP_WUR; /* ---> single digit functions <--- */ /* compare against a single digit */ -int mp_cmp_d(mp_int *a, mp_digit b); +mp_ord mp_cmp_d(const mp_int *a, mp_digit b) MP_WUR; /* c = a + b */ -int mp_add_d(mp_int *a, mp_digit b, mp_int *c); +mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; /* c = a - b */ -int mp_sub_d(mp_int *a, mp_digit b, mp_int *c); +mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; /* c = a * b */ -int mp_mul_d(mp_int *a, mp_digit b, mp_int *c); +mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; /* 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); +mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) MP_WUR; /* c = a mod b, 0 <= c < b */ -int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c); +mp_err mp_mod_d(const mp_int *a, mp_digit b, mp_digit *c) MP_WUR; /* ---> number theory <--- */ /* d = a + b (mod c) */ -int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); +mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) MP_WUR; /* d = a - b (mod c) */ -int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); +mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) MP_WUR; /* d = a * b (mod c) */ -int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); +mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) MP_WUR; /* c = a * a (mod b) */ -int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* c = 1/a (mod b) */ -int mp_invmod(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* c = (a, b) */ -int mp_gcd(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_gcd(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 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); +mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) MP_WUR; /* c = [a, b] or (a*b)/(a, b) */ -int mp_lcm(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; /* 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); +mp_err mp_root_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR; +MP_DEPRECATED(mp_root_u32) mp_err mp_n_root(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; +MP_DEPRECATED(mp_root_u32) mp_err mp_n_root_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR; /* special sqrt algo */ -int mp_sqrt(mp_int *arg, mp_int *ret); +mp_err mp_sqrt(const mp_int *arg, mp_int *ret) MP_WUR; + +/* special sqrt (mod prime) */ +mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) MP_WUR; /* is number a square? */ -int mp_is_square(mp_int *arg, int *ret); +mp_err mp_is_square(const mp_int *arg, mp_bool *ret) MP_WUR; /* computes the jacobi c = (a | n) (or Legendre if b is prime) */ -int mp_jacobi(mp_int *a, mp_int *n, int *c); +MP_DEPRECATED(mp_kronecker) mp_err mp_jacobi(const mp_int *a, const mp_int *n, int *c) MP_WUR; + +/* computes the Kronecker symbol c = (a | p) (like jacobi() but with {a,p} in Z */ +mp_err mp_kronecker(const mp_int *a, const mp_int *p, int *c) MP_WUR; /* used to setup the Barrett reduction for a given modulus b */ -int mp_reduce_setup(mp_int *a, mp_int *b); +mp_err mp_reduce_setup(mp_int *a, const mp_int *b) MP_WUR; /* 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]. + * Assumes that 0 < x <= m*m, note if 0 > x > -(m*m) then you can merely + * compute the reduction as -1 * mp_reduce(mp_abs(x)) [pseudo code]. */ -int mp_reduce(mp_int *a, mp_int *b, mp_int *c); +mp_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu) MP_WUR; /* setups the montgomery reduction */ -int mp_montgomery_setup(mp_int *a, mp_digit *mp); +mp_err mp_montgomery_setup(const mp_int *n, mp_digit *rho) MP_WUR; /* 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); +mp_err mp_montgomery_calc_normalization(mp_int *a, const mp_int *b) MP_WUR; /* computes x/R == x (mod N) via Montgomery Reduction */ -int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); +mp_err mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR; /* returns 1 if a is a valid DR modulus */ -int mp_dr_is_modulus(mp_int *a); +mp_bool mp_dr_is_modulus(const mp_int *a) MP_WUR; /* sets the value of "d" required for mp_dr_reduce */ -void mp_dr_setup(mp_int *a, mp_digit *d); +void mp_dr_setup(const 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); +/* reduces a modulo n using the Diminished Radix method */ +mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k) MP_WUR; /* returns true if a can be reduced with mp_reduce_2k */ -int mp_reduce_is_2k(mp_int *a); +mp_bool mp_reduce_is_2k(const mp_int *a) MP_WUR; /* determines k value for 2k reduction */ -int mp_reduce_2k_setup(mp_int *a, mp_digit *d); +mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d) MP_WUR; /* 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); +mp_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d) MP_WUR; /* returns true if a can be reduced with mp_reduce_2k_l */ -int mp_reduce_is_2k_l(mp_int *a); +mp_bool mp_reduce_is_2k_l(const mp_int *a) MP_WUR; /* determines k value for 2k reduction */ -int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); +mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d) MP_WUR; /* 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); +mp_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d) MP_WUR; -/* d = a**b (mod c) */ -int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); +/* Y = G**X (mod P) */ +mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) MP_WUR; /* ---> Primes <--- */ /* number of primes */ #ifdef MP_8BIT - #define PRIME_SIZE 31 +# define PRIVATE_MP_PRIME_TAB_SIZE 31 #else - #define PRIME_SIZE 256 +# define PRIVATE_MP_PRIME_TAB_SIZE 256 #endif +#define PRIME_SIZE (MP_DEPRECATED_PRAGMA("PRIME_SIZE has been made internal") PRIVATE_MP_PRIME_TAB_SIZE) /* table of first PRIME_SIZE primes */ -extern const mp_digit ltm_prime_tab[]; +MP_DEPRECATED(internal) extern const mp_digit ltm_prime_tab[PRIVATE_MP_PRIME_TAB_SIZE]; /* result=1 if a is divisible by one of the first PRIME_SIZE primes */ -int mp_prime_is_divisible(mp_int *a, int *result); +MP_DEPRECATED(mp_prime_is_prime) mp_err mp_prime_is_divisible(const mp_int *a, mp_bool *result) MP_WUR; /* 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); +mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, mp_bool *result) MP_WUR; /* 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); +mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, mp_bool *result) MP_WUR; /* 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); +int mp_prime_rabin_miller_trials(int size) MP_WUR; -/* performs t rounds of Miller-Rabin on "a" using the first - * t prime bases. Also performs an initial sieve of trial +/* performs one strong Lucas-Selfridge test of "a". + * Sets result to 0 if composite or 1 if probable prime + */ +mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, mp_bool *result) MP_WUR; + +/* performs one Frobenius test of "a" as described by Paul Underwood. + * Sets result to 0 if composite or 1 if probable prime + */ +mp_err mp_prime_frobenius_underwood(const mp_int *N, mp_bool *result) MP_WUR; + +/* performs t random rounds of Miller-Rabin on "a" additional to + * bases 2 and 3. Also performs an initial sieve of trial * division. Determines if "a" is prime with probability * of error no more than (1/4)**t. + * Both a strong Lucas-Selfridge to complete the BPSW test + * and a separate Frobenius test are available at compile time. + * With t<0 a deterministic test is run for primes up to + * 318665857834031151167461. With t<13 (abs(t)-13) additional + * tests with sequential small primes are run starting at 43. + * Is Fips 186.4 compliant if called with t as computed by + * mp_prime_rabin_miller_trials(); * * Sets result to 1 if probably prime, 0 otherwise */ -int mp_prime_is_prime(mp_int *a, int t, int *result); +mp_err mp_prime_is_prime(const mp_int *a, int t, mp_bool *result) MP_WUR; /* 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); +mp_err mp_prime_next_prime(mp_int *a, int t, int bbs_style) MP_WUR; /* 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 @@ -502,89 +697,85 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style); * * 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) +#define mp_prime_random(a, t, size, bbs, cb, dat) (MP_DEPRECATED_PRAGMA("mp_prime_random has been deprecated, use mp_prime_rand instead") mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?MP_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 + * MP_PRIME_BBS - make prime congruent to 3 mod 4 + * MP_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS) + * MP_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); +MP_DEPRECATED(mp_prime_rand) mp_err mp_prime_random_ex(mp_int *a, int t, int size, int flags, + private_mp_prime_callback cb, void *dat) MP_WUR; +mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) MP_WUR; -int mp_find_prime(mp_int *a, int t); +/* Integer logarithm to integer base */ +mp_err mp_log_u32(const mp_int *a, uint32_t base, uint32_t *c) MP_WUR; + +/* c = a**b */ +mp_err mp_expt_u32(const mp_int *a, uint32_t b, mp_int *c) MP_WUR; +MP_DEPRECATED(mp_expt_u32) mp_err mp_expt_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; +MP_DEPRECATED(mp_expt_u32) mp_err mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) MP_WUR; /* ---> radix conversion <--- */ -int mp_count_bits(mp_int *a); +int mp_count_bits(const mp_int *a) MP_WUR; -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); +MP_DEPRECATED(mp_ubin_size) int mp_unsigned_bin_size(const mp_int *a) MP_WUR; +MP_DEPRECATED(mp_from_ubin) mp_err mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c) MP_WUR; +MP_DEPRECATED(mp_to_ubin) mp_err mp_to_unsigned_bin(const mp_int *a, unsigned char *b) MP_WUR; +MP_DEPRECATED(mp_to_ubin) mp_err mp_to_unsigned_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen) MP_WUR; -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); +MP_DEPRECATED(mp_sbin_size) int mp_signed_bin_size(const mp_int *a) MP_WUR; +MP_DEPRECATED(mp_from_sbin) mp_err mp_read_signed_bin(mp_int *a, const unsigned char *b, int c) MP_WUR; +MP_DEPRECATED(mp_to_sbin) mp_err mp_to_signed_bin(const mp_int *a, unsigned char *b) MP_WUR; +MP_DEPRECATED(mp_to_sbin) mp_err mp_to_signed_bin_n(const mp_int *a, unsigned char *b, unsigned long *outlen) MP_WUR; -int mp_fread(mp_int *a, int radix, FILE *stream); -int mp_fwrite(mp_int *a, int radix, FILE *stream); +size_t mp_ubin_size(const mp_int *a) MP_WUR; +mp_err mp_from_ubin(mp_int *a, const unsigned char *buf, size_t size) MP_WUR; +mp_err mp_to_ubin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) MP_WUR; -#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)) +size_t mp_sbin_size(const mp_int *a) MP_WUR; +mp_err mp_from_sbin(mp_int *a, const unsigned char *buf, size_t size) MP_WUR; +mp_err mp_to_sbin(const mp_int *a, unsigned char *buf, size_t maxlen, size_t *written) MP_WUR; -#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) +mp_err mp_read_radix(mp_int *a, const char *str, int radix) MP_WUR; +MP_DEPRECATED(mp_to_radix) mp_err mp_toradix(const mp_int *a, char *str, int radix) MP_WUR; +MP_DEPRECATED(mp_to_radix) mp_err mp_toradix_n(const mp_int *a, char *str, int radix, int maxlen) MP_WUR; +mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) MP_WUR; +mp_err mp_radix_size(const mp_int *a, int radix, int *size) MP_WUR; -/* 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); +#ifndef MP_NO_FILE +mp_err mp_fread(mp_int *a, int radix, FILE *stream) MP_WUR; +mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) MP_WUR; +#endif -extern const char *mp_s_rmap; +#define mp_read_raw(mp, str, len) (MP_DEPRECATED_PRAGMA("replaced by mp_read_signed_bin") mp_read_signed_bin((mp), (str), (len))) +#define mp_raw_size(mp) (MP_DEPRECATED_PRAGMA("replaced by mp_signed_bin_size") mp_signed_bin_size(mp)) +#define mp_toraw(mp, str) (MP_DEPRECATED_PRAGMA("replaced by mp_to_signed_bin") mp_to_signed_bin((mp), (str))) +#define mp_read_mag(mp, str, len) (MP_DEPRECATED_PRAGMA("replaced by mp_read_unsigned_bin") mp_read_unsigned_bin((mp), (str), (len)) +#define mp_mag_size(mp) (MP_DEPRECATED_PRAGMA("replaced by mp_unsigned_bin_size") mp_unsigned_bin_size(mp)) +#define mp_tomag(mp, str) (MP_DEPRECATED_PRAGMA("replaced by mp_to_unsigned_bin") mp_to_unsigned_bin((mp), (str))) + +#define mp_tobinary(M, S) (MP_DEPRECATED_PRAGMA("replaced by mp_to_binary") mp_toradix((M), (S), 2)) +#define mp_tooctal(M, S) (MP_DEPRECATED_PRAGMA("replaced by mp_to_octal") mp_toradix((M), (S), 8)) +#define mp_todecimal(M, S) (MP_DEPRECATED_PRAGMA("replaced by mp_to_decimal") mp_toradix((M), (S), 10)) +#define mp_tohex(M, S) (MP_DEPRECATED_PRAGMA("replaced by mp_to_hex") mp_toradix((M), (S), 16)) + +#define mp_to_binary(M, S, N) mp_to_radix((M), (S), (N), NULL, 2) +#define mp_to_octal(M, S, N) mp_to_radix((M), (S), (N), NULL, 8) +#define mp_to_decimal(M, S, N) mp_to_radix((M), (S), (N), NULL, 10) +#define mp_to_hex(M, S, N) mp_to_radix((M), (S), (N), NULL, 16) #ifdef __cplusplus - } +} #endif #endif - - -/* $Source: /cvs/libtom/libtommath/tommath.h,v $ */ -/* $Revision: 1.8 $ */ -/* $Date: 2006/03/31 14:18:44 $ */ diff --git a/lib/hcrypto/libtommath/tommath.out b/lib/hcrypto/libtommath/tommath.out deleted file mode 100644 index 9f6261727..000000000 --- a/lib/hcrypto/libtommath/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/lib/hcrypto/libtommath/tommath.pdf b/lib/hcrypto/libtommath/tommath.pdf deleted file mode 100644 index 33994c35a81f43911b05ffca60e0b6066954fcfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1183099 zcmY!laBe~m5?D_MbR+n$BteVsQ`M0mFY(d3tH+!?~ z(lK>ESZ!_YXE{k4FemaH{&t&9+`^5~&)G*ZNOD{FZ2fl`b8HHHG+n=Et9&?Nx%+gX zlY-|XIh{u;hu$UG{z(o@;Cy1&Bj+VD?a@1_FK4twbq>DGIx^*2iAcG1y7N1qDVA9VZ8-%y0_aaeZ^})jhJ_ z0hgw%Rb^BS@(n-LDYA5qU2l})lv{0_qEdHH7j`}9yt-`jL`5|ow<}SVTv~^lQ{Ee{ z*ufClv_Wvz6d$fz6;5o1T2l`i`!0zId7bL3B0t$WKgB9;?eVo@dRmKKEa3YRdVNOe zz7y|Sm6W}!R5rXWxw$FLP-bQRek~JDE6q0^_YPZYLo^&>Om$b-dzq1nAtshjG&e$yXKmEh+U16%n-_&JYW}4xxf9;IY z#iP-Cv^3xBebjTR(?O#k;>JWb?cJ|y3ogpsUHe9?H;&ux#wWF@3vXGy*?)Mh=<5$x z)`#5sX1Z=>*hv^mU(|LShY%^xN!gLZ32^bikM#0j!KVc&bsuvkZZ!8b05|v z-|De5pS)wztG0^bj1KMVm1=@Px$TbXyW?l}=c>(r{V(0`u5U%UOw*0oS9L!aomkTT z`P9a|qZ4;dJ$T5{-mrZ7qKmK8FIblqeTXWtGi%^fV*0%9#_Ql;f6duq*X}!dPE1`? z|CiI*-P0x?Zu_cRlf;m}e(U09hWlk&_DbKfcK=*4e}DRX?+dAUDbUoJnwJ7f(V%n; zrp*kvphAY2sofByj9_w~8tz>zV=A!k{rVY?d5&_d{Q8WAbEiOX;|BIs8hqQX-;}7{ zd&I2&!|RvxF0QCHGkQ9OKd>tL?)+ar&$jz%U(Woc{Xb65EPikA-G7P3p4ON5u3J9) zYt2Z9yRx68q%5bpscDZ!$mtHBsu-~Sd7Ph&ck?U!;}%rJ-Vul->Tt}UKo_42u8Ue)S8bNLsC zYd+0U4>r_b-?sli^a7?CQ*{gXC`UVH3jeZSwKlpf^vtpw@#m)7EO~0DFirO0HZA2F zKMhwHNPpE*55Fh$nMt%}*=sX((Sw}x>#tpQ4V_cCW9vunPZA*=l5_RT`-IQr^t|V1 zK6WxIm+PBn#o1}^R#lqz9E@<))O>mITFoTcPmzU~lLIz!v8p`cu z9bdN`zrXE%zCxqZmI(9PvSM8wx|N}~BE5WlA8%B9vW{u);|YRSCRM%X4(gwA)B2~h z;_;IYGZM;9em$1IT;}GIn*ZYaeZ#M>aywRZGj&hWrb~(^-MgZ8uif7AVM*Te?~}?O zPg#9_>HPbGDgnXFfA}95Z_1rp=BV;v(W_i`o$D=swUjKU^0>(Vk`LgQITj?=zvkh^ zrqGLNfjggWe6ZZ6eZhv`x&MDR{8-DUV60Wu(R(c+sH|X7ie=z|2a(B(&Y9iTUuO7d z!+MiNR({846mrQ3G+xv?dgXtNNYav^FA=7Z$NyPRi~G3MdRpA(FAKdm`wcV9jvw8h z_`hwv#JB%Vx%13z?{56EOY`ny!R5}I*43Zp+P%tP;VQ<;!wqsbk0lEqz3=;S`kVK@ z!U4B$)EZYD_it*yAhu?`r1poY#(eVTY$sX2VfR(?LGt()&{zTSjh zmt)Nm(WEKoUV7eQa#@|=T6#cxzF~uJnnHlldka_3@*7Fn2fI^SBwdRZzcI;jd}w8~ z?R)B1tCK5^ES+ipL#FAD+xHUf#ETUht5}17l^^{vZM(5u)QJ-XnfbG3o?_{55K|Mr zS)Z}y7IWowE$amb_iR{ybMLjl3A2vwRL}Ex$S3)$zxeM9gW_3BPJWKKF3Q*-$?!4d zeCy($Ct95oGQ!mY^_pfH6fgY1JZ*7*)5d8p63fD;Zv3-HzjW%S;+d!KG$mO5>FF@5 z%yN{mUgx~3i4LEwFf` z-gs=PN@f@9TGNHJR#=yl5PrleyT7%{;%y&e<-8w4-

b9P-d$eN&9-Pcf zd^uV1anMn{%btflKkKgfSmw*%pX7P$YPGJ(t$~3SsVb zSbNp-F6+{*+y3TWQQY}=W1d6A+K?aFAG!C-oK|RZUH$W^SZm0^>D|ANK02;0dc`*& zD8l5bXRlNBV%y$TI=u^gtyf)i-1*9RZHswO_N#`1}AZoLWzIkQ)@n@C={#Xd{xLc3P~)z=>n`hTh1vVbpRmGkZ0-z zKHej8E0*t{?5D;5)0Uk)(RWcZZj!vj&y5NH*V;;?PBN8bP`>rYY+c49wMkR09=qT4 zzV)hdZR@cGPOoI`KGZ7o3r{;?qUw3%S+wHhiG2^|3a1?3$5K#Tx8g+q<6Vx96S>u1 z|0*kC^L)&oocx7*vG&Y@N0!bVO~3B^n69a6V?A}je|G;xQDr8tozD79O$bqK?&v6+ z!}6!xv_H%7r^x3WhkC>&EN`$;{Uot%)8DN@tS;tGVJHs7XDOU#8>rA+}=k zl7kr^+g%wfTq-y4v%TounBvAD%308UWRuCBBi=@VlR53XefrB}B?~wmJ)>?e^jdoA z_C)UVk99qMp8qpimw!ICQh(;Y%LQT1f2>3#z8~bAT$J=kI!*F)(UAyk=kiYBpFxQ| z{r4YjJ~lVsR>tKU-+M3L39QB!dw%;UmOD;iNT~2wy@umbe16I|zRzroGgz$!8v;MN z?ER|rty5`bI=#=kWH$Vo zn?G53Lsq6jSX`jzx%WnwUzqw?KKyg1GRFVJ+ijhRV&$@h{ikfQizmkvZusu^Dr%{4 zN>SRZ9UUnjuAkx7=DGDM?|ovG=JF+;7f!wYb@kPvtJlOOS6ygcqS3lB`^z`QnSWcD zZ!_j!>YAutm@AML`RBo__>GO0)7~?C-JdMM!k!q)AM`M4`(rgoI|clk)h0=7GyA%k^F&I&$IJEQ zZI2$A+|soFczEZlXf@Sf#mbAW@wd3w?K-a<7;#N=_PoCJZ$6cn2=fbaD}Ro-%(Y|7 zv`ZGbElq3xeo_3Wu*Alrr{4EkYEkcQ?SJnjuO!Zib_vRFWv!1DxM{sdySZ5GqRQ7@ z$A2$%{CRSg`^K+TJH3{L?mM$Bzx(YZ{T+H5Z)7j!KHA!Q?oZjaTQk>GhM5*~PUTow z$Qd)`O#j>ktJlO{`)9jriol|PR|x{Qb^jOzm~1LEUN>p6V9w6kZ1ai_Q{-+Y%zJZ1 zHQMx|vX6+YmEP>*=XXv_3wNnl`v2Uc&YfAO0$i*U88qj9+V#tL`)$FsM$=rARMlR~ zUi!qHn&r0h6?eGt3B}iyrf(D;+%Vo|aInmIuTFPCkpAm#KRPMSf2?BD7rDhxG83)e9=X}G?c~i%Z!9lX*i9+- zoU-`~N95xh64rCC&6-rqxypLUD(C9B#2vHu7|Mme?VEEc=I^J8!F`S;nR|+VUS2*W zKVbjH1r0los909)Qf&5^6aA=b(zS!(fva{o&QJ@~wKPBQym6_E(}QDd`%bZ4nG}55 zY5tsdJF{+foaSA3ck1I!3J3K1%Oy84mhPOJF5|y6r*unpY~<9V*DGx-z9qexXQEcT z%hiv?ba__0)3j@w0~)@|v0Y!JzDF@t^W^LUIxCNg{ycYUN!jC>msj+V4O4^{0!c+E>lkb@rh<{{s!Rj4EFJ!0)HqPb}-xO*G+A`WI7w_SGkE)gKjV6IO03 zS+nl`Yo3IgcI!E-zrERhrlmftOl$ALrSFt)oSqprFYEe5gZ{4n3~@5ryD%zvBT&T+ zuHY?=OklktV{?oO-WXKp6YLeejk#TP$4uz%^PgP%S~rI>FDyKsJY|R0tZ3S+?lTzPjC(GK&r}o|No&H@5O`gjk72f8euv+`X19LH*V5A{W>_V74` zKF?3Te=Td@2Bj8>Qr%}k6^qxb`dY&%w5MR*znXQeOe=laJ(Qp1&Hqk_4U=diOeuuaG|+9oC!^Y^SxMdH-0cW&hG zY78pAX06CDr$ORUb{q4YSBKxOVQ9L*d~n6z+)e*))+n;hV!hCEeeTw2-ohbUbj4~+ za`uYlp1t*Fsz%e@Spie4c6m+@UlA0!_=}JD>es9OHObv#S=rcIztb$^gZ34z)z@FN z{c_o5=*O*YZhUa#!uAE1&a6}xFRE*lQ%YMCp3<*xSMl!sKKb*_&o_5_>F<4as3SmAR@rR*oN%`l z4t>ABey&+hd6a@o9Q< z4o};Y%i?;^%&pyDkdHO^_pptdPSL|sx zEhhr6&M#V`|4daFkaFK8c~p@L0hy z<)(ro?MXLk7rUft1bVrAn*Lbisaj3iriZf6XNAsA>F3dY9U%2cr>NKM?U_gsXUP=d zUi+tZvB^hbSlbV_nhv!CZs;jXo;G<28JpSq1$n6-8r|DdHcAIgVPM%o5>yPtw|7X8Ctxc7Z;}tG4 zFv(YZ-nuk3;LyWcL2M^pzsb(M*eog2DzwITn%KUT$Dc|hs1)ya&$unOg_*-zR9-A_ zt?;VJr}w@7veMl4|BT76-!iONBhoRiX6l70RxM7mE}dpsxth=T&6DaTe}Rj)FS1Uz zelPUx_vy8b@8UBTl%%he?@O18ym{k69P7e4XKPNrGFtl1#&+syjDWA&TB_UfIlsy;bs`>p1Fd;14Jv!kSn z&cenwLR&@rZvL9`ERN|G*V-HxmwB0g+7BA`c3W(}vH!bNZ@1WGJ&prUKj#}wE)%kS zs4LiAaKbyqoyUCXp|tlG`3^cw-kY>u%-!L(g7hp2=J#LPs+hRMC(c=NX-CQJi@71a z1}&0GY6~`17wwV_5uU%T{j~XcS+1ff%gcVwy5QWH7ua@Y=R}KXOErEx;5yFj(JU_e zO4xaGOh(JzsDpt=JB&HzZez+6F ztOYHji_2?QHtuns)xA|KP(MO#dPDP~)fEpE;sQEDzZWl4bm(99?ao8vpk29Zgr}_j z@1s|JFK=YE_uAa2wGrSu2 za!RMGzR&!sad3U7#YDHRi?#NN88@%~>R9QT-?5n%ao;)x0}aP#P_4w z<|um~wVaesQ;)5<<`Q}(nLQ~-edFHyu38l;Z1T|`qdPv|4lH|ZBjumJ@Lzblh}fOw zZugg`&llnok8@+>KW_6q`*rS|{knp6LfqYv@1z&iHNW=bU#fVWRn23<$vsD`7H#m{ z;$~54aCF1rw`&?&Vt@_IVfAiF%1S^ZaTHM?YS?q_!NiP@Xitk@;5qM?~| z$0wp{g~ti=?|Np7S+@PmXn68lNbqQJ_E+-@GJHpO7!->IS|v8@y{|4?>;C$AwfuGt z-eqOtf0uJV_j*_7lA*p}14lvVz1~%Oj&KJ(VaT7-aIC9`d5vJt;fPK0IWoo^YAy{c z|5{Bxb->N-S;?l&Q@xcQmbLy(HmJD7Q2pzD+t<|1*|k55O_W@&zp025opf{V%1M8$ zruN>yRQhxe=N^H(cd|02oy>&pab8@1eY)=|{pCTQpM8Dm*!wuR_NRrF_L>Pb*2)tf zE)dxi7U?%_uSQ|w{Y__2)+ooHZhbso>*JxUrhrK|FIlW9nB}w~yt6LYWzRGI*(Y}_ z`&+SN$DzjCh4&YnSgr9iA(KOG@j;=}m3c3?!&&{V?w`DHZ2{wt(rGb&&B7b{lQ%2f z_Nv=h$2;-#-6Bh+>ffu`-pa2%!fsm?HPhsmgm6!r>u^;RU502$))JO-G$-yr{AI5Wx8*ke?9H{-1{QjDLZU+%f;7Bcz3bo*h;Rb)3Vcc z@3c?8|M*b9+~KO4Kgrvw{?%UH#SwOd;kHzv*G|s1)C1*qYyRc6O7lID;@J|tQ1OLP z#3#AT;JHt}&bZzh^{aozR7u^~%I$T_cC$H08on(AHx3msavb<|Fe3T>vb!sE;$4zVRg{SrZoT-T$S{kMTptA_+O4<19Wdyp3|N1J3Np zKjSmyeEWq@1#=xw`>yqo*}V3;0;}9ssn_x+a@o{%rj=Z6X!ej)v+uHIS^ZwxsdDeu zn@0a@zSX-bm94^PDS}&opq8SMsevV|rD$S;(NZ)44XG2+QuHpqZ6>hqb$CXVlC`qP z`{NruXTLN#=`%TFS^Khf6Tdk=S=Q%PpWOdmFFs<@0*_mhbS&lMb($489{t|%`>o!S z)2iu7CqFL#_4iZG$IHRnZT{}ih?<`CbHmRsd4)R#uFCIuwRg|}x z6$q_AXvtmlaz}d6PP^zoQ(xAk&iJmlqUY%xOWj@{^HVjdEn9kaznOl=Ag?9-=Iv*n zrq`&>e9|R->4#yw=CQ4tmb_KstK*wKHSyfdH}hkp($q`QBI2z@7&3!ViZ~1f~Q}(UF@~;Qjn&aCT zRkpDl+T9~Qze(WeB<3@Xp8I1sIbVx9?QBq0XEL8vaOgqCA;av=_C*gRzsoST`A;gI z`ggkbQJ)ER)vU5Jr_8$j#@SFH<~ytHjXbci_38msV5RHTxUPN zWWq<)TA_y}uRl6$O}>-LU9K7Fu!FIjtMWL{jF810+a4D3Ib^?e{w8Ucxqi=?f4Nq5 zr$jH`vU21(^n20#hqJzDuji8V`L=0EA4~RUB|B@=fJ2)~c)Eia-xbY1u_}ArBW8OA zM_uk)*P9Qo`ug+a)Q;`W?k^KHms;jone6_5G3oDP8KXBB12taG5WAdn-pyueN}Yh; zW0l8FcXz#AZ(VV|J<4^({6l(SVeHEZvw5O+-a zVD4WB;TY4ji=VgDY?~l-ov)DXZiuGe?U>U}A1_us5ArHq>freG%QVlIx`JQDrn=?7 zco(=qek<4Q@*}y+7PkpIq~3^fJNPVU@ut^)J-K(<7e22&*mYIS@+6z&%>s*6r&*rO zeYc>_y?f@C0_Kg8{)_oFH}p!?-YC;JZ&Gov`i0BXkVTI2X+ow_A1``-n)CgQphdf$ z>+LJrGoKz%^;@`t&*5O#A~uz{IVo9lrY&xNID>2ZB$I2?N*~C`|0Rz?_=J=QpcEO=h^4G?UFCO5WC`)4B zJe!$!_*eXu;jr|b_Bb>p{>s*fo*>81KnMw?zx9VR%aN}^=)>H5056%5> z(0sib+a-p}D-%|1`5<7#`CR(-GoM>BYXtr)7)I^$|Kd>^ePQjK57sHnXKpVD%#K>E zcwkz3{WCe9rp5~&T!j}O=lJKahGmbr@rG~54{&Xk)lO74ooDLp*Ms z{e**#?E z$?$ZD)=sH@pwk<8Gg#&{#eCzcU{_S^z`9m4V7rGjmt{3mR`Ci z(0WWvvG&~aB|B~3sT*y-WO#VhWf7^1ho3*N?oH}D?X38(jQw*&)27fxTV+j-9^2J4 zJ%wHKYrotdk4x<{Oo}QVhl(rrthIX>P*GK7ccWtGYzOU*Tk9@2=JWs3yT56o_@qxt zb1OG$wp)e$u4g#qnYlW1(U)wVB~cdF(=#R)N__1p?T86xf7jVLk#{D)38%^D!0ugg z`qtZ+Ux*#J5qZ}(`FHFF#i-7irT>0=UUrmWYBVoZ+CE=FbC1hht zX?lHM$@<>*fX-@N?swIWF~LWy6|a_j2-RBRm3N{d#Jo=GRBhH28xz^<-VbNJ@r*nE zcE09iv#F6M*5xzuzh@D=S1R^*MuU0ogXhWX@_9bbi#d>!`sqz+cxBk(84UFtwFVY% zc}r&JCvV>_q!F&UA;woVZ$;ySKkFh`Ci)ql&rhFQ$|wHp@_~Ciyz?%8ynT`3TaWbL z+CRIF`khKY#_`N|hiuM=DZH!06auD%vk7x$xt+LiitkE`R&9ZTz&A6~bEdoczD&2- zA8HxCylkrV1sRnkJHJ+b?=|6^qGo*P=tig7SK47MY$f`Kma%O-`25N{!y{9=b_#NF z?Yip!*t^{G2B)mHkk?|fNdm53Uj1j369bFph8?&q@A&BAKB*TIIf~Xe?7ywg7IXE- z9gTMpJD;*=)|g#PEUT~#TfP6;#ok|MSnge2`FP?i`FXP%j+goSicFs!EWGLX3a-_Q zH>#fE6x(6LGVhGw;^d`&Y*+U1T8V`3UFy8`n$HjC@;|#>t>@id$>JK6leaGJrDT$^ zs%G0~ehr@B|LPBXxl*qP-!kOCuCA)gz5Ggw^3^`S&y^A(UANE9ellHna+uQ3`>Y+0 zWPF0Yo2sw0GPPXsrJiet)6dUu1(UXzABfKSbp7ii&Od+nSFiqDfYE>gH;ljyC?j(- zcmoPH{)Sj?V``v4#Cn^zF()TU9~a!~|3kUJ#hU5qt?7$ZPESkqy2f;yy`BFFkE@Y| z@gj{$lm2|IyBVEo%4K^%N5P=%!ve8gt9R}C^z`)BXUkhfvJ_v&|G)ov^=A7TaWVZm zyX^Yd6-VQbufCpcKX>K7`jr1)9$hwNTd~1Isq*dHq`!w}zM3Cy)tMpg=(bS&_3F*_ zy0x2&l#Wd~6J!#^vU+aZty}%OA~l!posjr5a`U7^Zclrn_vMJ_&E0ZZ{_~3P$193^ zgrcHfPCq|;>cNWDy!Bt&k3CwRa%und_@ujPA4}P7QiG1%x-K5^=CvF5`>BCEMjXXH>^`|)&n@4-zq0jIaWb%{C^!5&yQ$+x7j zvqxBQ)>CFSq>h54q_#*lo}LE)Sgj zIlQS>;M$F|u`kqQ+4jn>|HXgp$AWjwbA4;h$$z$9KYMEbkFUe|h49Jigf@JQs55%>ylBr~rT&+`!92_%33)Rjj3;ek zS?|FVrSisld(W8@sSSHF-Dj@Y8MAu9nTV6#O$I(DO)e!}$DTK4o_OLN$-tV|`fS}H zuboG^gf7b_HLOZm^5K@Q{c_*y6IDKH%LvOmUz%`}Yt8%I)#4Ei?J`RWf~4PjTvn)B zS$k;xG46bYIpq_KLbN8@Y@8s_qudxhaZX6u=d$NQ7q56_n^k+SUSMmk)qJXd=F6p@ z-LBgxzvx_~>Gg@%)HX2Ee}m|Q+tcDV1P3*0ZxFm;YLPIp`FE99>XF6Qd&>@0%Fj5K zl4E~%arSoa1IZuljyzqyh3|sFxA!kA?6oEZ@ zdQ_A=IVL*M@zMk}b&0f?dS$c152=q7Z{(Uclzb`s^rXn*fp5(LM&@e9^?srCi+@M- zz1?dfROP#GuKDwa1;#UCh5jB0lHUBsT{y95%hNWk$+v&cdhTE5EEh{yWu zszp;;FYk^{W6|UF?v|Oog`a(Hgp<2sj!~76-J3p{SmUDUH&3J<@OivVMm|X4Ly|~^ ze*&lc2mc3pma?xDpR#)IQe?aIV_Q6jczLVRMq=`+7A z`chhwOYd=<;AEa|di_W4Ww#xi-``)4xqEbepvT!zO6QifHQ#X2NH-FFyTg zUsCcp=`&KYJttn@`^=m6lQ)vbv*>+J`xLfg&e9JbSQTGO_!4|2n?Y?4!}QmBH&q*V z*EMb95LqK~Z|<&D@_Zco7!L97Ts5OOG=9SNgayL0(r3nf(OfnCs)*>xE9w@@Gk>-y zy%zD6dZ+z*y1WzzzhcRg<`Y|eTe^1qVX0f@weNHJ^7S&ClJggCxv2T_=dN9I!g>1E zzv+6HEx-GUg-ldt?JVD_n>CVo6TfubUa{@^^8Er!8tb0Mn4U;}HSzAYu5%BJvuAem z&(zNDyw}SUk$!RaBH=ARrmrcu++!m6;&cq#>M*8TJC1tn5Y+j8roz(MLS3g?b( zclDgLUVgDv*$U=@<5{1#+&G{Wk-TLCum9$6d)#jMJlHy+xZC*p&94C|dzOW+zqI9< z*O554YezK}96PRY=CEL?7K7oZQ$Xa5c)u!3LpV~za#P&a1GeegHwoUDX2cjn$~mD;l5-rLmap7r9Zchwk9lH43t`OVH^%FS6{4=Ki7JSQ-3 z(vjC!@6Ba9eoVUkuvcX3%HtDmFDNQW-F;_fVc^9VNoUTciYiT6GGqGT$Rv~Q`{6^xN)wR2aewUjTb6_YnqFFovZroi>cZ`*5MEF1!lor>OcJ9N&5Pm!i(v%(yGXU^aE zs%Q6+zcR7u$_){RnkO3m+{s+X^Dh1lVb=j@XMJk(ZgDhOPe7P7Z_Hfvvh$-jyx zKMy?k@N<(+t%mJv=ftah_NEtuH}}l)I9o(=O@dX z#~xkP+wXLBLJy-GmpNl{gVs@Jt|!mZEFRV~>fU|XWGk_xs>$JMke<&aBO1Fh^<0y&tTrO_#l1mpLQE^LJIA|7?-B9}4b25Zjw5 zX87A6cuQ${_%)A(kCcyuN`4IETK_iDGpxpU=Z{~ddi(Z0|LSw6Pwv{2$nrFY@YU-b zPS3g%y7*VpilAxXiQP`Cd^Z@sN&A{}&{CF%v5~!ucg+U`T`ne|VkN-RosoZEKoz0Wo+vU>mVg=>_y=$vQywjt~B*(K(Q zp7-oO^JG80y6Uk7%gi4iH^-=-PurWMtVDTmtLa-3vtQpx$uy6wo+&?y@p zoe-YXyz$aCn*)zRE^5eBv!8nLsQb64XVP9hmBdT`qYboQXy{t)Y!B7gAaZ#6l`@ru zf7+yl$`mYC-`YG;H7;;^zZlDeIa`0}W=Bm=F);Y2bMkc zE4VERZnK)1n8VtvrkI0%rbG?;U7cdvFJj2k_WMuQ6wXT$w>QpR;_7hF{a~h*OQFI( zmg*N4N8TTgEGuKS;><0!nvygpe4Fsu&sNt38f9$*6+AeNdw}-RZG^nPoXJ5-} zhjw1MO^+8}gyhjE!V0&CkU?EP;}|G%PDR_ z=>*^GJXWcz)AqeLmfX1X{P8oVgMVJ%BO*58+U3V<8obu}%(VY}=s-k(`p0A03`=h; zskPp^=Tx^zOW{`6Dn=!#g^QRxZCBm+AM}4_L0{GVSzGy(%p`j6U&+e)y+Sy1l5fps zJMJfU;#QxxVHU3;3}EyQZUX}6zqt()MAKif1;dOe(b{=WDh?l8+U z@$F&STf%>SzvCsv7|bXh8veMp?s)jA#=r^j;;QkBgQK24zr*7a7i>PGxPD!I(%yq< zaTU#Op;fQfT+vYJK6@>FjiJa=v2)&HN)a8QD-2DVShRaiUS}23ZqxfO^Tp9K=(#*s zg6@`(H7UQ(tTxbFG)b*K@MOuo;D3Ghd(JM~a#mh6%7eG>((mo8oJYSkUGQLWs(totxc%JY0CPvX+wp?Z6OTLkAKWze&ucd=>5X!yHuc^QdA0bPqtHa*F5TY-F;R(I zPtF%xDi~z-?NO;J*F@gi9;MUn2Hxax*#3QI@#nD6*Qp1ik_AFzCr+6V@oLp(Ic}xQ zNb6AL_R@(HxL%d!y6t~`Yf|4wv;C9IrnxFwZwZ;l;vuiM^$OFJyUR@#+HbI5GdQ6= zBSG8#j@ImIRRf2Ezd2PBT`oO7wQ9ou*xx1$iiIgjCs;f$W*ofeq-8YqyaVSZyZ>vA zT|fEU|GoBt?`PrmSOfbCwp1<6#uypnLneVgCoQ$swmF<~Wm$Z}m%D4Zh1q0!n2M)6 zH9L!J{;I$F>vr9=V=GmK4!Jp8H|v+%-66MEE9--zVelda(HS3NuYay(^kGXd_%C9W zl_;~Mfy2dHBgV@n-|D(~&H~|!ft@VgntBx?370sIyzNPNRQ~q1LjR|gilWoLWLL;d zF`hEXOES=FJx0h;rAgdS@8 zZ~7J$kv(a9_m|?WlC`rWt?mAree`1GUEX?qU+R<}B_`_4rz*7Ptox|CSL_bg+-IvU zZ(6i4ENOl_TVngmp0Kdu6>57QR+~6|{1SNk_=K*{F%s`SR(;L+YPi@+S7T~{r$eulvo~6KR6aIP2b9vDJt!l&U^<`=l}Bm7pT2q<6}p zwXyeZA6okI@gWteiwWsJ6YTthPSj?f^XF=LdhEj)z2Zf*8^<+7EVaqqj(_AHx;`^`P(TjsopxWV8xi$i+Xnsirq^)vJ!E&36<(kj^6j*QFH=bPPiCb|j)@y$TsD2?Z#a=KKi5TV z=~n*Gvu1C;*YT}SmTW&hrABDt6-CzaWlx$H9C_L#w8ZX!lc36Zm3Y(LGos&H?e_R` zPkF|g?Mym%rEAX1=u|&>)O^vYyI1Vm>}Ts;gKxCuOl$g^djCLUYXVbhtADvopUOYg z9WpDv@g6GL8Lje!=gj=b36~F<%ygY}?O5!g*-g2fdzd!6YrNxhHD)?0`}0Uqx!Z|J z^X=z92yDrF_H^~x+6N93#1kj?ZO-)stFmS~Dm(dW(RYUv2N=!zDyQT<-cjzip*6`u z%2`F`g2KPP6?0skCU7R0JL;A5w@k4=aLus)Qm$*sc3#@XhVm?Q$;E;yUZ08-FZMD<1wJ z)sh-?$Y0Dl{H&+ZjZ4MXR~i&OT=I9>Q}JgPBOffZ(myF@V!#B_U@R!S$rcI}sFO-^Z?q@WZbMV1e#Ukr%#E<^4d!KT% zpQJIC8`$t|<=$Ri5n=wmtw31rTB-G+|B5!x!ZvaCyPVun&=JqPSI2Al&gDmvOMG10 zXLt1JEtTx)d-`tILc^?oG4tJT9y}NE)aMh z*yNU%p`UeE9{LyTqwxP1U>G8h>c!5fNZu(kzKJA$a) zRc~V=C*Rp7cN+lMPcgIhJJ@S3CDb;_f{3Dy3vZbY`F1^}Nqp{!a?gPdN z&gVAnUSRQ9H#Bp{o(l~7)?XC=xbA_E$ee$s`@`3V`|sO&^z8Z71=|FU+V5UGKkR+j zqMyy?<>LP4KN>c)rr&D_Jo@aZm&teTycz9>ijFV1u_x~D>X6r7#?SXmSB)-C6V1^0 zx=Sb~BF*RL^{pui7Aro5mj6_<`@GDqWLu4VpMyu>zwNs}Guy45vT@O$LfsifvsQol zx@!`{nd;{D0}MSOPj7$wwBP)HgzfD$^VZ)J-SjSS=?v`__Jcc=Px2b~u|0ix^wr6u z;YZuQ@81()`*WYbYW4UF_5S;R^3?0u>HphORTgMtU)HcEZIQWy{o)-x+L@=~n|dxe z{+wU>^nfulAN$%%GV=qc@lBoXQ&8W(`T0kqgL6}i7&sjtwq98JhA*>A+nqUvGr_4M zK4;zX1sO^r`(GG`@nJ?r-z5?8z-Vt#h*wbg7ZnfCZisPSf)dWI|b zpKN^o-jYR`lcc&{?0a`^?*aEEhwVdt-rV)5;y`NG&(jusoh9XbsS$GtnRikLaCWwmW}l2TKB!LsUZgii-IlST8NM@<)2I8{G7 zw9Dwqk4|R`bNP~f{u1`HzZt78>rR&z6KT{lH(zrg+w{gd_EXjxf8qmw8$FoxTC=Qx zKPCH#m_($6#|)01HwE_|t+D--Y;ON%g8VE`=RY?bdH2U;N!W3lZh1dJ?6)lM-5ayB z-)v)Bw%1Btvy*WWlS?NGOr<1(?)RWW^1$Yt*&ByXHnTPv(8J z*6gikuiT}#QYK0s0`Xe;7uHVoo^w)XgMpw}O~Oqx?jL-g%^X`gIwEGBn)Kq}jz3!7 zS!vS!HXj$Ll}wvtvFBA_x-5^M;kwOy!QmTX3YuoI&JodVU@tgq)O~wbV&{$vXHS$0 zUw-sV#BlCxh2|GmAJ#=265bgzPk`aGdnoU>e~C7m&V1S?7dd77abeHyi67PbKHZse zlPgx{!7SCBz|*PR&x<#>R^MNwf2yO_RrT%OPZOOcukPBkW!4ih@e5PSR&KFfcjtbs zO?1-?Mn{(AFINdnzf%~v*~NcD$}|SI^jLqvLyiH*Z$-_&dZx%?QQNFUskWXQ=cDA4 zZtrYmx!32arE;_B#XGrV?y6ZE|2(>MHTrL-5W!H!p`o}iXF?^T>IL?|;*IZpdz3ugR7@+=7B2N$81h1W>b2sp+wRF~cJTAuH9e9aFHw<|u^4&G(>VIH$%=_a?O!vCtD z|4`L_8Z9HbbVk9Wlx2B&GGCHTEKZoQdeZBsQHHE>zqUM4b4%a7T)o#swP_;Ty=QA@ zZ#X!~MV{-RW&l(ON|J=%+BhTDtzluyap@gGsdJNU1OxZ! zzl-Azmp(rsjXRKG=hl-3<$7Ng)jA|EYfOA8pB<{VD<|Q+yZ053O({JyWy6<5^Sly? ztn2poUR)E^D5?AG_Q54>tV`1ayj7b8cXm##+&EWZ$&;88)0$)IyFRGSWog^{vn^=; ziy6z?d_tDUKjsp<-DmEmb$pus9 z4Wr*kY@UCB@rAlm_TG2q?@mY;26L1MHvXNH5xRZT?def@XXQVgI}@-+@Wox1TXj*{ zN0vCGe=53hbKl&U@-XfDNu6%{*|;Z7k3U^A_ z&UVdIpCYNYXvreRSJ$Wa2&M02ZM>1_yMJb<^W#&Yy-V*IxiFS$eUl5ke)(INL3pt@ zpToocc~69O0uIdl-8_Awy3S3mwc0TX-`D7z*5y`FujXq~SRp@4VWw(6=Ohn1M*+?k z3#3B-1(aR$PI|iJ8F%RFNL9D9bAGKde0h3u(DoMze>NO5Uu3${f0mmw|H8!=?bH+Z z%qYy=xLa$v%c0`tjQ-S((~fO zkd?Zw7HjqPFSFh#{y6XbfzLb*z0d!d_bmI~`~8S(wJ`hRZGYo@Z5=FRP3+Xq3E0}5 zJlt_@s;tF=w^tvV+==ESaNC(&+{VT3JHf*vRfX9?Rk1FO-mrDjemV;Z2h0k<_$ZoZ?hy` zKIgY~QJmp^W&iqZIZ|x1b``uybh&g|Rp|R>fzI8TITMY)?dv^dTXmehx#)`ZyQ!kH zIb-xp7_{cjUHmBS(mki>`x5&)q>mr@5!WNA66mr=Sch+$<*i#063gVirDpJGJrz2y zSh)MPz~YCKZ!`5KiB9VdUHylrOL+Feuy?H2)UKGMrap+)I68Z`v&9|}d0%Uh@TMn^ zKS}iWn_a$bRd!1uH}k;!e%F2Hl^AVqDJ=do(fFhKU8@DvshgD@KE3gMb1LGZPgB#8 zP5(R$!_O}9^=@(7Y#7bbQE^K$Z0oH@+5VrKZ{+Uz!spKA;odkYMA+VW)5674BuFLcwt${7=vnZ3NN z@QX*}ZKI-6@1fG`e5+%P9km-g6#UpEq+X~>C}`VU)X$T0onCn*sQhZsf*DilxMjl@ z>ztdrZjzMKO955W@WPjiC*4}Ogkyr!OI???wL$MgRW`nFV^ETtG@G~Mn^aIy!=_&^ znPnoruh{ranOAyw*6Poj_g~%hU-7<%%e3eT9P?gFYAxR&`RnFACTIWaukMPTtTvl> z(dNyWDZ3wAL~k)pzV*@N%)C=~#P1mPnY_x(+p}@9^{(|rtXKc@cMC0lbo=eeon1om zE4Ucf1RIAaCKw-I{;PGKv(o`rzkaVDo>v+_K72j>&E9PXLf(9d4P{&@eDbO0Zi)Ut~#s!ehy7koYm`Qq`=TkKb0!D)}?x4pXSzg?BqYPgXSE{D@5@S1hsG z(zYk0Sakojsb`-^zg@SWPxWSVero&eBj04ETA4LXmXn>iB&+JhiEY(k9-YkH?LRm3 zpLV*kE+MXIP2CKOjK=4y|1&?c<;K!X1vNjx%~UgE_;wd_%;7F`;)c6oyur=XN-g^) zcfVC^-FbWZC$9A}+o(NlkEr}3nV6`|xs$eP|9o3NKW`tyggKJu)_D{z)eNuH6jG5o z@ZI!RYh}0xW9yUuv-a!X%h8*+`_Z%IzNOn69?idd_4V1^ye9uA_`ZI0QgkoFIu50X zExUG9ZEak(_jBvyxP-#5X`km`$}4yKq0p;$G>mKc#RSf)zVc04qOnXI&qIEe?B49; z^z(OFJCkZfXq~w9zMGePw|Gs@->$I5JZQRoNqo)DyP8{^RtMDWGj)=x`(1zc@sFZC z<OsM;;_pQ=<^0GA?37K`}Zc>c5zUq|* zFr`!+xcmKsp?rqSv}ynLhyTB!@!?Q*)9I_Gi7bx`UU|Ql-G0mTY*_=7Ld&kNhAuBV zR_wp@MA5@%Vv%t4y{&Vn+J}X6a0wY)3C_>lrz~;rL)IdWEp5sTDGTSv<<85!C%S6c zDL?M`hERvUB4!cJyfbtC^~}Ym$BWtj|8e^C*`wyHIeP!j{jdIXHT}!;PoE$8&t5+L z=w{)W?AL_et`JwOJ-d%%oyDPAC#&v5dJ0RpnQGNim1j?}Q;+uJNqg1(5#!PxUxSV>OxkK~Tq^TnTW$WUGrB3xb6rjeau>{> zaBr4t+9bnS+>+C0Cp3TYQ&?Sarlu#L`+G*r!OB^2`=!M6+%l&JOI7&!-Qm4krJ0-h zwLHyhwt|e^nV9UDS+$Qj*=7W6?pLn}dU~_LVBNiJC(+7^IJpHUZ!Op_(O+{;d5X=% zGs+t5DthL&m$0CN^GdQ$BYjTX@Z~O6K{ln!bEhQkWeGo~|G@0hyM=F*SmsyT@E)AZ z=xaWCB16!{>NLf`s)a?0y9JcA75UP3Ug+;#*VG~3b9GXBj=RmIIH$8&+uN@``Dc}w z`;)afD0AiJ8;4e}6^rsbopM+6l9*iZy?Y;ho3aW#pX_cENHAEdr;xb+{vyG)ymI-b zizN)2DMGiKKCS(h;96uYwrc-cyUexTEL|V|u6teORC8C-{g6C|ab3uPz`{4Xx~`VL z`rm!_YWz0`R^^a;!D8x>_rq(Z&${q*Z{do}Bav)rOnei!Z!B}TWPQJ{bImM4jZ43` z&wV)|LabJ0Q*WWa3flwO%GL*x&q{Tu*!JL8!gHA?~MM=?`K&`7sXHBbB|LvX^Z58z*nb^isb9F@lJYfvi-2T zyEuV9?O z`|PjKZ?pZj-z=^kQQ_x!{YSDy*m1hM=f%%vHk_quuU^)FEPiEv_ug?atyOnYT*goZbF{T1#!a_2FExaL>}^NN!aSuzVGj@ z8i}`Ot`u%svt3QP$ms8*uy!}sZ#zvRwc89*mPAROsdn^P+PXP7An&}!`+&Her2?nc zyXX91;kzz-VAAZs*Y~&lTd2Q(;Z1I~xw2Q%3lB>e?z}zes|QQ))BHc1gwL%x~~INwyb?78X8 zZO`T`%4t}nY?s>Re?Iku@RrmFj=ApL-aSEcmKi17U1M30Y#HNsw?Jb@cudh03%^~i zEhSyPn?p{t8yug}W$DHl?XDEo^Wo@=NzU|AmYAIKXGW2C${)4K?pdc7uG@K1 zdFu}Q@@LaFKJ=UN@!^$~es&kE?@x=pEdEi#Im_j!!mkT)UDvK0*n867xn}p%H*-~7 z*3Vtr&avzs^FalnH_f*`b%mX)@@VPkk>x#8XyrcfZgOq0hI^Dp@8c&g&iKZg7DOoD zy0(N(C$Ta1slT(~?2{|EvuNy?pk{aX#I-oRfKBI@x*X)on#i|upVU!nBTg2JH(@Vi zwC#A#+c*Z!z8UG*c%S*I>zOzI9`1QHx%O_v%5yCIhD!|OoF^+CJNhq%)vSr-z{UjE z1@}}-8hgF-d_OQJyIq#%v|B9Y^X-V)gS3R0-hWbyrJ9*!z6pZ2$(yozdc;i~C zYW_BN^Wq6dt{zi;k-Vef)Rmk`U;49Dcz#Yj&pToM^mlun&$;CoF^j|d2H)2dF&$~v zr&ZkYTP_*YZ}6F{oX-Bdy(mD-^|IgQYZb~i$Ch*yiRHUY3{(7{YkDA>=jaahqwS%q zp+Iv4Hf4}4scJSlPr(e68AMZTST=R6MdVA%i z?`f+K>k7-TZ;zWdf!T8ZV~4#ZsmHe;SIOr4a9(ew@tplWuHLUgChe&UN;I~ z%jNxZH}$QWCtohNGGrG!eSg~)CAEaIV^f@uT~Vm;aghC7Hvi}$n?AqAYMW>0#a}a> z%9is}b*t;zT93vL+isqmYp4JJ<>~d8pT1B1_HC*6v~?SIv`@Ok`0W2pmZjRy-yK-_ zY9q(#f13kB1&_U1Bz*McIk}tsOO{nEth@h?DUwZQR*d-*@yGt}&EGnFdg2$b;PF(E z?8Os{iWu#KA`_*y>sZU*=KHNuWA*QD;O+HkbutdoJX@1zetO(@ry}t98u!)W3M}&1 zEZjI+el1w#WSbpn=2RN6)v9Z8uv!jr21#G0*Gap5Sam{6CZn-uljGA{kK2p& zo0h+xyfWt3!=}}Yvfmi01odC%mrTC!=HZT+0@HVw?^*RPcfmJthMGLR`(HVaFX#*Z z$$8~e_^$M;ZhZ&0F{o(n^EvHhVY^aS+{=E6LtdTB(fgbY+pLZqEqrEIb6YQb`r;Q+ ztGXUvb_#zg*2Z{lPv{}<9~}p--t1reAZnG=<6u_t_`-?b9p+p5`(9ggB&$I1Q*_4B zw}y<8UmT9TRd>kQyHqH{@~GwZc&EKr)FO;7Et%DB?D2+sasTP!K5JQ%n?gR%+y&eY z^(~$dlOM|@wf0%R#ln?I??ts9Zx9Z+Br#|C?@RL>E3Gs(C-`l>ao+4dd$H=&M2t~X zaI+KAJT-zZ5jDpgMKuRCV}l4C$#ysNWS+32z|%YN7mv?7yk+;Q>sCn}Esh=%y;GP^ zDOxk~SQysWU)^kd#L-debeG$#l`p^UUG;s}^-CEO)a>7WuTf2tU%Y3ZaOrB6pX>Vf zb!~0lP zW&e99S}(T#DR<$P38$Bgswf}RPPv%AllhXS<$(|b#7m&vLK`100e33Y6{yG+?IZ}IY6E*X<)m*qO*m-&1g4sGo zi|2B-ulV^_Qsa)X0E_JA#)iu&4+O<8KHQ~|bf*376}_&SOMV%PJ0nZXq&7+f^ey05 zm0iT1yRExlIj)qy#^&DoQ!h9qdg{L&*!z2Kb>*)9^S56Yo_<}rcG@HUM78V3Fq0)H zxq*_UsX6=*APdY+lLb+ornNDV{W8aS>%{*ki`C8I+%tDqf4I8iBbf$aod*nIaw=;} zU8aTEO*wLIK7XWo#-S_{C-c$AQ z@ZwKzr|$c8`Nx-E7t8xgez#}&$Jf>|Gq2fYl-I5KYW3{r{Uz0QH&!QHdUp2e+1c*# z^Y_`rzdmb`>VJR!`m4`;x|Zjk+puBl&D)oYf2`=?y!Y&~aE*id@?Z;F>(^(ivUzKN zu+P!9nEb!+vwKAR@zr~tCNv%Xy7%6svoBvgJKvvI_x0<`)tm2bGQTx9?of!HWqP94 zl%o;P{qoOWS4*GaGk;%0zh?fmCztyTPV5vYt-rFe;FlOn$GHmT`RmpO&Gvovg^z8f zuEbfnz1H!+b(hZ3wP{#g_4LG#{DMG<^}O%4+W*|*xAXy{(Z9bE|CLWY?_QCAPA#WE zs5R%zVH<^CkW{r3Jj!Hq6u!ROe1NQSZ<-ORS-%QG>PV4-H8=JY9-rxiUh zo@RS!L1n?`RrC5fSEcARYn}D3G)r^OTsPa|`mK=0y!J&xwhh|tii*G0T*K~7)O75h zYdX8EPviY*MS+XH7bI@HW!vUjvR-y|5T|_Uf_B4=Pv<}WIy;B;_5tTZPv-D$KADj2jH{Gc2 zv*Hm$nY#Z>_Dype0=6eFtvs_mcYb5tPvtt!?Tf!mJT!gv#=dzsrsTbM61!X#I#sMk zap$@%zMNaWg&cj>`R_}EZn*9bruw$U*YAbru6Z4k{b8}^%UySjFK*wfd--S5npn*h zUf+)13qGGcl~I4{i3!$!jPev1Ph`D$W}NfOFXY_yj2;C~znH#9K{dOU{7yI>wp!PE z)rA_>g2E5G)%O?Qei1xz^{rQ|hYe+3X5QTVUaoHE%axpWo<{Ok2VRN35S?Gm*JXL= z|AFlbI>IUqKlpr2nYY-@Vco^Br@C3cR8Or8_1|7lxDv5`uav=<4u!SZ zyGnmc__?u#;kA)Y-pLs|KU!@suk5UU%I5fe|7^7%b$hjEWJo<0$@TjeEW5_(@2iE=-FAmE4agy;tiOsdQhs(`ByZF2I?RPmGHd&kN zlrP_$-p~8*2(J&mrE<6OLE{qTD4uIPmlpNKZ7RA@Ew6lJW>xu&c$QV`p1gW@{3P?q zMG`VLHAXUd@f8im>0i!di}@r>V%&XRC% z@o|C8K~5FXWIowiu_Y0AdzOpOTi$l!o5SYQZKX91aaYQACV9+vwm353@OPsZ5sy?H zw6ZK$i?5s%(lK>!PI5|+h(K+_CX>R&{bIemmBuTzb&5Z+75Uv@*qJLPG41yojx!Cf zc3z&IKKH@BDL*Ts*A*;zRV-R$@nHALuD2O$rdGCYThb=`a1Nu)&Se_2R`MP>&l7M* z-ic3|=TT1J+W7`sw=k|0P-m%+U9g*1aJlUU4_BJMh=xTQNsPMS64;DvQZUZ=gBsHWV+S+Za53=JEk+8V3X34288MZeHFE>1|3~&vfxBQ9ilU<#UisrEw#QXi6;rU{j z&*6U)Uxh6XoY2Wx=e**aq09ZI7vdewkNr%W;yb3r7ybX#D$wd0{w1VHn%DP$x{tSG ze#xg#R{JA@f4{NG?H0(>xs~OAEaC3D9v!#q9OWGMcNgcR%WO_N#kIQmZR?gdxoINS z8P?ydgAAwiEM^kAwv+vk&&mR`4Ax^`=WENe?Q?uCGt=qrVP)MJg1V8r&o28Q5Z+}o zVcYkL+=8M)l_}lrbDZ|hzA4`<(9Rd;QNZ);XlH!=%q!2icl7iebUFLV_h;*_*)CHR zI-c~YuGdTJyKUeV!t!>xw6xnh$^RG6r@Rli;M=*y=F>^JB@vUjmHMZMt`*=(y!k=Q zZI3J;Kl1^e!xJn#|DLopzn;)Fd0Nr$Y7U_$4=t4!?>dt2El@OSlPt0Hjg8sjvrYKC z!O0$Lt62iUJGfRnxbphvf+udN_t+ShJNr#ParuLS%SlI7!LW=u@zY{omt?-bexmKz z=DcdfzWw>aFYjb)nZ08&*x?d9H~h>-t{+KO`bF1|EKTe@vGnY5m&YH9U6>hrPF&8v zfA-LMrj1-h3D-81yEW%Hil&uz*S5K+IXzjJthhG+$b&l%WB%rqxE2Gm1yO?fa_jH;roiruBs-~v<39ub{Eop zRvpyqR@wD1+HK0*G-D&%{rb}*uZzZ}7jNu2vN1b&dgb{&-)?9Ic4p6crT^)V#|+mU zdjvXV%9Sr%>RH9FchLN(2%iI!UnX-*;d+&22XWQsG_pD|5h%?zWz4gJe>4S1iF_~|}~v|43YVO3fu zEBmJJ;Ng#Zc)GtH)M56Sa&vjENTIm1l1FL#c~ynOiz@@IR)-|Y%xP>1eSUaT-RwQB za=Diq<1Th38O^?Sb&*mXo5Vl%35PQrUWOceCi(gGy6dXk{xZs5{G9GB9%n9uUXAjZ z_l@)WYtJ3LFZs^yU43@%jb7hdCR^5=-8^IJIsKbIp0u%?Gc201LEyfH%w5A}Wj`A) zL};GkG2L}C?fZgD4#|alTeg0XE3ivqnIY!)w`#k{G#}Zi$yJ)dM^AJWt8C~kkuO=h z>22PE7Z-v(-@5wSWiDvGRV%9NJx6Tjv#$&rJDVcbaNX)}li{3XI`v4&>P^hcrhG4N zXgOiZctIn`icjN~ZiuMEF2>ElXRAFpA1W8!;R2 z>5Fw)nWX=D|HH+L?W}rQds@KU{5hJlSSIYaE24HYX3hPsE4LI^9Qtu>PvISp%6eA? zSMl`wC$D%d@{!;&VVkAW$m?d(=ib^8#d*caN6}BZv7?NalSQ!2GWO*s^&c1WKlp!o z@%!pzzP8+zePQ7NpTpXxgnWvbIp@=Crkhbe%R?0#zbKxYc|;=U>MxP>tq*)2UHqDC z>&ED$(7kW+38iDpg+3M6|5qxLnWVF0(W}+>oF2&ruWfqvVb_;L-_0fmWWTAcsq0RD z$}M_**&bITKGkJh!nt<>4^NePQS~<`Y>wKtDFKJG{&PoOu-<9HF2uKK%8|KduYy0! zzS@2^Oi#-tNW6OIKGko5fyT+F%D3nw&)A>)SE}(?%gO|6W!1aU-r<+}WD}nq?Cv?a z>g=vd#_hX9PQ80Q(W3V3wV)`?*mjpx5g8}hD^>PYhvSdzv+=C$EO@%%v7zaEhTAMo zlME*`*#DY$fBO8RDv2+uFW*(V_F<3CgZDS{nab34)FLXy<$iqd^OewE_4V9Dou3k% zKQ@0a2>wB$8{1V znVyB+V!f!pMmIe5*Vg)#Z&IGhuR7v>^X}d&B1#P}CtttBRQG++v^a%YF%1jpCx`xD zxqR{UmT7_CuINr@cz%^J;c_#V=vQB+WpCzeyezS;DZ)n3kndw%t;LU3KffK?vo^}R zH&y!WK~}-lTU^7|JU^MB`TA#^T)Xt23DXt4f;V*jzdv0eYx9~J7IJ3J2aYW^vYxi; z`_(VYVs@T?bM?VObyp`X&Aq!Tbd?t|8&AKryFzkel4OnWvI|Pp_ww8sU!83GToL%u zy@Y2@?5A`28{SLh&91CDqRzK$YolXIMbN?A3w*_S9diw=RXA?{P+mCa>;fs(dzJ?t z7c6yO|F59uwBe2ux?eOS3;Dixb}r|d^5<5mV~I)JgQ;J3U24kZPbs^Wd$MZh*GFp` zt~`6TE3EI##I5O5dR@Oe-U{!#b!W25x--Aiuhb^ZzWeBz>(oCddNv*Y7^nQL{oa;s z`9J=C{dnxa$9+@wb*zxQd0G34xB3j`?F0FLiph zMjNLToUEL9HQwWxQ{DfR7kh5-UXb$6yjo*&ZG+eRj&KRChf{Kt8+n_IEzTcT?@YZH z`e&!w<4UG7uYZaq#qlo{N{{?wn|pcRydy8ugnTVD6J+)=eHSoW?*8WZ^P3I_rENCk zFOqY)J?}~0lk0*@izJGDjx}3<`^NF|v1Vi3iNxgGw)>)2o@>W#J%4SI-EHND%bj*J zlNA-34Ch}}@>bknJU{8G|G9(DwdI1Vrv2FX$ouXw*DR~nOCJ9g#!h;j&9#4z_olK( zQJWhIb6Snr^XG5eeE8OGzKHn(pOP)5Rj10Y)XaZnFV-!5VD1$AhKEA0Cn#OFDLS&n z;YZkcL2Waor%Gb^*JedZ-kT~r=fj)EDGse63#P>>MtMj5-5GG3{pYa_0gEpS9CzkH^+li67BA-WWPhH~#j{sBNF|W%e#xca*emapa}pmYKYad8F#S;Z=cT{S_%MlA zSxepW-nF4!{`KSPuiqGX?eAW0*jN4Z;G7cUnzLKpyw}LO#i!liVUqNJW=x~ti(;F~ z7XQwuORQyq$BfpLu6vZ>e#bIslE5dKKRWw4@N7dnzxE; z-+36aRzi3GLvN<7GZu8tDEQY??Y2kedbsEZ?|XtK>~Cd$C+^m}xbfx*&s#MTMVgFe zX^{d=&t9Jv%)G{Jx#srd}4YF1;&XLqv~V+WjE%`EA!b zRS)-wEPh^*xN;}s#+xk?ulh2ZKDx$kUA0x%f_d{}?-O=$Z)3&#{@*>jc>kgL|I9fY zCnQqy(2mas5AT3RflN$|jJTi&=v!b8PFjFQiwF)*_D=K7moevQd;eSe*$PV??MaL5 z`gA8b3$eJ~-YaS=QTArbF{@7ds4w@Y&$+n9WcOv24+l57EjclrU$b7)=D~xv%m3}O zdsp|vl(*b}cV_v4hj%ke_y68>_*eV-mGke;U)(O@al&?v-TmI`G!~VT^UBT~h6{gJ{Q7gy zE?uBphON9Qt^{D z3_Y$_Z&u%RO?+wc_sS)!S4%CO!Zhy9kYqak@5R-QQ~mxY|JqJcdMf$0N-K`J*L1N; zVP~gNw&d69rWx6elf%-#d2BkhqWkeu_jO*MFD7{_RNkI=u$|Fj_OaL;Z;9};)#cA8 zTYi0THFWxiY5(`Rc^7`oMCw z{^9Kl&9Z~{w9GWs=*)$b!Xn}y-%bQN|)wal-ikZoNH~k zKBKu%zNBH9k{h=xo264 zv~OV89?`LIm1otrAjS^wuV&vpT+c24 zbN-p6GuPG&69uj}N6c4YtIeph)?ZnAu(e1miM{0c$r;H_YxqxnkI70p`lRlP42Ny& zy=>`3^XH#k{oYU9>geuq-P&8FkW*##jOi24oDEjie785wRWT!W+rPyT_QA#pueV=q z3zYkIs`}Za@cbNm-M-Ba;%rTi&e!F!U3qJd6ziTBZ{9N2S}c!XZIT5aZ^{M>t_2uICV^;i?aECOH)+R~ub=?SUF$p5eV+RiOI zr9f^%Q7Q9>9nQxi7WOXl&+9q<^7x#?OMdVBQY9|_lPUZm>mOC`-v)Co%u*tK&-zwXXXiOdlA862yMof0(-QlGl0WU+bzR7;+~Gb8eG=bnujlQ%8IKmxr$} zO$|)Ry`FqVy6dmmb6dVwj6%1#leajZ_VGHze#eAWP-AIkLGU??n!`>hUavh&1dmS; zkbLo@@C|Ea$&R!#n?8Al-O0JiN9-Qv>WkdG{BTib`C5}hN3PiHnHg=}aVo|0hQJ4& z%azKvwAWvV4g8TQGbhF}aKhY&QjBvq9{jrOac<9#NxfUn+BjZv(Az%O*Lb~Q;APq1 zi?hzY%#fYq^}wlNr<>&?p+$EjR1eIPEi+Z)a_5-ZnqIiBb5@R$Z}_;BF`MInf;#X1o|5V>Q+WF`)gEq|Wx#t<;cFV_^DM)4*Os|lFnYGmSS!}? zd98wVypz9HjdHJD+{>{xy4~4jA*UFgbGIDTC1d z_AAy_L3IZlrK(frY`xX^LT+DFM#_uGH7hhrOuT>IRBemsziSdQxgIw#k#k8K`WUKTrzcl->{qCtp;#uBy zt2F3z371V%-80SAk4N)TcdVr5rf=Jwjqj{K$rPVu6gI0^t9YVFcvtaJh zxJ^oqECHPxye=gLPhWC9^kdU41?`(E4Z1frRnJjZbmPcj3Jd#Za`BE_@wLy_d{!-e z+VkGK@gdJ+8`<4P+l41gJiU06jornL2`B3=J!LL!&2!8=$#?3%Y=gn_lXmltczoNY zbX{(@tV++XZDK#dE~k~L?kWp)-f@ztrN7a(%Wis(A?IS@g^9D4be_4s!9l0XOfu(~ ztESH$qu?7??v`n^Mwh9!UYp0@xXa({?5;&86&{Hi39nu{e^tY>+8GkdS(ZLp_<6lz zLV^2Y<{R$}GgzyRtM|zsIIj0LW3l>OzeBk_dxMvm?tHL2=7#o-j*g5}sps}V%o~J~ zZaB`XSyr@S!ntc@PW$8%);-bqZ6V#!%+VaP{``qpt>OdExdQkTa_sJlRODu?c{=5` z|K|mb&G)lb{5*L5&Wk6WMe=V$#a1bw|1~}5$&D4B)tcsaI*w}mIwmRfGG*nGH+wbz z1We2F72+#$NG#5Ov(1NnM!xfsXQ#v#$QLeIRB?lAy3TC=>>rtlpPlCfKR6ks9bypj zTOi`ULDQGS#6zcc=}w9(-aBXO$EN)KFC|+=9y&{%wM_g{q!Yrf_R@A0;r7uxq9 z$X&Z+TZ@CouQiigX3jN;Q}wJ{xn*0y{*4P0KSY|Wd!c(H{qBl~VzoRiJn#N>WlI$- z{i-Idvnl^%xaNZz%h*X`Wy02_PcJ$|O`N{$gmUJhm;X!L8nsL38|N36BB7^gNYu%owF4e6Dxi1_-n<9G_Nlu(9BJA58d@}UVro~BfRxDf- z*KV0NYsLM8$$I`d500MW;PwljTxrJYxjJYsixhvf7UKiED|4QD=s)Y3^#1Fl&doDS z?3{M4_}BlWz{#4C>DJYhr_1DgZ!dPZe9gJN=wV+%;O{3Vy0hkQtiQi z%SC;&XXVVg!o7K4wDgY9C5?9k>okr1j4+(xyN=<9~Y|uSjj+bd&n={i3Jlhq;DNZ%mfr**Cd* zz3V=QH>W1p^mdeP-}FYop*HY3Q^*fVr+XQT)y~PA{W)Rk@Sbf=T*>yDzSB${n*V!j z7BGgXDTIZ@ZFX)cxx#Id&<_OES(vzx-*q`lu zI4{tP|C{U*TZ>xnoMpy^Z3gZlmlcEGn-vsQEe+4vkw5Fmlc`hAq-~V^tgr5NN$`=G z->aqj@8zlQR^7t-N+%-YA>%EKOZWcW+;nX%Iq@x zm}r%_SygTIs;HCmmK~dJD#kH4vBme($(p3YKYJ`fXB>@q*E9ch>%9r<)Hgp~&vv%F zFembpUZfH&IuQZkyv;S^DfrXYLjOgJStTXQnD=1Ze~b&#x?heKu$FlI63P z*jj)4^m4Pyl)aa_Qy%yEJ!G>APPVHRyZJ=^&DGr0PYefd%>KDqCET!nha-v~SLBw%KHHOE1eV&eY3vUZ5t6&zsCE8MBN3*w%kZ@;T+c{%~*kk-JY! zmd#hq?Y{Bf2-G6HmrD!Cd=2&bx1iQD#_bqu^UHtx8p8C3)?ae#>Zfkwe zwP50hw6}T3Idg=kKhHn+;N<%K@2>s*+VQ-rt*-EEMEJw9eO?N|_on9Z>iMmiEy!h^ zUd=rzT2;_N`KVA8SPrBRqlar2RxQ1msTPc}gw|RTm)-4xrh}>n5|C!?Xao2Q~ z8{Yy>ty*q3c~au?(oI|Dx%C~hbM|3*_C1@kXZ?RJ-)|36_xZO6CM5nbC^q(taFg^{ z@FnH5^UEVESLT~JbMEF#6ZSjr_5bn7&ieL!dhF9q&FNO^YA7mTF3r*R_|o3T5rB(sFTFCd6r)D z{&=+1AE`^_P)<9yO|SSpPf*p%05{LpSIXPhfBo#t`lkIjgF>C4Y4SY%K6MWPua`R4 zc|Wh%e|Y|UhL^qyzcD%s;9dZzvtVpsWD4u& zTbg1V^lJ&~R1oavuZ=pLC%aSduJ&g^C$o3lFN|vJ!w#}=G@VfpPFbYV?IX5L#Jevw zw(=PNkN3f@W|6LDx3BXxMfTj;eo{}&KXh*JliS{!SC$_6f9?PMJv)D#?SJ^`-SqB1 zUxH%m?*FT*{rJsk?f(g{Z%^O9yNyvRMs4DrZ{I%sdfFOwKm1bn68+{Lr}()2JAXX? zbo_82SMJiHyvlNeLs9ZqKD|+J-EiyW)9HsVR{d#@pC{kvcVxz-NV!|@`9JJ#_Wb+l zQNfj{inUihy+0ht$-DX2)3$#x$B%E=W3Q38xU;fKd5Njq@d$BOBeC2~dI#oMXzqKt zB)0C{;;lwmmRmdH-O(9 z5IR=LaOSJ7Ld&%<_v2q5pHthm<*HYv(z!yDQx8?#m!39xGUF=yrN}#45|4c4a+io5 zb7MOko_qP1cw+s-$8U~aJSe&3eZeV}CeIBkFLta*IPdr6w{%2#m!xct$jzAtrwVZJ zoZoJt!TI6p>21GTj?e!%S%7x~*R1wBz11A&KI_^Fs>tm$t}b6Aof{%_X|)vZti6-Eh6nxB7fz+7wZ?30GLt=KgQ{r^2#9ztnqW-J+-a zkF0lZd|f}iaoOUg{E!8{ZxcG~9!^m@`d}9iL$Oq1$&-ztin%*IWlpUAD7kXADDTSq zj|Ebl*_T~?7<5c7>1yZd{Ris4%@voK_Q0I6bNe#&v%Fe2JzpOA{#4YqM(W;?2@4+F zcowl~Ex&SG-65$bcHOsyl+)sJMRnvREK*#ma{3dCPM~xT$N4o2=D*aIP*&qyy;DDf zGyKEm%T5P(WqdiDp=|ToXhGW-9p&{(UyOf0m|&zZRa2}?oo`|mKeNGlA;|>+ZBD0K zGIq58N&m7=)GFo5xu))Gu6{d}tKae8YCJsk*q)`n4R?g5&97S|{*SR(E&P?xJ}JfZ zwOWk&wTwj@zpYrH=C-oy;!(S7-upF&j^!UTzvj%Lv%hVAvsjQamydx!38N9$m6Vmg zUe&wT?~}j0|Lq0FZ<0E`Gkl`6s^;|mjMyhR`I!AiChhb)d7Nf)MvN8-y;ooG-WHlB zQ~7c=XEtxB7v~P^*cDRjlhsboI3lrX#}31wk2mWUq}ALF(2~=A{rsULLto>H;7oP3 z>n63W?;X#*zIG@$?pSeyMyKfcErQEe7C(1Q6Wd&KT)AbN(Kg8^rSaUo{0GN3k z9^E#rE&b|W6KA>R$5Jkpf?{&JdQxY%6t^uu`O=2prcqMbg{9g2&ocHO!O5F;#3-DK z^V{)k!punB$|sS6tM(QszEho^H0ia5+G4iX6PAB<{gL9{lKsW-i*eEi2Z^IvxobP@ zjJgglIPmh!MG5wo2hT6?WGpXkxFjC?#AU{Ue<#c@MJONG6fM@vy8S?Z=~3P2vpQu~ z(^BV%oU8DQop-*=p|GLlZgw-zb*B1u{!CTVyeq$+b=}H|oL?+?`0bQQ7ayEYaGR9X z!{Okx{OHWaX^oy&A}_K%)yUXqo4`8hrg6Y2#vfVdCU0ECG(G%)>iJK(yhd)XkMP!X zZf1@;XlxT}oU&i)Q;PlnI8| zVVUR5;>NXp()ne!T*p2}RBX6&+NkJW%!RWPU%QJj&EB&iuZu6xVT#}9?9C=R_j{%# z*`?2Sf4~$IV-W1IK_Jl}>GAu*J*N-6=kTfBvDk9+*T%yi(o*kFbe=vF>w^$y!3e{71+-R?a({_Y)G$K+>! zl8Mqd`excif0jHq_4(#?+kIO&j%MbiuPWFBTb1d});yTg-E}qh#iS18Pg}&e7hO+Wb_x+g2U#*!UCJ=c-11k`FC$4yCLTA6ik z`@DBD=aw**>6OLwRi$5DWH}-IZLk&Vte}Qdt_!||zuEMCoyN8ADb`g1uQM;FNuAyj zp_RGa_*kL$?)aLQlkaU|x%eh-?!E1O3I0NxSIuZhTe?}I>7-g3m+WK1saBW6X8+ZF za8Se9*y}t;^#lnusZ(ovPtT7Q-GiDtj$4%T|YLq zcSqm(s=ukDJF9QWX4wa7kE)m^t-MxoAj)N@+$aoM~_9%mQ&7*DjmnI=;25&qdU>h>kmhd(PL z%Q$LX4{cUied8eawxt(^&E^Q_>q{M3?rS@#O;>-V?B0{J4Rpi%W*$h-4E_G@vWc$H zym!|=I~-^CwJLnAS^1{u_qNs}#V(dP4Yl*S+16NdHZL}b2zJ=I;qa?v2ha1IWUJ0~ z3r$j*^EPY1 z9KsJjAI$f=P}$G&c7gDoh0nQGrz9~8cD&uT?XPi5X|{Q^0* z+PWRqdm=lP;So0+X>%^U)e2|(t<&0_ z&fIZ|NU4AIZH_wAquis0iMK0qUoDQf{h;REmlgb~&40Z<+b@sPh;k5!USC~*F3L%$4s_}a8LJ)KQcccIC4Mtfwz{?{0!! z*sfL@F?;ff8rkeBj{iR=pVKp3KVNSnyv%3j%{=w{k&BJJ zG-v2u%l7ZgKUo#BO6_v~XO$nQ;9ilR(DX?_Xph&<_O7oLEr06w&MFQ4y5ZI2sYkW* zHRm%$?0F>dXo}i-zuj@l4_Us?T>HCZb<)>$E51lBOz+5^FR-e_u;Q=&3p@3+!?pYq zzD6F;YRKah|MGK5$V8(fZcX(+inVKWbfTin?U$d`@J;Z@{xipNq1tJQ@b#-bW!kUq z^xWLOCpO}F3}?RCqJ^K^%WAHQ{yx8bdwCvX&igGJ+EW7SFLHcdJwN^VyH^!{90xaQ z8P8El>8V6jU1 z{WaQF+s%K*$4zB#f1cYlOJ0pvW7EsSUIHd^nm$oew!TvNEgF00=K0vu4>%smI_Ag8 z36?1=JYD{u!LOM~@T-7BtE%-)qfvpD=(Z0jsvtG2D~E4Y098LzV`TR)zd z`Ewhq;MY&PHh+k^Vjf=a{?%!p(uu7a8&8)Dyf(-*NxOAxE$iu9u9v?QeO8aVW%ecH z!>_NuUw7|6Q2(EG?cEtXn0+ZwA1Oa6i_6&9&=A&_GBm)PdNDL0YVKuk)agFi?Sj7B z#D8{luldC$)%E_k5{FWBa54nvJu_tgZyFR#Bp z_us?aFFnOH_in!Y)KUFmiOwNspHq`PG}rW<{PmJ+zT3hrotGs`HVH2NQ!=?;i`6$S zVMgJx47CTmC&L3*wS0`|;4;hdG3}545*#M++VtgfrYZj2U0mE#4tiO4HVX!6&dq4` zl2pI*#Z*jp&PF{)(KD%Q+O(dZo-S{2D>CBE*-tO3zTEXTnkVRX{G~L9cu=(Tsb6!i zU#qBT%-{PxLjB(Hggwbl_vJS&RAQUjekn@Fay8%MSf?7El)W#{FWI>L;`vL4>hd8b z+fIp!NUYv7S5M&{duH&esvAe_begwr^4Xpisc>{>PGqjjhamIQUWq}6rXARF!@9Zl zjvddwS+_f0EL$F_u3FntC1qvF+Yz;Al97XIgy3x^lYKMU_b*T9+%If)n&au3o*S#J zzSaEWan_AXO3i&y`hRM<;rrkzH|9C~X1Tz!@{`>}aTizl2bY%|PU7YcooRGq;uN0C z{RNpzuL$_<7Fon`?P_e%sT+|y!hJR`TI(BUZX9!f=fX_I%bo>3K-q-R`|hkHL*E%$!Z}2aY^Ht?=z%(Zrvt zY;6>^op|5AnxpbRvXcM8cFXf8K5gK7R&%ZG{|wLsT<{hhWtG#@3LRBeG=JV~%hh|a zoo`+c+wGR6`&WD`P-G7FD0(~F^+I>^wF5;eC6Apo`VD;(rGyqQSewm%{!<1on^p8p z)AJS~izW0lE#9ZjJ+b8G97E-)DZ4w>3 zS@84bdlD%+6YQeTd7Klyy=jrIPpo6w%(I@WC$GBJdC7HSrMUB470>jWhpldTouBfj zBeR5I@vlhFD*Kk`+sBr@zsaQ2#=dFg(dB`>v5huI8~YPq$Uit4cDc{Mz{s}aSqI;7 zyQ9Z0v|sD&b-!d2mAj{3w|#=4%ekjb+r+b1e6Rj?*|GVj>WaRb3$}0YT;yhXi+h4V zv!n146Q#S2Zo3a^-8B7rhT&7t#&%D(wau$^+FH_yZo5JT8oVk*!og9&N zEvh;BNzDmmr=T21mr^#9gua(o7Vce>?r42UgT>)}db#Q(Jw2VNGv_H!Q;5k}YVmHi zu|xdZ#S=KJWs|miH+e2tlp;T;(B}N7n=4HDzg*#eNu zvuS^uc&Ecd!G#-+Z(@X2NG-KXYd>`XYa zEada&*Jpb5e%@<*);Xih`&g)8Oh~lG4#ttjq)^=!$wOAukB>L_57@9 zWzdrqVt$7W?)Lo4@wB!RyHVxKJFP2fbHQ1OuZz1HT<4#PN|Y_?S=#5?mmFHN*&$kc z_NJfjCirlz>V9Uc8?SF5EA*v1j7N+$l<9&SXVG(B?kB&dBu(43jZ2m5xpX^6+btI6 zOm{(oJYaJTjOR)C>E)~C;yPy>?wX)#6P{h7u{h7M*!yZ`?WxNf zneu0C(2Oj*Vg2pQgu_~8BFCdt_R6T5q~|VrCgC0QVurAR$HrAJvqaQhD6m}Piw!MX zBVx>Dvoi0YbJ(X&))dyrAdg!=?074t%>HnzL1JZZbJz8sCp6X^lRp`^K9S**Z=h`E zI@8j1?6J3f!@~j{ETRO1GV}$_<(YlG`=Qj;adoeVsL%C(r7#M0oFOpC6ZFA8E}G@8EV9KXin>OwniCpUqaca;v|;meQWB zc_(k#wOjfQzGmn51}HdRTQ+q^gyHk$ws9*A!nwPi@tE3gO_Sc=Cns#MGM44=lS9>~ z@1MVYWs#)6UdkJ5@!M)gcO@y7XKK4n;lFly;@xewVH0v!@@LtHJF4io~Rh1>EgL#PO0ftX_Mc# z47tt+tVplwPfawPyt~~aoG+*2dHRg6ik_D(H|||K?Z)w(q?2dztHfKTg{&du;i_^4un#8RoBD6J}k%xp%RaxkQfG z)-IJkqd!M+injCc{#?nhpb@wEL)ndQC+zC1*CCkidE}zNvD7C75VLBt<^Vvl) z>uwbOTz>w&W?fKZmibbdy|s1;O^IR0ZPwKOT%i1DRp|T&;aV5^uJ&hZy^#D~_2F*K zk=MTQHD^zqKbyASGU0^eUw_q_ReJaM{jVK0%BXm)5%3_ad|&C3+iMqJt_kJ}IPoO@ z{p~03cwZ@R_+y_jxn{z_O}ovXPG9v>|L*IB+omr2*UIzfmj6DB_KykozVfP0R=gVj zi!*Ouz>_=A`hqk(OPb>J>XvDH**)v}_P@yW<&CW>Wxa2vnC{ut?RkJRbbXJ1WYCdd zdy75ibFcay392<-x#WM;Qp4oDPm@>7{*l|>u@;&ZERgm$b{ zTV>ji^V6yRMDE0i)o=cOzrX$X`Rgg3st2_FHn8kHvfyIU$M@b_pKnR#zaHBlcA_(V zdccz3PP0O|Z{1yZe^2lIZ!cz^j^XUn+Izd}{5RF=h&7KU$*L=Ezh`y&X>82g|B+9Y zS@9Krd9JKFJ16YSrkc08c2E6(&dWTwF@5?}yGzd!i*8;$#8W08eeh<8)WN>gsKa{} z_U3g)2>Z>lwYyupyLx+g$=$H$+)ooe?)ZLUTfn)ujoL!4->=Hs-n6ax^!4B2esleD z{`v2&zIzz{WxxCVn#TR}YIgoV`|ji9zuVp4uhY)_?zg02#c}=hi*v$6m`xI%yyh({ z?IB_Xe5L90OU9d~O-hd6Ti&g^8d>(6U* zrtWGlagogmKc6`F=`jW#(Wz=?MIw)LSM2w3le+6UWvQXFWbauGT#SG`Wdrkcocv8a=$yvw<7w6?yrugUkx;@du~h?{8Hl* zaB<6lr?>CcGyKpEkih6CLApQSj*^kNF}$N>2mHKHuicZuR_imoCq}^EdtX*UMK|Ye)W5 zJav7y|N4cEUv}?sSw81x?EeDQ)87O20*~$Zd`tJz+jaBfYd43tFOGE*xmHvCH$6x5 z>jjfnuG$&3waoJMWfomWSr$J1ce*)lipZ%q|2y`#d@ua}_2COK#U}pWum3$2|NHXr z;Xv)ZEXm)DdZnB0>$fld?yzp-Z}uBrl8S5Z{x6qq`119`f;UNXuKZrVVXw)-mw%tL z@8-~+bLaowt%}B~XEXmVWmb2VU$r42;oim#4_4UNh-ei*+I?)>-_6YtdjiAW&QF<@ zbmjMLw|lR@cza6xJO1tId4olU=T85<+}v_9GV$Aa{;a@LnVajGbD~-<@>MQg9KC1T z%(I=_swD$X?qCr=c_aUJdq2OI?!h*O-iOY+GuCpm7dTw{rMTtdIhXDKqqG0ISFHW} z===RGH@_U6&fc^FSE8<+N*}iM`a?5g=Fl?A+r)qqXdu_A3 zQeSJ=Vx1rR-v0Q4ypOd=fi{!b5g>{ucpe*H%y^TdbsuWk3{*p@!(x;JqW-<6qH0)2kHTx-2s?(w2k zuCpDY$`vj$3ZKw@afppz#pIqdS@~GWU z_u5S_DJS7pSLR}q+m-LxcRn>z;I>%8s_Ne|@ABP{U)m=e^|oB>K67YNozmR}YbUUY z`7!fo{nzYRFndG9{-x)(GODVtT(-wGMBi|hN6WjnTaqji>f2;CaP4O2YY0wQtSC`= zTg3k2MRSWS@k}%RyRV29U%n(qd)X6))E^>s)!uCX=Pmx`%U02FuVoF#@n=!XC(b+5 zRvILvy=CDQ0qN$9>q0!!R6czznRGXBfpNs?p1z<%A3iAi`jqX}k$Sc1_M#`}bT2ly z`t;3?VA*!5`?Rj8!7gXYdEG1TJw=TiE%*CS>MLO>M@ipXU=85?(3p>}25YT=rmkGpjtC zP2Qo;EhW0S*H3;<5xVl&V0MC-IP=wA`VzjMrTy4#mze5ZF!kHOdR=bWRg;wXHy4W? zOyBdau3c#!u+?Psk$9f2{wmQR*V%72vhP}we*LfN&#NN$Pd#&p3uJ@-1|4tRA;Ysk8={^sisJN$KjJi4l{ z-Zba%IW2JZ`UL`$-K0f5 zoPH!6+2T~@Eq9~E=22n)JocVUw)a2Fg5o*eF5P$ZXMJJq*XygptwobO4zf&mzhSab z!*7`~zt>;BfBd}KUp}Vx(*yn8^W*pb{r75e{hKFO)#D%ixBL6c_{Zl5pYOh3x36Nu z;dvWsUwLRX%35AgxgePH{{G6vy$l>VH)b+)gs|xxJ;!)2`_JRg%&*Lz1_mGWjxgAA zxoBg8=;cG%0YzeAFMcIFQR3B@cb{*^D?2R_w;2W{)3;?X=s#6@c+Df(pmW>rWr3`Q zmwyOc-FQ9lxYLqy4&x6qTP{7=zsRwoC zulXWQA3wi@dGao1yMqrpH%2bBys%-j^YoT&+9x+J*s*&ix14BP!)o8>|8|QxJf35} z-(>f_xlC8D#;o8kPL^$VjLrZ1enGR$7q+s(AD$(ryY4QSU-L!%`1g`OlMQOi&*dEq zaj7+r@?-fhe>rX%Y`|k7x#(e36xqG;Ed1RNayt`bC&7(oO^RnNG3Nve? z$IBM{4tyR^+g^O%!BoQcb=%2!o^01e&v-SL*?zfmnC%18zAv}7wtsFf^*8Hg%JDqP z-rdxD@vnErM`qpSN1oeWtM;xDaD1PUUh$FhLHfSgGb_zMUQFavu-jn%?N!jngB;UD zzVWfXeYfHXEAO_T&e<(zlrrY|eipRso@=sbxoEqcZDQV~w@F!>Q)|CXdvsU#(k%tg z>2mWk3rtS8>pD%I*U8;#v1`tOJ;sWCGH3tqugO}UTYWdW``D)Lx38-olz2N<+|a(W z{JOewSw3%?jq!v3B?ox=jVJkE-#hm(yXy5Bhq%4Mk4xLfJ`+&1W4R)6rnKUQ^z{?( zQ-8K;vj14~Bu~WiZPCR!v+iHm)|YXN(a^K+OkXDH@3%59z1dVIypfBPq>%s4I47xnVqH0zm@xc$9m9bPa| z>(lMWm6k4|wi`0bLzc1qS?`&ZaMR&eXKezV1!n8W_U0rTT(LaQ?##JigVI5#_4DewW_B~g?Vn>5 zQtBpc*|j#J#Ist^Qt{PI z!?!3cI+WjC)*Wj{$|+i7mJlv^jFE@H2xz40~SJxd??Zw{6C z#V&9u#&y}*nSpvGEPt<__1biN@ouA3gT%{@KlFs}J2FpS^Yj>3gY3kJ$JfFWeENUN zSj}fvS{uiFv_R+jicYRo^Nm}NP5vZicH3Ms?97K13%}&ftvsxv%`xxdtZ6H@R$f_Q zo2F1@w{zm;qpn;D9J2%zy>_t`Tfw=v zGv*j%)TzY3cF6MC<@Db799z zc_4W59|yB(_Rqf-wY_<9p!%cQgjZ*@!nAUxob|qOp%8uD8VdEsL&GrwR4W=60 z|9!ys;F>)Vt;q*PbH3eoZqL56V%?e-DwQ(rd7oY#OHkw2X*_PBl+Ut1cDb1Nnx#G; zZ@T^3{_odXv&^YeI4`*VR8tJF{C@3%%bq63zXp0Hj(O4C*Sr}$KC{~IS^Ox$kT>z; zgZ3rAY&GvJQ^~sFo-uv3bx`MHt^IaaU*czGa|BkO)@=rGG+~dBmRO7~})+WUn&or|S_ZbC6 z_bNo+H@+77`oY4>TRA-6&q_(y`)6^~j>F+n+t+5VeC_GdV|_W%J#T}LepT1(pw~L> zMv0&16`O6l(&jyJyRYlpMC}WzX_t%^wS@7yNCPnpCy#@jV{SUu@Sb?H29I)%0GE z8A>moTN(*FWM>|k|8?4{>3TWGybIqf)R-L6bWm0*Rc(oK^K07!FCHhm+&=tm!d>Np zrAHU%_intE@b;RSDQkx>PjcelTdk`S6U`m=$gfB~?Q#9kge&=i2R_s-pUtuFMzXkU z=3dkIjG7R(mWv-AsDF5*_1FA#yYrSt^Q^B&CVzZ#L|FgD)z35MzDk-BG|BnccTPT@ zq8S?=ZZFf0aX%80!q;)}rjp#H?v-04S4t{d;g%T!3cY^s2?X>RETqTQ1q} zzHwQne)+jzsoX=q^X>gCj!d7w!B_YZ|Bbq?Gnc%)&#u1v)sD6B>ho)*Z}#)fx3F15G*8NtspUA}Ny+swRj zdfV9>LCdAS{W|yNfBCi)=e$yj=|_)<%q#rInsiV}wy;)a<4!55A7|H{P2DKY`fiha zllJ#b&wWo%{d2RY(%tDz^r5~fohKtSbRHR`eYUV=o7=8(w8BqrcgWTmPW%hc%+pc4 zaqjq&ts3qJKW~xV60ZJSuyt;&I^VhLKI#!{`d3)}Na=hDtE< zXCzJwN;j^&_H1cO;suqgLr>ql@cYD3cYtZ$e=C({!}N39a#!>Hm~z^e_*brNp2E03 zKs#`McW+xyXQRmGiDf0vHYoT?*%eqE=`)&g_|dGUdF!QS@XeomaQ=C(l5@J@^4U{= z@4d0~oN=~Q#p$`nZkO!2l)d}9xAQTZ4EwddbJ~R!``#pMKm6gcFFV)v^}qPadbj@n z-RF5(L3ka5bn34D&2RsEv9Eh2$y2#lJHh6mpythm=2HdcENfbzvF)|uWy_~mCtmc7 zsk(c~ea;`h?N(ES|2Xf7Oy0LPUT0C}swt=auM0-2WX}0nVeVq7wD)Dfvdv%lk}qt1 zq+7IbnfMgLuMgc*H2bX#rNVf7V%FPKH5+^%htl^RG3Koa_`tXv(_eS>PW}jG17gaB&}`h@gm|u;Po26 z-RoRhE1GWobYO4;-w)JDZspto^lRXHQvSE@@$XQqn?8 zg7NQ%1I3DWh}966^sYK`AZc*=JQOnf!h&UTA;ww}n6?;bCe4hFva|J-!>CI9%I4g0Pi(fBv5 zbLRZ3<_DVnzr`HAy>oZxHm~oikLqm?2)z+s9H@Lm?jDQE*)UJ%$!|WYttqJukTC0v z|04ANqk7tQkqs|qvsD%~`7ZDFV$r#<{c+ooN!orp4*cu%+PqSrSK;$A?Tc4WEzdvS z;;0`}m9uZ_x1+D-#9yv*z5I$xN0ujgP1)wCu;k@hk4ygZu0OLcI#TMOMoalwiSX#d z@q#=2(u%#h8w^%|zPd5_!(T_%uqFGY=3L#`clt|m_KRFAM(yQluO|8?-uU$2YP}HW zPXDKkDn21$`$VOuWM6&uQ$CSp&5KtJ$9u&;=(0^~X%M=c-Lvi6G{ez zxpIYCRTi)8gc}dAEPB1WguRWIUxC-1|10ah z7$yB($Zx%ep={@5?Q)d^;$>;~ZX3+mE5gMeli=vGJIpfS!j<-2zw+2;XX!6F({S*2 zOCqm8a;HhptHYDLC0|K$1Qvx>{L=4KnDD@G$_J_YkGC#;asJW7LcxHrk9k7zUCkR9 zjwf7@p0V`fymR}PUay$&M7yTJ(w3AdA|>nBD%L)Vb=>focZFQm=hKx$J+17l~20Lp1^*BmF@b^e;o~75xyVS z{FO?ZSiz^4Fl$Nw$;1`w^4(>Bf0F%;eys*)m1UKko?iSp{^7 zHFBgiu4exF{eF5r|LZ{etQY5FwdVR~K9vk*loxIGsVZleX6MgqStI&$x&|xvUX!H_ zM;a#Hs;@o3lGD7=!}0Dhkx#{{(@u#6C^5R%s4>qgsG4z3So@3bylvkre9kWj_4^ph z{wO6_(fjS^!e}F|OzhTiIe9~Iy7Nli>!f% zxM#oq47vK#lMDFt%QfUbd3Wrr-YhNVa*g%Q?#bSoAK!8A*e-;niuN^Hwr+q%M!cjILG(mp1dR_&L$b~H0HCGU%(Muv?QdrQXd|GyN( zR!-ge`@h`^*RIf4f8X=R=^gyBp}xjqUH7*`8k_4|_AiZVHT-Qa+gBFJx~Ed4JIHa> z-|+UuK^D_i`0sDsIQ8nmM~82GdU~v)zRi5A`RaF3|2ssu-+uYWZ?I#^>0Pt_?hiG( z{NYl^x?r`+(4_yne`U>D+9s*$753hyb~4|G)ZBlkAOClmW__w~>7PeBpZ6jT5uvc1``6sBH>&lz=`rPU z_td=qhaL5!*hF7=F>A-%HA;O6yq<%SDhid@_a%-<@XOHd?|fa;zpL6yh}cc#wtB1YUuS2 z_{hACF-*I>;GmGNhx#QIlLeP2ti2^LGlKi|fuzkBC)cN1oL=CV)t|pk>PpjFkLKDn zVch{;23r(7ZJH06t-tn^v-$TK@63=k|C9^of8=h}c#x`W;TN`c0Vl^1&*jf=WX2X; z-G6`jN_9gW>!ay^7daKQW>p#}yi81A`QxzX=6Z(xJUk&P#wSX|Z<$?K$$sGYVRPOW zeoq@$T&Dz1fZOaCO#+;|Q0uN`XJ1kLRn96ZF>+gp}Eq9-4gm8MD zcs2Rj^R4!e9A>B%ZJ)@Nyy~c?Vdr_3ms~IAZ{z*B=9^mYin^BgCgZy=QfJ3LfA10b zeA=?agBgK&|LZ1Hd$4VP?Dn%G_e5>$qd9`w%*OAu!!Er$A{+7GpyrC?mQ^Np%(06k zD_AsN|J4fG?&+{Np#EBq%Ox)32?#xB(&~#xcH;44xs8{Z%xb+FyOp`jJ8Ic4$5&2?m2EJ;cQkg6 z`WsGZXrJdu_J$3t!oWnI+XS8JFJv zsJZm^?-TcAwTscMKPIz1Ja+WlxufqhWZ5rqSsj*&+qj}~=90A=W*vGpUn|UGeY6&H zRdz>|!d#9kT+3Z_Uw^;4FH_q>dPeig&wW|!>>q?L%>Q9%-lO|hES;^+GyU_vb=(#Y z+4mp5byBwK>#Ib$wp-7aTyC4tAyZZ)AY`EU;#r#FLMzwHJpxu$S0~!5x>U2ORXCO` z*X}&0z@$fCkzHY~Zk~s^Grm|%VTu#{-E`Suj`zh|b(yo5yzp6Xu3LKb&f_c^??)5rU$orbYbvHx% zb~4s)7QSO2Z}EHa?QQ(~LmRDT$}ux9{Pp91p~L<=4O@TTW`4Ihf#>@BzrgrCC5tcmmCSYSDc=+*xk%#P!!r+j*PA&9 zFt+TzGI^$8>w%{k;!6Ax#}>5na~*6-tT=mn{?YWLt75NX1!s2o)iBI_`Sou~T3&Z_ z+=G3$O8SofyV&Nm$YjI)>U+KaCbZ1Cvg@XIV}IVH0Itm3JNB<{nSHyqqANXV|II5| z>o_N*9ylXd{_*hR)#tvMNu-rsb5Q)=<$S37O0B5oG?uw7H#lb38|hAbV_$Iln2+0* znH)==O_*jHeW5?P>(z@h;>#Q2C)^Z@w>{O6$Xjvuk@%)owFTVA+)dM>44j`g{tQ-Lv#DvTct_;s z|4fmr6Us7r4n9_py_LVANN?4wOJ8PRYGFzfOxw!oD;6xc_pz(N}uj8?cKfk5y4eaJBOmA){XXgzz;?&fUFipW@!$e(^{w zHpxu5xNZObia+}I4Gr(h9PbFK7M1?JFIVx>jX6Ogfs89cV_O)-PaWnHpI6FR9OS`f z{8M;ip|*|G)$X0y*Ov0H75I6iTFuBU?G8`o3*Mj8|-9otd+|?+-nt>yo>q zSXA9A&rLM!+GBD0jO0b@`5Sr;=v+Oz|FgL9k;g1m!JkEWzq`KN`zW`PmC9&L3!a-?GL;^SWQu<}-q}n{Mv) zVf%5Wi9=RL+0n|Yq&cw6>OK3znXbk^H3a9o7;f28*1h`s?#}t745VXE_{M z*&v^|R;p!gLvKOcy!*Rr*pyAOU&Q+HZg7cDIU$-T#Lw_yX74_`KNC(`$Fd$?DQB1J zx+-=Sf6q>vlKHqF!Ya1?P040A#t%E+e37W0P;;WW z<-zifri4Q_dryWw;$0w>{?hf5L(B7wmq{&t0ax$d%Wd3s3VYC}P?4?||2ybzWU3J@RH-C!5XBJ2)q<x=I_FbQZ0t_v7(Acr ztmhfwK54#x(eY1Oj?FtP`K}eVi>}#G>9~nK|L57+A94+LnEu|qbdz`BTE}PCp1ck5 z>bWl`yhKfM&C&(k=07~@!x?^>3#>^z?8xc;MbyWhLe1){9+s(JU$Wyb(t5tH+4b_#87WLS8vGe~8 z_|YMG=*7C?RLdCF)Yr8qIa-4H)l&B#lgRwmr*+}&r8kYA-yZe!o|$pydgt7r{r3X- zgd)pt?a9pZe>nBS^F!=&*}Fpd+5YI){k1Cd^9gMwdl~Qisw>{!&%M?9z zalz$>zJ=#vm%mzFzE3b+AtmqqQsHx!(WlO+b>CVLy;bBT1F!C@%x`LrJ|c_mafbG~ zYi6jMT{o$%)0lNCFAuw7r(ZnkA?mUc9-=vzWAWVvhrZ3yP!?!l7I7#Cw#gl$(Nw2 zYcr>JfmGe*Z^c^tx9zN*yZ-8B-%W}R4||X^x2bE{i?p7v#o~vjq z&L=s=>G!m#oy`^fHL_WvleeawyLfo&g3a6)u767xs;)fW${4rc(?srPj&8@?eEwfD zh`qAlZb`$b$0v`t2krD)cFv~p-G|6bYw?UTYD?nXuN*LVlM-1Kv@nv3CAd|7_S-ok zX?@?8St%6VE6_RfJ-g%94Gs}?=S*v}TLzwI;sc#zU%!lUd|&cmz1VNxY4SIJ+Q|iI zU3n@TJENwgv4xevapSkY`RvVMvz8rrd}qr(tHTd8@7(n0sNUlEvt{Y6)$3cH`aFIa z_3z|{j`Onk%=fk@FZFsopTt3n4PcvM-9tR|8?V2_> z-tXHsr;6MA*(V zQe%6UI)++BYu+rWYx*Nrk<)jj_tRD%{!Qn?_T2aI>Uk$VZ?3sd{s%V3I?k_NHy*9IqSA7B^$T1_JmHfyfu$&XV0Vg!hHqT)Sh3N_Lbq~w$L>$G6AiI+#61x zc+16dNIpxXf~QmU;;b_wHnUF4*c`u<&f3y&)x&#!_S;+APMWaS-eh*+4_eui?HHtW zdvmQ&XR_Cnd%}iuALaBN6?(0^=zu`c#afl8n&rjCkE%i7E%jPK;mkykwpD#J?+#olVJZ{_Dm$?~>Z8*Pl}t zy9#Z#Ui+Ch`HstN#k@(I56ke?ulpzv+0PTGwK2})lpdF5itNQJmy`Ei{BqQKevI_0 z_5hZXxy;QT(PEoanBv|YWa`}{ntJW$h1+e6LjC-^&novm{aC^s9Q~u_g4tE8otgRP z105tn9_gygzTflw&RO-N0c#pEf0y!wX7n(6Z!g^Rd%Xt|&H_y%}QDL2a zuw=TqPv?haFNzYF4ldeI6nrJ%MD?cgjaEOVO)0kvox*%F^MLWbJ38+K^53#ZiEc0y zQ`)PzQu^HYoK>@}EAP%TQ~knl)wIH=Yu>Z0Wd>Dy?;YVj?w63dqqtdg=iBSeCemBK z?KvYa#S_!{-15)1#@SXI`y%Ddd;VNrV}3+RU~Zew_OKsk5Bq+!nqtlIeu^_o`O=2o zwF-~iB#o>iHt9ciUi8-B(1rH9_pV!(d=*seRlFgyJScHrX~m`mdrsch>rB7cQ?_|` zZfa!M&7C>XAMY{QZ<*g5d*St;7WL4e+8=Y@v;Tgv>rX{e@P~ib)qM`Sw_gl8J#~&{ zM#1mn&5@Nf64J(bHotuar(5XsNbLyjIeQ}469W|coJ!w(6)|uO^^QWKHdAsc49Dj}S@+p$b9E_jc2roS^ zJB>ls!{pJQxYL3=ikJKSK2UD8S{LRHr9jZTLMg+I+#&Ek$&q;bhVaLUb@eg}7Mc&L5wF+<s?J+8Y!FJQ_Pt)dUfUAqOs*%$shKl$%X<;hb7_NFBr3r<*eUt{N;bL)OB z*=y3W($a3j#I!{wc{99MOcT?yuUD0jlNL`>4)?Cz&vYScJ-=VnE|&Gyu^o(c`8wG< zCeMDo%XikPDKg8-t186f8BR;wEzn!aqCESzQ^0P~CS@nJeEB}t^`EzvADsJ{+bkq} zUerEUO~0PclB-pu803|`)^%*}$PGGu*>T++OT)Y0uAZI{^mX$o&*=W`!CypAe0yJmXyXDK7KFb=#ZLhoXKq4~2^h0o2!|BqEa_fu#Ke~AIuzURbdwVPYe|hxq|C=L6 z58r?If8USG(?6VFTz~)X;iKXGW%qO9-|l-Q8^`;!XLoxl#pX!D2y)N0m+pfZf zHFTX|#M^U@$3r`&e2bR)jHaJq1(LX zXytvh28ROx1m*BhCHgNmJuBwlD0Cj6G9-{FqZM`;Nr{ zW?q_GPB=D96Zw620h{%eomZZ2XTR_u&SUa()u6fBau#0$cZmL}ZODwgG11IlQ8(@h zm)qU=>ygiIHk_PZy?V-#!$JwFrVo$uJ`^dq^`JJ+VArAFP9kh?1H;y3pLi_smg{us z7r9@pahKm(aEXL@+$>93YBX!o&z1)&eIngV+>YU2tuI&aIPtM4Q)Jg9pXoOJTcZz{ zDSr0Y@r9QqrSRl=xx5qKDxy6l_dR@?tHt2i{?P03X`e~rAG30FALlAg-&)NaX%odG zbz|ba-czfWToyfbORQdZ@g9f&u`K$Y(agEh>kEr+sq9FSU9xz^zh{sBGnD;g6~G+* z29IfjN59Q2kw(AGF;4U`G_oLO^m}VeWU-8U(Kq8g5APc&+E*M?GsFd-w0gy0|%itJF^0yHr+v|H`^Y;jf<$p?i|k%)j9k zs(bo>@0UAwSIOl=V*SPWf42Sqb@*WnWO4OZ@Z##?_ldiXy_0_&eTpOV?Z5p|>`T_l z^PSQ==DGJj_db2!f~x<&n`2u<{oeiGz1P{zD{lGQ>1=a&_O8}p;@xD_ZRWR-d~I#4EMGzT6`G!VIIr|5CfR`$@k2 zR<6Lc`$xvpe`ecL@BBN<=(ftK;rhITwfwT#&hP&B*xx$p*}9p@(JKARKeg`)b8p)F zHwPLtng6^fVPYe7NNH=>1&upp=idHrRGt`BDf=ydVI}wD&901WR~ZZ2?;f3hPVe8} z<60h>TU+f^W1?o*^IdV|7F-rmUp;+YNq|LahU39ck9(#@&6#BJc*_sNS0?9N7r10O zn_c*Akt&`bC&ac&d_vRoCEuSb80Jq2U8$HZrYutVL2_Mllc;}i*n;IkET6>WTRn}| zzfL&y+HTR4hwl3y-1@2>zxCYd8%wu5m7OiV^PEMuV`GNiXA6;+cP{qj-I|KI_1TLZO9NN~ z5~qk?wYnph;xR4Zf4znK&LubHratw)V7s(+f@|f5`|(x#Q}2YaeoFZn*zjtfQ*lDB zN$fw1WyLZgZ(L_ApHP|OBKVIrI_Tc6U0Oeq<%KGZ%;gJD_O$&KQsO&&a9PMU9lcX3 z{1Q41s+Vi;)$f@-PiJpKo8H0fqTM>pS0=5Kus*e@O2P2c6|x$`a8t7I+LW#8TWvm#|~>~Ku(>Fb^v!kB+^+KV%i zwpIO)E_Abte_4~UHfqo6u4tcTu|H9zf_}?eFhSviV^!!{alL%lrJk=tbIdI+*v%Zhy04;{)?E>GzpD3)d>2zUb>5 z%REEUylY?Hiq~O!VeMycE-4NCeSZ@Z``#S^qC2+x_SmJ1-wT}T$;|%e%Vqyq7V|r9 z)#jSB_~y-cwq|{$jci3fGz3Xl@wV9=#%wf!Byrj8m#*xfeC72x&ZTZq?)VXHymzT3@3!~mSH3h@PtK5?Xnb)_e8L(*X}*RD2jp+AU|N6mg9-V%>TUW5X?22(rp>)AkzLiUtPoBJ9 z!tpqVo6aZSQo{h738B&xrmdWH_T87&O~;$=34AKNbJ6kaklXWj97aA8oGV>zUeYyIat z4`vB3a-VcAJ1e&@*Mce4&Dry@^Q*X}tcB7CCK{&9436X5&2G@yb@O?dH9re;d`r5c z;?^CCk!CtxM`kb=_6u|di61;vCKYwau`C**b3ZaujI*_?03TG zZ2Nbk3Tvgx9lFZ>Zx+j^vAsXAh;JhM%%fS;dv;w)?on4g@X=#!Z=C7O)pmEk&wRYa za0BCa9mPG~1rIE<+^-x`mu^_c`&(Kt{-VPNztwkHNChB-!Ig0b? zLF4Ks_WY0Q9NEfpZ>VQ zOCjRc`J6(9LJnL16>tbN{1R|mJ~3@St6S&R{r2TQRM&Mx-D+Cf+}V=N>JoNK`fS}OcNO!c8GJCHARjd0ss5u#9r^B94AB1>Hkz$ z=YD?ldclp16qi32b)9~FEprduYtvB2&fd{-!Eb6*A7EP9x~;1<-zzzfZO`L3>N`F% zY*I5=SaXDRwvdac&1ao+%@aSo;BI^B7jQ)?X~FMXF~LjM|IYcQY4KUF_iCB`x)~0S zU8V|!SbTEhI&^o%o3@SfR(?3yskEW}#I@X)L6fvy^yaJC+Ovx)S4vf%J>uh>GPSQI zuy*Q6L+L{jk*gYdR^9aBTYhua#3LT>kC?XpDG&%cHX~jCkh;qY5?;C4QpM3o^OibUM1M={seo4^^$)C70mnEfBUU>6yZrDxO0*=M|%uED&HiP{g^x zh_k~XM69UK!TCm>XG3N0r#_{nT$fif#j@miau>3;DQx&zdX0NVYr{)cfsB`|$}1aI zoOV2_@WXPJgeOuIP`E&CL`Mtq^!vDPU; z6*^sS1XVK(8ge(?GCd%kwP{!B{QR($OYZJg%ktiyZ*VJ{q}1x6GOFmob8tHhl-y}YES-|-cajle)^H=-91?|Zz)Hc z+&=kg7kktCe>d2_b@!~C30I>W`{!(Bx+pm1H`__w^ca(c zQQ|XrdidE`->!;@+gQGlkRKuuN@UC_$}XdI>5`~|I%{{SW-IPCZ9`~5yk(f zbk)Joj^5{oI^TT%Y%+CU`}XCnT3ja=od}L}{u&S@vf8b9=~fo*?C`dgq1!WfU+v^u zBA+v33rnQC)atoK&yJkD*yE*^b#+%A$Nhs7f^NCqHpsZJ>szbyh9e&m%x~$2?OOQW z-&OG1f-|Q)zL+kZ7klTxyZvR4zw|}&%-gbGD@ye-*Y9M9X@|>N&YsN^TV%0hWABzj zEU|`L%$HqjQ*B+?V{~z`kJm$u`F>&hL<tC;QN%bt|e&FebKQqCO^fzkmUNBHv6j^B)q-0_^E#1aZvc&!#2eNH!a1h{hs^eW@qSa{A?qmKqPEb@W-Vi8*TKRRQ9h-0CUdy6nz>b& zZ5}>6GM7m~+tVuW#3q}K%f21I#HqpO6MJC7qgOJ#&tkvcYMotZ{N>qi!+Ea^xBi=Q zv+t%&lE1R&>W>Q3_-&k053l`~{OsaX-jv!%+s9Lrf?gbX9?beux;eEw%xvNHt+I;y z-70&`-nj6dJ<53KrNZ9;M+1i=rcE+g;euisr^UbbZU{)ax%Z)O>iomOi)?cq3Q4$j zynmxMJ8ttQ=fX(ejlwIxy?V~JSw@omVcX8WWqZOLGo`1VS)#Em)U#((Wa)jan-$G& z&rYg6_M37xXGLV|f+bp_*TgUMbLd>FNC*rUycFPftL2Q~s$f5Ele0b_KCg3qlf(FS z)tR-|za?+#{CxDa#jT|$mwVrT@L;*csi{nvrSBKV$WQRoWp$OG?)E8a~ zCsqjZo_XPKp_JPqsd7KLJtxTbu=CzG9uF68d6p2xS*oD9*528;;?niCho@cKR(CN^ z{GRi>gkGB-(~oijs~@gR-n-+@x@K|N6-M4kKUm!^$jud>sZy+~aN(-b$b;E?9}_Z^J7M6mC%I2lAeqZ8~b=D=HK50}h?fR&%ytcwhs)vk~A)wjKw_odR^Val|FH)p!cR_kP~pMN*jbWQrD zinH;Dce-t!I@3hsaQ)8a6$dAN+O(=w^WO-E~Jga&}GZ_m%%6 zadO$Vyu_I4T%7*lJCaI!E?@0UDhe_+|JA82;H{cv`@5k3)Fi8UXH#A--@c+@`&xHB zXL-Z79Ji;auR3%5!Q4ah%hRRO7aBOMITPkG>ucBRDd|P8Bs~qUzkXG6=C#Va)#*Z_ zt#h}xhZX;gJQZ~QILrAL#|rPXU0M>G|8l$Ar^2Hg)sgG$Pkegla(Klwed9S(c{lSM zz5Y~Mr;_LFu6t#=y1`ef*1i<3usZlEe)GK9KR&NJUhMdcWklhpU*lL>hf{Ey3AO|(ikD`r{p{By?!WDGh-az zPCqxxpbK`_zb!M)@Y!J`7vh)|{6n{tMSMrchSDRSw?qaDUE_b3e??aNrTE^zE7ejB zdhY((=XLgr#pV6VKPTGQ^k}y}zp|&P!(slT5Lw$@6FPY;8TmU+qM1&d%{;qt)jD+! zzuLc=*QI&l4@Ig=T-z`~-)3E+%H-C_^pIuwtvovZ-S=m%Z#`i;SyJws?XH+`hwzT` z!s}klzFMYG*Svb}k8h9O{N5a2E@Usa@Y42)=M~r7JUV3skM+~U-8&lQ$Nl^D@#f;= z_4oGH{(X1z=HmZ1Pi}Sx4P5_wZT{i;$M@y`OTN8*eE0k9`H5m_>568b%r3k)@cvM6 z@$CoYrx0~+Qb1AVkD=_c7Uy#AHdx_b zv2Kkh2j}(c=}(q_yfZ26$=v;0pZ-6sSnC_G5NMlO5#e~V9#xM}1#aYFUp zSLO33Ty^&C?Pxijns#W`ti4&i@#$u-3{gYzfZ1S4gdeJ{JdSv(&g4We?R}a-adZs?nzJW zT`H@;pH-GnSbFcMs@2mo?=JR-Z{jJadcHM!$!*)J(y#W_l@_;DT@ugMS#}(iPQ4np zyj{_am%snsVW*zk_0=1?HyFM6Ti(7nVv69s*1z>~Pm-GWvi?`sWHoKM_3r=c1>&lO zA-`?^r?y5O_s;(QzpvQy@!5a(`P|o@Rho0Rer_9gEC1{EeXa9*8xz;r9GQRng?syg z=?k{DA3UfZCdqsLQdi5gJ5vt6{I>Le?H7L!V}H+Or4f6WSK01j^t$OY<-zCGQXQFM zxpNMM_dmV6_>)203L6)>D@uC=J)-w=XokAnI&|{J(L-$w_cqLX@lF5QeES2=i=7PW z{f-&bhdNx3 zcLeKOY~>4LN^NWZ;5l;zD|@zZwa&T2j}p9Y><~D`7IE>S&Lyt&gqdvjgbz(`XX6vP z))`;)K~3_D)U-EyLhmd*y<^3$GwTzbPwDZ^cy-m$^2dZjn;p!|4#eq)H~!?f!Z53n z^Yhj8{F&e99b(@a;qu{W`jocsog1gH=+$<)ubaXoSv~2$$)Sn)bq-P-$xTZ9_d|~P zuq!kyl$B+k&6?Mp((8YF`TVuXCl7z$k-K05-`CqKIO|wGNr{%~v`bsBI=C)m>Xakw zPHs;vnAS6u9y#kG+OW)A+wjva-NJt@Qg3(_PQ?`YI^D@=Y+z%n`s;U z8d_gn`xO0S&*udKPyd-;w$~MimHzc^!`r&R1#4|{5^sE+d#$XvyeIXu6gP6WsJ91O*3K1@e?rO-*MuzafM2Mbam<$ zOcb%^=kQlr>n3y9$FSkJ>+KhgSFT@Y^pa-S5U9!JW4m4Wa z-*ArjX3=zcX~9he`i z*I6Kw#-;Ih4NstQsbt4wHy!2$cMfe6u02rs=*461-QAMPzZ`pAKABnHH*V9(HFvOk z+{nlfS<1jauPPzBI`6Uc-P<2!5>NJiJKEloqabwf;Ka5a|J$7l7*07W^!$oPz~iuEP7*(dP>+1cyDW#U zvhv1O6QLI^0*j@8UuHa!u6*>y{2k3QEzxa^o9>8BesJD*?u2&HNh;+*ha(&BRt0!4 zRWmZ(K4hXXN$1G~raMojX8wD1>{o&;6DVxRw6?@sjHg4oc_$ zcBmI@uJD@tGUW1H-&f+hJ}J*A;}L0k>9Qx}&2wd;XVv>oiE=T{FkEhP{)@}Y{Y~My zF$It0>oRn18l1f?Wpu>#&%=vXzlXmsvtl=A)NY?^a!N<*jm#Rxj;4)q|U>(~AJaQEHs$~9ZA`>Td%@oLmNTyJm_ ze7nzULcZRk_(S^+aE8d*RqkuEKVIRo>9YRB90r@1bTQ7m*H&l$ER%d=GnMT^8O#esTwb?S;_=oYp6J7ef(EX^qwns zFFiT-`}O;VZB>%uMz0Pi zy7j4@Twwa{YM>BPPtUrb4F_+j+`KrOebH3w(0So9sl`nmuO?Nio!q>5Bg3kMd7b+s zx6Phut#9*FTw<&3(MKORic61Nz7Zfe^~vpH{6{{g{pByY(?YFoD|G>562@wt(3 zM3pCBg4M$EUVO_V?>|f2S+@i(&2Y{$YG?kD(J^ly`<0Mx7UqzZl7HAN8=>Avec^@w$hj zwq$RaQhf1;FiW3t)GPNhv&4F(mKTjvX@vA!|PGdg?1=tl@2vy($L+b8p) zo|4;6b-kWV-U{{}`{K52k5&>0(Rl2-;sVEkGm}kib;H;vZ`gF|jOFB0OzZ95ckwK6 ze($)nH0DA5)&0}-cGa!ve$%{V?LO{@a~L^ArZK8>J+pn9{q4j2?x>Qizbg_2^?EA2 zm{UH?RX${;FVEk={DD77v}+bm;AGXQFJj|s)q^!WLp4P8u>Q_ycZ5pd{fX9xTM`dXx*>$GfH1P zM7|1c*la%6Am#4jMQOh8mtVf*FSGUBgNYN~1vcG!8az?w_{JB@vjop(Oq}Jhp=@H5 zaEWut%VUXae@QMC=di z@jTT-8x(>KUmm&a{Vt2ADkh4o3>R>e0|u~e`{(yZYws& zYs_A}fY0Z7#4ocX=T9Y%^ZDZhC9h6hFZ=pYRp~tm({L7sWnNK2ac!O+(-i*lBphAL z#WLUX1>fTM=exG8c=PtLmgx*mGo7w^z2-cVE>};DI=>?#METkD)W8Jg`lRH*$sJn` zX{9KfeA;=oX~xsqS1Ja^2^M!44i(x@y1Gka3e)0yjXxZ7XML7XYyRmFx#MxPC{Kgt zU+>Skkr!80Y5rRGG)H~%?!^+1vvu@x1rI-4qiZQ3kQDzrj=S&-^SQI(J9efWSwFF+ z!R&`ilE%@{r>RN~@1q!2F03yKYuV~4D%9Cr;$z-CCAouLx3}j;yFv1Ow%pG<+c>i_ zKAto0N!hC+uu05vVok{1z~}cq-FO;OsW)T)i*4*1|NGvyPBW9);Bg{PNP?;7@>Zd2 zn@op5!3Q$$@}91J{*pIQC%R?r^-qdH-Z`B6FPRu*+)-qY@m;lubM<%2kY$dyCp;>( zW8cI1YyDI&&3|#s>8CzB{#Fx6StcC#ey4wcq`0l@n}7)uXUy|W+3`b;Eo6Fs&6^LV zqVdPJF21&?Mq|USzv~vxq9so~x0M^!QvP3+T>n|{cI#|QSlJJC7o z`6Hp4jdpibmI-}+vM1!lvzr@4?Cxy%=6cbYw?}AkqU&1zf2vnsv)>79%#l8_@*WGX z^9io?VKs5j7f*Qby*tCr!}TWOEtQk=mu7lo zomCJ?6TR&soOn)H{RA6hYE0-FcKZzv^LZH9r!%tD^t z?o;NuzwmR&ONIAqm-bo}#xy*xoEgZ|8y|7;Md*?{zYLbL79=I?$~wOAnR3MT6FbAy z6#kY;JKJBGE^sqBn>X!j`;9-_lvbQRbbqJMv1Hl%+x*%*S6l9@T=cm<`1-P!*F44I zwR?|jQ+q$JP`uRPvzUL|zYc~gQ))U`DoeJRIUlzcuNPc1Daf|)!bMRlp$mVeX|&Bz z{c`txj_F}vJA21u9nn9X72Pd!53%`)mO1=j_r0NcXUEONgNITr3&qkWw@=RwyYyg| zmP3#7ucyA+9uk|cPyNknwdRz6w&H6IyVG7X9+lc|*?g|d+J4`;jt4(@-Um#uJg;>8 z}hGw%b>KDEC(YQH?y{W9z0o3l=E%6M+ATqV9_3A?NO zj3>LhcJLLSn{p-UQii(So%HL{RuK+gbe_Fy<<1Nbz zd$LxpFNs)v<<~jM>;sRsFI#H8V4tqgx-|9^malKFJ{);WzceLtYRu2mwo1RHwkRB! zB|dXqR#>vRr-8FYc=F>NHrm448|1YLjXu3odD^3Y=4Y(*%=^M%GyRUg&^A5hJD`_p4(kt|Aa>$wn zJ30PM->*l`-LO*V#FZ5)8B5+&+xJ)MYj5W72@P5z9N_$UqGm$^`>{hAK3~4SS$@rR zqQv2fyY7$ASZinz_GqdUbEd{MUsCG)@)S_N}YU`24$Y+1iAa zff2`VPg~>bdoUvA^76nrFMeg@U$^_qU9v->eQWOJ8}Bao&69qu&0OsI-#$5di;v_> zy{%EZx34e0Z4wuKL~DZKSKDQ;3w+~LcuxAB|32;Tgbf+V=k;FRdnBcHtJQkd?u=_| z=E+COpwxCa(0S{rl(cFr{y;k=Nt|&aA06-Wv|L-^`MAhqdgGR|nt&BAR$a4> zJhY%t=Oy32_y3-L^b*^?`0w$r`=)$8d+Na|3+4ntvHzv(o*tQUq4G|_Cr4Q)~m|j%5?kig+U%6qyfoq1xnSxjM zT&@*ZKdG_!(zBdi!8He#2HyDdZE{++$B%?K;lMZNZzYsh8vd(%c%tF2kT;tG)7|?Q zCnd7Q%;l8|kx!ajwax6S*ypG>a#_z$vnqbSRQtM2&v3r%RWnmgRaW|> zFS#OF$@0wOdqb?+geQG6I_p_&ntRpvpXLnt(CFuxoGm?ef?I2BG+5OQ96AZA6^GF-<5swG~8vPk8E}H6sZTN8P=w4cQdm%u72nE zrmtFWGqqP;W>kOmr037TpkZ zxVJ2A^$*L!YS|~-eqGtz8rZUO*PJxbshRbBa$)zSdhc;v`*^yNpK+SftPOKZwuC)7 zzh7pn`Q4X%Jn_KksmG#JVs6c_pJgI5 zPorX?Uv=EWr#rtNT0YtO_MN4(!Y}RC|82W!PG?N@DX+;5ukvE#^pcG#W-dE5bw@`1 z<#g|lGoR#7%WTv6&viU2{GHI}Y39>s+nEdAvkUaniCe!;i%D52c*lM3>&5l6y7+rb zZ~6z6-B|uw|5OVDQ_-b92BGv#58p-f>*uch8$7wd<=x3w?+oAkl6n#9_R@R4AT@KaSnwnX5GVmd5S7h4R^}I%Mp%-@ETDo1XmO1s^JDtuM9v?y{TANPZ9d03> zBedA$fe1(Bx}x=0mDC*1RYlHVs4PreE~B>L{o=SK@i(d>XLx*7I;ALCwD*K>)Z9bd zf8rlZ+I#&c&&J?ByI&Otc8etO%#jORxlD`C@5RbFdAm4I?ri6_T=Hqvm9?$m?xkHx zL4OXg&zustGVtTUCLal_3wC$zY9D@NKfUIZ_pFA(vk|G!E*uWr-YtE_^L2%_Z|U>b z`(KHwxJ_bvJhNk&)UodBnOCc#bB}*?*JV=MHOq1DREJ+3YnAiZPuB-Dp3&40s97D} z`R8TB|MSuj|NboVcv#J2cDQne(%PU+*B39|yRVfcZR)Rr>&w?ZY`d0b#WtNS`ftTr zfmg|@OBuf(ynMNQ+JTzgAv;=Gu8AdV$lda??@Q~(W%F`X6Ye?{@kTfvQkbY4^z(q~ zQqLXx_W!C64gK{Jb9fy*Xbv7;x3DmW53iemhSEWzNT*zzm=H6(el^B(v&>P!ZR_=Gn|Q6PWAx_!5*_UW9i7s0?YjAg zkJh_w({B~4ZhQY;WO9@D-dgVZ!smy+Exvot=-l4Vw_ksITK)E=`tH4xx+>RhSL%Dc z_x7f{_bemUncc3w;gzM=bMxO~K8IhwQq*}bhpl*Pzj5z{d#m2=wm!V$VOY-p*xM6k zPI|WG|D8tBeY{gWF9_z(_uMd@Pp)XD#>byxw=#0)-mtsP`Ql!|-r9NBM4E2>i-^C! zp8Ky+-HJVT>~0o5+hS7m`*q%W<_X8MEv8xGsWA5J)7nCAl2#Wk&)wqlQK9(z zjaPQtxD1+Z)yeOl;!t<%Me1J@-mH=vc3s7n7Dfy9=+9{B{PmW9LwQfO;+b!sWqBUh z1cyE2i+QoH)$^c!`kQY@^Ym4X58g7e6HxN^l5$<)ETCoSee`_Af@p)5OjRG!GboN(DyP~7OL z^cxSRqfCmdUE^wx_djmKYVuleSBT%*JI12 z3%?%w{bT=j`zrQ-yS~4BRv!NT?(LcywG^%g&dG%mYQhQs_As*;JC-rI9(l8D(uzVJ zhdEapBO4Cvf4AqT{J!bzX9ZJ49&j+fCnTR&kn1 z>ZA1^6$`3ooNrcOF%ws~Zg+<9!So|bx@Lc~Yh2AGJ9DkGk0#S+ZiSuC;#wDVpJ7{a zT{Hhf^5HdHcbN2*(J8zf$=+!UBtopT1j6XCJ75R z%u}Ar!{;YgXM9LIyv|KVAns_6@ZIAYvVPX4(JR?B4@^z-`nOT9XO-vy?gbsnHnTVs zQVedlPvw`Jc#QMK)}?p)YLXmMf33)rdB>e<%vHeZE4S^M?FI>cvrc=_hzZ-P%-$U9 z;pY@nIv_P6M%RxuA|P@_?Uv+wlg!Sq5@48cSY?LbZT(ZXHIoeAZS zSwFl!=bd8OSar(c_=2Cy9quI@sESx5dg{R;rz4X8w@h}BQ@?V+j_VKK%2;*3%z4W$ zd%9%mbZpLIoX5bJ5Pxt>ivO_{f2X{wluGYnxEI|}cznU%znxx754&>DCIkMl}mctvnPLdbSddSxSwHAX#Fx&D(YrokZ1LZ2uA=70&Q$B1W~rH>xA|lEEnVeZt|qIy7F_n7*mLApW~6PI z`RWxN(O2FI`~S08!2TlM&*1f@hI?w?H=Rq?3X)BBb-A49>%Dv@zee9C?Zb0cOPjvy zpWQI`{PloY3#3(izesrmytuUC{_X4^3!Paag`cObp&54Doua%+i(5k@4eO1 zxf~TiIr0fhj}%P$Z(`aKuk5%rBW@9oZ|FD3=e89shcyb2kR;t2RCx=MnknhlPJ!{jy^Z3}b(tm2Ua7@4;F}=SfRtp6ec9 zXfwLcbM?vARte?l52Oz)2^TBcrKie2Ke6s;!#@X}$yNr+yEOYf>^Q!9ue$Z<$=2D9 zP9l|z+MJs@|9JgVE@KX>eZDJf-t1R9_S{wa!RpVYr#V}4Ue2L2*Xunj70vrYi+G|> zh+S@6$;j@#`>*%?oDP-WQ_N1C^_wOx(YO1-tUW6<^so6pbv0&f@=0CRz-Vydyh^Fb zWsBw|M`~Yh``hsUCeLG5ou#%v?h9D9OTYd9-{ss~)uNEaY(A4i9=5iM_3#Rru$I1FXk9H*aR)yWQBy;BuyJk!9cu z58-KNmL+VLf6&)p_U!5mH#z$m0u$A~dCn<#q4;9wB$j<07vmRAHJl{Q^x|65*A*$J zKRBF?mO7_axvkJBs&w*CA+ffFGjNL5=3#vbR%RVr7t_2PP_l$@@4e&;Tc+o#3u z#-?Smss$GUcVe>viy6@OFyM+nn;Hd(R4DF@kI%r<>kIVt5rJ{#-i zo-d8|e3wl6rG@1S1ihrW#KcZsIr2EOP^si&n`TW!LXqbkyMSu3XK$A$yoq3a#CwKq zUX#4FYm(?^pVce2+^|cfa(Me0Enpp>&SAL_%{&2FU+?Bv&LDVW%{BhOKl-b*=3Mh<2o*4Po3^1S&%)}< z`&(suI?b5-FBT^`Pnv)BM3Kg1E}bAt^Qrt%k#5H`*L{BbbMln8%U4f!=@abh44Z3t z@#Bi6D?b}+D?8mW(ED`b<;J{E|F)j$7Zvb-BN)p0X#Gz{=Z_m+y)2cw&!EAcoT3%QylavF8pr9P{4xw$EX!?8die|` zc)8@5c6bNNF->n;&m|JB!JDsGyY^tKjplm!WpzuO?yubT&+gs+O-vgZ_is`2TEu42 zCfcx|dFG>rhw~QA*&WeT&40V0WY!CZW!Lpj^-urU?schsuf^n5^EZk(E9Pg+NbE{~ zrna%~FmvFBH8M2;%E>i4`&B1fnsFGg73`Uj+jM2cj)fb?Zag&W>ER&1Z9bdluQvuD?Yaz>=Wp+>%}9PFbe79L?b)T0?C?)_wj?xjr&W|MNS6|wbu~_)^@nyHr{458 zmv$`q^4Rfdn)0fwId1IB@11bi5MgZmBF!%4k}&hHd?c_H*aO?c^SKvCe5+E%yFOUPI5N%MUgmZ#Z)I zL(;1lo`$x6Dt?(9&Izxa_?~ikc|P+uk|@rus_OiaJ2_Z`Yb9sg%Dx5F<;w#O{7DpY zUwQnS#?p(iTusxaCU70%KGr+?bnf}tQr*j+mMlK8a6Pm7QMT~BKShFX{Gv~V>X&h{ z7N3+m#+JUxC0p^)xzEeKuro%=9Q3xc4C0nGKC`Wod5y7H&nX2-rSDGKO85PJ7w>FH z3Ku&(t?DWBq}(@r;Zv0UtaM1YWz3SclH2NR&z%Rq8XoU`|Fw-pdIGzxxyLm=mxM~b zKl^$c?4u03Mc6lAZ!`VQ^E~fpm#bJPtCZiiWk1u@65JQ=$n%bu=U{(+s`N}!$3^l!My2h$7=FWyqy0fU zyZ%z{ovjZPw;NP=d<~RTnRLW@i$m0P2|2!sDdMlK4`!QaX;n7vkUp$kY4K?D(uqqi zpZ%@4|5d?}ht*-R>VNzS7A|v7IS?-tkw4|{(yJ4~r@dMETK8ghM&76CzS?#Y(%*LQ zO6~EUM%0m68@66LwZl29cPHoGMISWIb$>Ri&`sfwTkpTzgHho$6KmJIKer|PE}Klv z{m8R|d(^K0QUucZA&uGmp;TAQnagEX@lDR z*P{Qp_RdWekxV!Ls?FxnH;?PYKJkd`EN+$CeRFb;O|5-g`Fv_dLR_hylkT4qH_00Q zNw#7QuNIiyJ?rS4$9HvW!-u2@-L^jd=C6mcN>~3>3hH_OIo5vS44t=ojx#v!Jpbsr z`&GVcm0OA2h3gOc8fam-HY7bzZB{(s-Jx`o4suV%xveNVRtF zemTC=TN(c)t-Cz&@Fbo1CYCEPJD00PUVCP9dY6pH>VoZQNzAD>GiE*7;L9_M&7*ME z6aEvLhVPyjED-69xDt7w%4qug8H-a}PaZiu=RNs8XXo+hpQ<-> z?f+iw(O9b~keL>suNm=1&w6X+k-H0jx9sH746QeJzj9;4d3XKiGeovu*()l(LBC&F zW=7dHe_`H-f0QmN&WXA%uJPcDBunF!@Wd73d+gstP1*X>a{4;IZ6{7me6=+7>V*d} zr8k>b{a!wE-_41?m0sno?0>}TXK!krKk<;|(UzG~ip|{n<#cAU{km-ve}2O9KCd%R z7nxlyUZIsBraRa9(w8azc3rbR*Bn?gFYVW(%q6@NB-bpvb*N!9o{h_n{^e@Qd z*sv$1x~|vB4o%;yu72~j*DTl2xGDV`6Ey5%3e|!GkITmGZJIWB?v3Toj~Q}J4cIs5 z$gG{AKM$$Q+no|pGSB27SM#a_`RiY8<&;(|K4iY-Siv5{+>l4pv_5_{baP%P&8#V= zv%;nJ)YZ(^9iN-|*<-erDEsbv(V4~}?fhg#hsX1UE00CpscXo360uNl<#yY$3tvtw zd_CvJmUZhLoR?2qKeg@3o|hWyDl$7aKEHFxjVVyI_V!idW6TERQ0>s}P&G|{Ioeiz%QJX$u(wc^yl35jM} zWjg2QoONKkevJ2Ry7lzzw3J!QyAz+EOa0sOsf$&xcYXi*f82A=E|SI^rUMVYfd=GE zER9VO!*sBo()S564fZ zggov|RXrW??`z7nnW1y{8f&j@R$%I_-o1MBs!u;YonG@VPhD)M@Q?kU-e12TSMz7* zecRgFiR<1ydFTK3`seQVdMQ8o1K-`NE#l<&SXo}!>1Vll_n&7@)7a|%4qXA0sw+)wSDr(d;wd%LpE)VQX*^@SXXf>yWw z^4`g42{3yTFWZ+Dc*}cxeVs*?`1A)Reus2!y;|^H{y-AT$~o!tiY~p`e>{4rXy4ow zO`=>*@AUrH6#iVT|9yIU!{VO|&9YMqyT6zHf6I6*i0?@i)1gED%6I++-d}QE;kr^! zVA20&x}R5nDOYtluzX5jcgy_y%^Qwc=zl+dYwp+cr!IV~pBeXR?d|%z`u}#nhli9cD zpL1XL$%KCB z7TzVLxF%_vI{UkheGPlQ$$pbn4HUHPQSa{$KDcsK$2}EI(^UnbFV`wwpS*j~zD4U! zymT0{6>n@-Caz?0G`PQcw3d}E>zyFr!<9gI}VG`GwnYHmd*L=z}6L3#>^x|}3 zQ0zZ<+hct5WFAlJ?D}yJ6kmS)ym@1P!MntbY%YF7W^+^0V8-h6qMwAkoP^12SG&ixWc zl77wpwO-CTBBiA`SZc|lxW8=bJXvzKJ3T^vTh6NMF#9Q>d(iKRnA^n-yWL(+ZCzg2 z<+AI3W@gW;=+e`@M}t!yGrZi!X5u!>mEzld!Q?iQAWVI z>6y0?=b~BpVbN-VP2G+wWHTE#a#b1SAQG(Pa$FD%>5RJ*0_z@iPJ z6Es)s_^Tc9-pLOiD z(uAA)5*O9|Y>htl+x!>DtEm^Ir+u0?<58geOT+Zce166W{3+9Q8{Mu>5ZlW1MyqX& zRDJ%c!p)z=Sos^SU%dDsU~PcvDTxbnTOz4`3Llx^WmYwSuJ+Y?DM~RtfX64O?<`>Wp}2L;ZDmR zmB@W^cjkZGx7?C-(hiYg;aUC``|KEY@tLul*ZA(X0qC}YJKeY43%|}zmgw?-m*9{Q`oVi!lxltHPW?9EQk9H+k}gZ4|z5p zXZSs7XFu`F!OkH`L$cdZ_Sd@C7o?AMf7C3!fArAdV~vU5HvA8D|JOAmh&^$q%9ZcG zPt7{$Rp6ZU#ed;PmJ{g>x7?oYaJlhSBx0$Egph$9>oz|R_n?FrJ#IS@A4VIAC46SH zN~avP_#iVmwfW80P6LCed7Wh^JubL#bbYJqRq2(}*rK)j_5{&iOlJJb|5oz<+|oJa zjh|bKkyN-Z@9Z+Ki`x_4`LZ7|^`FueUSj*o#3@exubaq@&3=!abD8G+Q#~N?c*PX~ zhx5U&+-@B33UY0|Yvhy}aDBo*-Cep0O|vwTDvx!^3WWx(Ub97`H4mCt`E|Pj*P?>w_|;+WpL5q^he-y*@qo^k{SU`?7+=i-I^`a@DHySFisq`{(nA@4Mq;Y$|sA&ebEd# zwTgvdh4%|q?NaI8tWjD5Cl0*&{UT}myCYFIFCUBjntpNyLpPuB>p7XdqFz#r3{NA~ zq;hLgmnJey+owEp{tUj%cfxZ_Cg!Evx!=AnR>D(fYK;Uzp!;L%h5Bx za?WUun{CteYL|w^K2HnH9!ae+KlMNP%vNuf^9%2(e+m;_-6C@2qZd!kK>#FNw59ID} zi3wkQ_5S7G!s?oSlf|l;iRJYz?mN?Twy#fX7YJXyaqS#4QGXHx!!Zgw68oFrMG+O zq#cr;6XtwWI(T5;Z`*~c5|uLwre-SK>nj!NyvDF)#`90Np9N1?7qB7TC^1P{mxagm zM--ookiNh18Ra`uG=6zzttwvKWoRVem_PNe#imbTN@}iryp7&394w-W)MuA}I?K1i zEa>2dLM4wW3QH$nwUfHQ%zwH-C_b}fZ`{Sb{~s`99AjSeSbkOao41x?6Rus`z~id- zp<-orwCjZ&U&eIp33Ha1{o8SNn*XH}LeFljS2?>wu9#zmecTIP+bKfpX63(~d^X$E zkt3{lce>h1iIp4pcF+EBk1eb+{+^`3%mXz~;-b5m945UmIlp7O$=2C_y5%li@MXH; zlB#w>sMg|I#FMi2Dd!a5r>j42We>ij?)_k^tpd-n5?_vrW%F4J^(UQj^XuTSZfde+ zF4fRg6t?C6o8Z1+OS(yvhspLQ2BKDzZY{cW@qff?<-lB5CH^ZF^OHIACtTWjVX^cc zNt@FF9CKbLwI=%iE&McxB`D$Aj$^-g*PkoxJgf2S_@p1Z%$a+u-<%Cl(@Sg0+S z2skA@Ty|&8;RCUW(GzlXxBQpMpSL2|;kCij!cMN-Cv(H@DD5nIzr(}3Z=T$h7oW=7 zMCNuLobdcy(>BlYtGfcs1DEJ~Z+`B{altBS=Pl!n=eJyrvM~MfNu@GnOZkhl7Dx9N zh1#+4JkvRseEmbn4rynrFgfPS*E%d3T&Bb|95eUOX+A5vTk8AeUApWOS6ypNdU|W) z>-GiqrZ1M9S~0&i(5ugX->Y+mKi1XmQQdkkV~*CJgT_MDSuwx$xj1*OPqa|TdwzUg zo1??L1O^W?@Z&Rqp+k=+BjB`qJmU@0N zT5BR}mJlejpi461AiuzYMY`EySMS|g^eJiHw;4^gM^7GMoh-b_(^h;*YmCsI&z!6m zLLUoN@~>ZH`%kFMt77uJOA&3Mg8eZboJ_a>HZvPJF!ellkICX>>t;IKdrox&zu(Q3 z*BpfRltpB(XWq-^*u!=3$G?F6$L2X)urv^T>195{Wcz|^hT54^Zl$sA6|&pncmBYW zQ{Pu8*1rAX{Zi^<;hE;w^RK@R7X4fm5fNN%JSUi0EmyfTe($GQ!F}z|UK*VC7X5KV z%KGSWej$Z(3HK&1dAFw{;)LA1*2L76QtIm`KfA?ZdJ*auY zU;4E5{bh=is!phHJ}nj95piz2fP+SEu}X15ta+09%`aZIY7J*MCg!ZNTJNg$j^9sp zE~n(8$NhU399Z&A>BCH;=-S%3{`Zaun0w8Ot=V=qag%ILu6)xoU&Ysd%PBi)^6tJbddCI#Z z8lhW_P4@Mw#%z7~b))Cp+T`+6y~gY3x5!PN*B3Uguxihm(%>J272VV(XOmjOdb#P7l>VwC>9beS0nSaB>ywkyUed@|JZY8-}byb!m9q!6i z-s_V5|L_BiS4aD^wiPT|*wpIxSJyu}Iyd-L^_DlYItwr6@z}1cdw<>`e{r1jtMxzk zU3Z`JUNz3@?R4Q}!3O^S;X6Zv&q?evIap-6{`hBY_ag_(oO4Vqm;8%+`i|?E`l?En z$F56m`Eqk!3}f)$yGK^?u4MYMvO6=AP5qWk4q+CIpC51NlI+b>f1$x__w$r_^ZuW; zJyZAPH`~F04Nra;h_n1ovOWD*>{5QxC&rKq%zLx%tm?U0uzSfL6Em?52eujo1Y0{; z-rM-l<@M*U5nUhmD1F=`vh!=GWpSz+Lok1zU{@#4g}z5i9`_e$t9+U)y59JJ?$TqA zCo2Uw+$sO)^6qeR`^>{q(o$xR@@KU!kUe>Vx#`-^9jw1LGxvS?w`#>^<%1g&BM&UB z-2C64+x~To<^0Ii-KPY1>X<#s4Bc0r;3U?d)jIRs>p8&%C)rQ#xGVSBq^!{Y+lo;C zDE@}rYih3>k5sz|-W2$%)}v8d_U5LhSz-057mAh3=G~kkovyH3W^aX$%Bs?|3mi>) znWY=#_>?xz?EMp7vU=6CD}9U=MOItvZXR3gBvG|H>EH7(Zm~-O+#0g;x0SHFbibE7 zs9*l3k%6^DU9fF)RciMSpRKMpe*NE4bnRMU>*8axtk-^Cd*|=sk7;Ot|c?FHrKHs}-F#o~4xmOO$wj~{3^Dxmsa>c!sZ*RoASPHg+AFz4+_DSpG`#cnfx&%U1Oxo_g?t-p>uJZ!A1{haUX?DToP;pMBKs;d)=79G$w3VAYHsE2u%-cJt+Kh<@8-Ti%&zDDs(4Y7K2 zW>?m}Upf<{UY@Uemhge)>28OGKYBQ&@@g)v28i# zZcuh;`+4OS&#A|6{oZA0YZ%(YUF#mVbmH6ZH{bF*IPl9m?oK=MvTM?BN2iQbJ^qf> zh8|Z|y#BJ!Y74*J+>8hN%hPs>o?QHRmW$!O$KS6VQhT_5t^4A|CjX`!UFIBgrrqLN zX3TlDw@AmU97-*ladQ9u>J#&|KMBubw-=GA z=SV*N`PyfH`}xnWvdyk*^DI1B`_O5x(n%9r<>Tt%~D%@^kTq-&gE%KN;RBVEB=o z{Puxp9{a(g+?t;)?I-r#KXmG6iIC;le~ww{L6@vqc1<|a+VFC6>x@L9#D@KA4%(SN zarmsb^UJ}|^`{>4b1z$3`2I4l(S-Jde8z_!Q}-`PE_9XoSzP__^tU(MSJ)VC2tKU; z{j;>XCFak+hTg|Y62C6omI;czw9x9sSw_QU9%6mxA6Tx`VXeFQTOtr}~7p1%D5*tDQ>-^KH`G+p!0fABE= z{ko$mO&5xO-<~^fipZ&){YUS&d@uanes}Ba77n|d`Ijc&zr5W3&AP3Zf(_ENFYi$N z@pjAZZ*t4B-+bfT7UbrUy?uW+^M-wOH#Ds!)xUoGej{$ygD>CAt*tq==iK?Xa%^2{NaA}{Wt&IzWUwY?1uO@e_2n?X$j#%%lKj|`|bT- zWaaK&d!OZo$#UlV`76()@boBuiu+&5{(o)rp{v^`Pb>R9{TJu#pLe2UAFJ$Z+p4y3 zQ{->mya}b3PP~#a@AqRr-ymuI?dLDa%qhD)Kk>iQ7N>ms!_8vfI0FjzH`i`< z(%f6Szq#|si=JEWq8C5^^7r-@E|#wZ&Ux(Z)WC~%%(lu8~$Uj zS>Y#xjBPH~=jY$qu5N#+J^yyxohv72ep+($=c8ha_^Neh&lYsgo2r&y#-;wUuyuhw ztF(N$&T)1gi}{?HscR-U%{Y2!(O&aCfq#G5ntgxJDmJer{_2wlzsp}l9Xh5lCE4~) zAb(C!ZTf~YN-NBMPPb;iCy^9!e2Ji9O1h2YO8bARExYcy;s+t)&?6L6uGG}SX9QOL6;*E>^#I@t^Jzx?~`(VE~u9AoMoU^-)6Q9A} zkE=?~`ASIq77IV&cyCek6pdQv5B&>o{+P(kJEx1aHYlAdY|^fV{)Qe!=^Z+n*E?k& zK3U#eeARI8w*IdlUl}bgFP(SVV#+-3wx=Jvm-tLwwISN);DrAZ{P$+<*A?~1;9{Bk z*^nz`#q|0^Ea9yBRw9>L#CrE!^j*zz_HLVE-&UoHu;q#Ic8_mdRr6Vt%pkV2!Ep=A zy3Vfkuhl2qUa+n8+1yDV*Q{3jAboXa-IbK*g8K>>8N%ZWPT84BuGm*l75@Au(*dnj zZ@7=Y?%Gy*rZ(@S^$Z7F%ViJx$_-mP%vMWeUlp8Pb7);mQ9#;aKXVR7dJ=#i3l~G9{OKhSvcvW!;96TQ(ZUZhOA8S4PrdzvObtmZKGR8 zLAvXSu=1~`t<-mA&C7kkwq)yy)y4j@WjmR}J$7v4+wt1@o2tx}6R&*Ir`YO0l`x7k=yg z&L44Uy*&4xdcNPeaLQ`F?7G9BRQxM-=arU9TJfH!N;y(*taUxuai*!&(tV|DcfzJ7 z{;cHGZ+P)N^i{OMDz4(xjB^2P@pm3P%0Ba;Ui0w!NQd9ECJ8*X*Lh$$X+!JA$tDk9 zzKH!A^YG}>J_*0~uXN@!H5zDs)(D(2=Wx`s0389d*vnh1)=XG6`@g*FGS0saXS^9t zY@9f)&p>a*zPK0KYxI|PEsR{575Mj6*_76&k1bLsF|4TSzqLnBBc-I1rPV;JZSFZ~ znVbB|uNNhy|E{_v7+1`=LVW$k2Rp>Iq~~9}S{cXOy}-M->7q(->H6p&3!*+aeMy{? zDK6n8e!}g!@!`!y+or0BvM0S}`JeEHEAdp*vX+V4>U}?5-kQU7@H*!~sn#&RXuhj? zH(mTL6g+Q8_dR?w;b^Ooq;!J+ehq=mZJY0Hou!*;QN63}_a`>-^NDQ6yyezf5*r#0 z9y+1ir*`pv)~qFe15bJF_H?f|Obyj*>EZi5W6q-WE5H6VaJg!?);iT}>gU~;+`Ren z-6p;czq4|3ZP*Wsea^>rJV;gUwdH>G_SA{Z$^L2Q8lJDpuKN2TJL+nt-}_fK%L`9) z9hNJd`N2v@)RbwSb4DHW`$^MR{>z^tsna4_SL+cmG2!HdzAV?|wXR01vL-J%vtZe& z8_J&yPdP>0{Ij7<`#S5s31zEQZA7Q7bPqnUf78ClxcxiZcTs*V*ZCEv=Q7U;^-X`e zblof7`$-cR1(>aTUY?w4@@s#B;+BJ#&Su{*&!2L1wa`n}W{HnEEbHGyH>MZ;SQum` zKUsSQLk@Gj_(HSrx10aB#4?z*-@h@Nr~Y*A7`FjvwZip7otw=B9%{UYt?>doZ)ZKNv<)unkG6y@S)?= zwa!ywej9k!xUwklSI>T-yZ@@<&nMruY&(B@LjLVrQ}6W_EG=K|Yve3Z@H6Dus*v2;aAnhMi7&jL)IT0N!!<{_V$P9Ctxx2WRycU(*P5<~ zf3wNC)A5wh$7efzr)bt`Sl`qLo!$4md+%~yCUZ93*HfnO)<3vtBDn3K$&0@gorS4B zKF=?duD1U)b#+_cxA}Kk3fwvli3#1XWV`mn%-wE%#FNFP(tbAiOICU6&yr5p?s4Oi z{gHL=jC$k!;MFX_7veIGZ4J3OLA=F+O|R#*0^5{{f0x(Ht4y_fJHfYQg3Rvs7e6Wo ztdLr7sQZZfOaK$xWb-cyxndT|IvhOxuT=N;sI1+#<}b(Z>L@{}Pt2zrPH4C!tVq!I z+WoU@mhth_({ny7Ej-m?vT4O)@fg5I zu%3-I&%{O*?wZf*$H?^g?uyU;KWqyUCUDD~7uXrEV~}^?d2GWB zo|9Res!l(6ZX^XbzX@h*asA)1&n~2bdCkM=v-@m3yr-X(aQf$*(j(nF*ZP6k!X4=b z3m(i6Q<)I;aJuN5?0y%CX%pG5Z#(0$?2>w2zVDi8FIbbSrrg+^x?)OLxJ$8fz!Xb? zS#>*0r#5ZiJ#PJceU^Z9noQ+P{zQ&KrL#MZFLF;*yjdl9BX5VRNs!yxgzY(Pr(2ij zuIMcJt6Ony#ssyf?);ppe@4%m6efNAd_uSAS=2}0KNq$wP_UG&?7d!9^TkHsLG+T| zMVDr~9iEW4q5Z-1=x&KrpMCO$W@)7xPM_*m+}H8t$HV9x=10F6H!QyFp8JD2pZ(3I z^O-v)r=9W5IWOk5g?r}MJhZ)?HceCmnt6H-zZkwsaa=cq@U67IA z-2&FS>-*9Y^nUrw60LH(*UXXa@??Fr{-alCT*s~i~n08L) z*vfj#ubS7ipjk&^@(ojt$ou!CS2QVBKbu>A&iIDlsy2uBDXWedHAt06ik!bNL;AYg zClkAMGp{?J^tQhrJZbu!MXH~7Y`S!4(JRdutL3Ib4)RZQmYW(S_-2_hHGTdq(H?*K zjl}IcPo!F8TKBdK#VkG|vL(v5p!di*Hj_^QZL`(Xuj)i8a_pJuuAS>3y{yOHHbE&m z#&6+=B{PpZs2L^V&~#65HnM2PXzum`=MJ!Tr@h_2_&R7JV6(!h=t^jD%Kj-d=k6 zym7Z@@MU*h9sZQVIlrIRZ1>6DsIES=c_}hK~jn( zH3v>j<~gXZ;dJrP{=AK=r1xz(>3H(2@+F(U{*$ui{ZE$r#gKiSi}%-*?Z%lAg*6I4 zWz1J?d2@D?U*lq-Msq#8eJqDfUcBuPb@zI<%*VKBeZBFDL}FYtL=a;W@XdJ;d(0Qa_v2$J*mP8y0>omGs)Joif{_dfVZr z{Tn9EzrE?)=di0&d3N4jnw#QsYJ=0XGMngbyQ=V;=9%8RCY!8cJZC&TZu0)q;jAsQWgQoIUV2^GH;Ieo`&!f6hDYI{?%bfRDe8WE!2{qT=`NtsNbgd&+%V)Ofn(GGJ z9h{vQcyEik>`Iuhsr>BHRDJ&Ju-Y`E*$Mli_Qc3N-|%H8_vD#Qyxl?zT> z4S(Cl(i9Z)Ff&YC-20Y#^D~|!au0YWb1M|h`DKvt(6Q+l=c~njTwT}fUoJ_QbMESw zRJp^&ZdbRPmArBHd~36L|7^kFb1tvm&f9qO@MrgTi+=X6bzFDvpI4ThV5#1H4&epC zXYVk6bcogKEA!ge!^)oa=Z~F7k2ZUGrHbP!M*BUPxoOWY-TZX;_$ANG9i|(Mi)7PW ze826QDsWmjUgGqF+XXIX=Aa3$Np|wgKkKgZt?3Pr%7irJNC*?3H!cNO5v}?#Fq-Q@*cJ_ ze?Nar=5)aM7iM>VU9Vs-e#7k?YxSu`>+hbqs*4ur{i(VWowfP$g|_gkQ(nE(`*Jd3 zzTuMnnvc}9KfPXkAw?9^*yAsmvaR?`PCvTvCZg#4!yT)5 zUyGhp`NsZT@cjN+)4I-VT+KFZN|tHo*=6m0{A>o6t!(RJzbrVe^26FiSkPtr&%-i1 z*J~b`;IJ*s*Nb!FhSyJ**gO@rJmDj&+*BPCl99&XHA_*T{HQ2+>x`;m)}11nQ8@#`LVZumh1_LtlIplKfIouV?)3N%;7rl zARK78&cxEh7(QHQhUN54GtiddAbq#YoRZWc1%0=i#FA8()a3k>R69Ga;*z4 Xe5 zIeTNGC(9n4`0aB`a{b}T&z90Yt6#@`eZt_A@RRMt;|Ga*`7d#JMqKJ)VDA2Y{{8gQ zm#1Exo2PtoF|X2t3ztKuPMtbkU;pZT*=L@zX}^~L`~K_e(PsCDAO5s=|M{|juRf-3 z@17s;oUZ<#`TBOd|2hK)&0>$>Pq%I#zPgz^l)a*u49T^e%&%fP%*2n*Cw2-z) z?(Gcz@Zjy$;19;4*N!@@kGr-%_Ep38^w_waZ*}V1d@bxBe*ZW>;&4=dYkY%*^xd4F zv+bX?Uz_##bDf2L$9=uTH%m8GXq^AFgMWc|?1BF+kI(l^zptnMzw7UzIfX@vvhy1z zR(*F6Hg>UM8i%L)z5BuZ&+hECACFCCyN(6^@Uq@}^Z%Xt+RO1ZUfE51 z8ka~fvh+2~*l^nK+L^e`ny35b`o6jOz4Ca~yvI%kPu~A(iFN6}n0-%W>79>fvrbLO zS$y{8iRW*&I9ul!O%7`8_MX3Q?YvtBZ+&KmG%q=>E+qVx`Ch(I$d6TqZF_&%7P57- zowjf;v6vg$u(xV+&;ED(`LiR!^j`W2z3tfe@aHGB*~ONxb*@gm=N-zri~DY_V(`q? z%__UiUw_^n<@j&Q%s)2ldJJ29MVE_g)i`;?FJp>!(}KyKxydSb*0X5tvrV*O-7ERz z@1zqRQZXyu7({&Fm1|nEKu5Uslya&_^25ogKJgv7kG^_74li&$F}3}rfiI`wuKE0( zy9tzi&XCCiKEO?wAB`vdUR&U+G)b5DP%kwhwwz=`w zTkW(s`-Er7-x%>sK7(o7JdM{bw$(i^;gRN_Ts2{5qUpqqX{LW8m!zkZUiPfIxNJe! zRp;Kb~!w`eTmj#q_uC4IQboFVC zi_Vo5wDUig9W|$qeV<0;CCMWDie{b5pNwCpw6K@uwB>(Z6m{`qn$v*O6jQRK+GmUHgntmJTNbz2ux8jt zzc^|Xn7(M%q~e*Kw+=m7TC(HU<)c^Yg}y&%59Ts!s=cwd^Mgp4cSv?q5se z9L^pP`j9l4z233o==>8Z6XtUz>5^~ zcpiB;bnmev5Aqe<`}bPym{4fw?Qz&Ni090M{FedEoCQ^rF1Jr|ot*U8!BL@NgT-MM zu6a6k(k_YDZ?V3+)cv8V;w+PW&-caa-$ik+%)OIvEdF@qtc5E5FW(z$@)-9l=Fi#o zQo732&r1IHrV#TBDqG}UFFT?8dNvcovy12MhHP4sc58c?iT2qvy-tshDKf_DHaF6L zELit`u3+u={FL1jzKgLi?=#A~es_KS?it+MxW9eaw)@!ZQ!)o!`23C7f~y*MkFJeQ z<1nw=+SFB3=gO}RISPMtPH48eGWL_9u4dcnVDk6VBg8#)}8AdFFa-U zV2;bWaod9b-@e?tMFA&GN*3|wvvphM`u_7| zZR`=vzV_M4`;`@+4KFReoXjbs?;JAG_%*^Y0ANn-I6ncd3X@{`r zR3Yn%RWFVnY8Ct1vUdN{c-sxPj~vUklCXE#t6G=Mq?|X^F43cBbLSxV8VZVa=E&3S3~9biSu7vak=|yXOC3o z>LY>~&1?6q-pzbX;7aVKJfE+-e5?F!hi=&OXT^yR{u8*))lZx`yFfHY_Y_a|yT@E9 zh37A`{D^W2j6H2`Y02gMDUKGwWFFqhxJrW_0#7$y+%3 z9_*i4<6RY`@yh#Bv88VdzG&i@^ewuZy z+woXc?BdOL4!2iM`hK)~?c4Z?m8WhW;to{E5q_#V>-~v!-42PLBD^{ix&*R|Ea&`? z;deGFWT=oXb}st9Bx&-58E^gsiOo_}lh=QBd3)TXWVJUf*EYR%tC_gML*Q&4n`N;4 zAzPP@2hUB`3;3qVstGAdZT?q#p*S+^){Ny}C$ydTJ55eafpPy?ugxAuRjoS;&2EWg z=q4Ubn7VPH9dV&HFAYE+@_%6Bfy`@$m$`jz^JRf$!h``jcrQ%+=Odv4Xv~ zOzlHJ9Yg8OlI0r?2}`!Q{TBO}&%EZ*lG%@!?@bL5U-?PN?fq(=iJp_6Zu*{P*=hRg z^zrNE=Tsi?3G7KZm+4t@tRNPW=cW6 z@XUi3woK2~@v;8BRL5kwBXgMKoL2!$f@>WX5pABvGo?66*}~9HH2LJgCtqJ|pZigOJ=f@Kq1XG#E3exI|F`@%XU<2( z4^yiA=kJeFe-Zjf-%h)#S4s|0N6N zTSlI<`FBh|tU8^U<>K#Hm5j#elPvpVj;vBS>+e{+;roOSc`v=6y3e`z!^glmT{}te z&yTYQ`!=kYyZZjxMO^9+eR*@a?o#k)ot4|4hpgeV zo^x2hT&~#BSn=IcQM*N@4|vZ04D9BA)b``(ZRPVuQKy&w40YvdT-oP%Vw<&1{r;Tl zuc^st#_6lS)Q0zSP3@MspZ<^|xO%G_TT0P`%VpU%Y}5Fbd=}!LTiw9?F>AZihPUyr zR)5nu9JXeL*t_q&PxuxllqYPsb6SP%iObyWlRLvsSYDfyz5Qlu_~v_0ct6ER9zOQu zQPdmb=F1#DjC^WYc@I`@S34`zbKdO48A}n}O+DME3%rkKK6vH*gYVT5Sx0?NWtKG8 zXm6U_9(VhsxYTNybgu70C3g?!3Ef?}J2biSV*O&S-8ah59^z5Hwosr`RJ;G=+ghQ3 z8)9*DW2P#VsW)i8y=Pgu&&)B<-|KkJk=k_uRm+x|=B_@YP;JEZ(=^*ID)YPskJDMp zH=Lo`1${HSVvb%e?3rThoc1W_q<(PYj*}m~jFn5H*Dn4pdv=M=6ZSv@1Gifa7pN+=~7b`KWb8$ZuRi_RhL9*@6h80(SFTGHo*ok8Ew4!Ywk1Ql{eHR9XFb83F8X6)yZ4QvvF?6B-@Z0uD0_#Ij_7} zD6y39uEMOSul7ssi@efy-0#}e_ev^p>OyA^p@moK--HTZ+<2vBP+0)O3Rf+Ugo53NbU_>YdU+u`f04jO~z@*gUVYD zN|!`<@~)ZHB)y@^)T-oTvt@~3Xuiu7t=yo10<~`Q87G4R@8=iilygEU@ za9!LgeDyosJ4JSjKTlqLSV`x(%aS)iy&oMMl`^9kzD~$D;A03}z5TG_5#{&adTQR9 z{9n0ST7Ac+$28VJMGcOQ_U7jcku9KhHPZmsWIy|{NI%NKNXD;cb2^%}CE&u$j z%DOx4{dcXZmWy#WIt?OLdM#OCHf0L;?mt|)@6&F4`4=XBafkV`x4*fYytXwkM_#VoN-fv0H?HeT|6<9#Zx z>(G`eXKkPBD^@R2u`^w5$!ojo$OMz(DIa^}gd$A;pP!d|AgA@w(P_p9?^Rd}DH(Pi zS+aAMesaWqwQX}rqR!{0e@DeHh-V2J+DQVaffvAg5)%>FA+lT?(%nM z>PlGcke^|Cc(*2dtlrk<0<)I}96O4WcCI?M`4-=z8;2*yEtH+TPH5`;uCSJzEqh?aXt%jf6DPcbsGVMY0m8H!ic zudw`oLg9KuwS=&G(&_m93*)C2aj(30uJ5{@$-=xn<>qZU$L_3qvr3?K-r9?&|K!*2 zSY>s=U{}NWw!LpM4OdxL&*}N3yHWCupNMXjME1jnyxptgcs^7`p7_Yt^-yQUU-g%T zCFeMIg~rX3Ta{q;dX2R3%uMl($1;|`R(JikcTe_e6?I(`?)~9xWh=|}AI_VTWxOT z8ExA#b>7c_qjAqGX1}-|w7K_3=#26V<8voB8@v|m=wEYd>5tf`Z{0r*-HTSe6Y$9N z^G2BmpE?ZHHR=K$q`Di-zU`=c)xq}HwGaAQYd|o#tKtRqqW~& zsN2_Ry!egj{4lw5uh-Y2J8m6V5`4;|XX3PlY%}hz5B4}0;M1UMocs4k^_1l=ymd79CI8;Z7<~NC zGrwD_WDB!XJ|&xk?bCg@Ls($9WmJ{&662YSfvV?3+}iJWw0%7Gu6D74v7LJ4tlPX* zg}dcd?oY~h4_JDs_v3`QXH%Z!KiSyHwmg1uh-><~>N&4WL$_RZtS* z)ScsDuyc?5^i11_>0P_0dOx-9oK?pDta6vJl;>66S|;Vi4D1%!UOr1+E?@1$AU#z! zTDqCp(PQ5&^QUgDpQ;7!3u~|PCE@4}&CI0uY z$?BXxw|z>p)$aS`8{gIO4tmepbi4A#&D@tBYDV9;OBemlnRn-@3Fo2w6HyORzL{$$ ze@cJX;qm&0{QBwfl{*ETQiA`N7_lX6ujy3X9HPF@qyBT{y#?p)aVD4K>E(T~U#vCr z^t9*4Q?*UAm{+}6y7czsjSlT^wPhT9d=o~B0TMu>4wEEm+9SrD^K@o0?aWSOI)-zuBrFFp+3+N}3v(fVEmY!yTtkUqj{J-}meN8(awlDcd{IB0HS8ulFfBWv| z`SgdkW$)L<+5Ii~_N-@l{e~}J-o3Nrc~JH|JijGy_viQLE2{2&zFPdgJZ#p~*>``g z-kdMK&;G^L%4Js%9dduZ_s_dO?=3i|pVf(57j(eo`T2x9>c5$zrzTI*pa1r$mW6QE zPwl#-YrmeZ{(EpukLBxWpMO2s`|IuDzm8lxt(IOAo3r`!F8c^>_3)~l{fk?YVqQO$ zPh~W^et7SN)kZOT@sBFj&6#+5dG%hSvpn(tLXS-462T)6OYf=7XX z*uE5{Af@vuz0rCPLxR>{JNZ=h%#tY^Yknr4PYgVJ4;8U(ylx(A=zb<4cC$pU7RI`uq>H7fv~SggL!9-eH_ zUXoNPeNFVh%ss3LZoh&ucK%@#F5K&-Jw5*00n@jll>*zfWY*|Tf4ymK+W!hWMw7~E zCz8)r{7C*YcfCSI;1s6+moj%ucfu0}1dk6IXhe;Lu1L>_hdcqDdy`TSv-{2m{ zxtGlTs|!NE`7ANGa6eGDru|H-qg#Gxu#x|=Jvu#W76qoRNG!g0{UVt!8;zDd;Ndn``*uX34>x$<3Z;!+4jh zaarpfepb8bT&KyzWOu_0=eC;ZbmoiP+Obh-OaJQrQ|%3{`wloB&`dQm<9%*(zxl=C zYnGy$cAeEYb;-nSyS>FNH-Y-I2W&ki-Vu-gw^zKTRLsXoeU*oOa(mjZRjaB*&p-cq zTK+?VT$!Ee@yc@+X z9rw=HEw1oTOSr1DZLOmDhspPEd~{$Aaqq3U;-bDxX@;0(L4t{a(mK&+qH(`mte37h zsx*|FG%dI1cAyeydLjT>P44npmpp7$vd1MCr}SZnn3dIxcpY9Gfp2-ttiTmRZ@X zH*X)mIT(}u+mR(KaiwC`d9fF|M-F^_Fimfg;8q4s%Z-Z~xf52`uS}SHqsVElR-1Hc zhr1uo(gQ7LTsp*WXh=RjS#wNR^mk;X^M+?)pF_Dby5^QOvCn3#VrYBo`Jk!M|HY(+ z`5i|V**ZLlw&_n+X$VT(}lr@UWEGMdMdMv?(qP zc^Q0;6CB>W`Sc<%@yBGR(jmD*EfBjIf zoW>TzecT~XckA!PC+0u8udsx{Yt@9jM>AbmXWU)a_BC@Ohn z{G_E8&#Bka7BzP^m#&(p;Z=F3y3piE6rbbw*G;R|cLtwWbnU30+`q&>H!AnO;0=Fm zcVcn}*V-uF3#+$l>`2QGEXbF>!MLND=U}D`i^Vb14{}dpRK9t0`<=Tn?OKK0mhAQI z2~8c3j_5s`e{plvzM>iX?QSZ4s5!wrFHPidk{sKdZQ*Cnq*y!WDltWhb|3iclf_uw z^Gtl2#>xq=^E{3uMC)8v{(mIp<(aI6{nGk=Wqo!HDNd^j`&=fToAh4l%}tKdJ7w9s zR!-y-%hcYkk$awdqrTLVr9CYxj{7e7+1;nGcB8x-v+Yx+5T#?xi^9|+IgUuxv`HHt zPUToEs1p%TaqnTElAXd|?H_Yj{%_&9XMOq5eBZLRf)AQUuRfT|8?=&J)M!>lO?|}4 z6_#!0I!{c}B<3}=H{H<|*G|s}5&B%?pm6nY-Mi`LSJPwo&(t%2J^XBO8tXBGuC5Nv zb$Y6*Uk}|vIU2~ z>^oij)G}QxK&zwZ3(EyT!Lt|JY%L%C3%72U)G_|a9w9#O0kI8bB?W^8vd*-!2h6t|>^)Tjvf5rv5qZ#k=Y8K*hRKc%{}(2k zhJ0VfGi%WtN5B20m4_cr-}}&^y>nfx(~O+EXCAa=@jX|zuC)Dh`@B%->?bMh3?V1v z%NWBfW-m{un!K@B&9p;5B0ucFfzvyd&Hk30py+wB@Xbv|S)B(tiF{HwS&Fwj`znwX zWtsD)@J_DbacRMM&!U$1ipiYmDtGS83f{Z0=1?jhhx5k8lPYdcODZ`&{SLF^wqMz2 z8Lt0{ncJ0(j-tCrra{AswXcZfBb+=Pc8QTX=SAMy=F%c$#C{PVp193(PtuRNsFS&2Twp z?xfn&T${vZ*ZQrNHw;|nDYip3dDV=ZT>@rL`|muT#@=iAW!YoaIzLY1y}mE~W@)m2 z{n*`caEY;SKtREi{JSXz_6IuTG+J|X-`+lDEqU$g38(cF_yznc_CICLv+|nr?OMO! zvkRQ=Q&OC(C3o=3{W4CEmAYMWL}R;U{@E8lTKc*gJBx2W;ns^ayu~|LYh!?)aEYc! z<|bvKM+P!>lV5STs8nf9n&z-iTkRO@L}gx?#~McMY;`iR{n9q;y4h^jhwhX=H9hux zx|OS=M)>0tcNgJ9=S>v1iSj=@eXMIibLLtPv6D$sM~=9b?3G*ibyFv!SuB_Afm58Z zcE0H;ESI*Qn-rzkCCs=_ls8fzFr>nc8B|{&4(Y%`FhW$+a>4p5x!I1 z6F&%i^zECuRq3ml=#iO=FJ0%F^`Xwx>_lwWO&1;>^lt;_=wHlWurM%j|POMrZYwzFUGl%CqPvC*e`|5V{+8&J`aGt~H?AK3 zyYlZ;%YD|W@4WiI6<*)=YufxbT)KXZUZH`P9%#!&i}63gST_rJQ;ll5gn%Wp02 z6gu%%VR?O2nr?&`gYDjZ&*hFUdiOJ}Q~a&(CE+jotaf?5YdAiqP^3BUeb(JO4ua*z z8+IIibLfi2vnP)XIbGH|CRzK+OB`wqWK`ijeki0lAo=*`wbC~}&ayI`a`We*IpxmE zQzp#$GU0oJ{_ZCiziwOTw$+`|qpy4(n}tv4L%0Y>52!r#Grw`3~GJOmUIReXx}I zQ_|MjOBWV0s3dD&+4AvPm#8$S`?nQoa|(-JJXrgO`S7L!$q8Sz`(&K<Ewxr6^frNV>eyB*<7|Zv2sC8sPLyl z6aABvH9miSop&SG==}XQG57l=sa9Q+3M}5_*XSy7ZVj)y`Rti-(ycr9W$zuE{bQm> z^{f-CJ>N~to7TO`+-;X;vz&T9hj_I6K|RA;tEXp1oS*PIVO1gLlVrj7D{3CF6r8#y zdFGVTL$=+yOAWRNb5(6#B)5V2@WNF^x4&;JS(xp6c>Br(+3pD`0ir#gr#0JH4*WkG zy8Xf8>c@L)%TJlH27M2^eI-Kn?5XMVk4vyxKYpbtG%xAc(Rs`V%h~QWU*7nfVX-=A zeNeeeM&a}w40T2qH|AT3J}^JZuxDE1cCHnZGi3v+YFM)mS6(@~P15Sl+-+N~Zpw0d zyxQ!fon`Tq4hT4CCM7 z8B%%m>tnZ|HMh99nBKep-t=tN>ywX;s670=-%a_hV&+k%*D=$oVh$bpmExQ5$06%| z<)^TzLFcM3PcS{LUB;Nb;KPl*0kh@$7w5g$%Bw#qXy$&4%lb?AJM+a=Y^i+et(UZ{ zHE&Xqi~oA>zZ>q|l-@eC%t9+S{llTfK{~ls)8}6adaxzvP|c3C&7!`4W~2!J-o-h= z>(WVE_m@4v9{Vy+yI7v}6<@yZ;xlINoENqxhf5wZn14!K{9%Px?VF-kJEqBnC6=|B zKRUhO2&Xxdljh~Jqw_fA8;*&dldpWrb2Ik$vY8?OZGtY`Tedd!zz>t(;nufLcyIO6 zxVPYO_4D-j`Fn2`?s=?w$onr}R;hKr%jP_Fo;dEJALkD2{(k=5o%#*c-@pBO^yZwo zbzRwW<3IQBuD5I4|E_-5@5?v${@%U*`FsA9tmOyaM!lUS&QWziw_u6Wk>J z33;6TwERi)%$t!jn0+|TFpqXFmf zrfml<`FTi7iM=e>iP2}iRIR>O(fPuz$d-*i9yR`X`h3L#4(%5+cJEN0pnv}GZq_B+ z9Kz*yt!r4QFnfcwL35b)u9~}PCmfFP#R}GmUDV3uJf$PFLGk#?mM1*?r>&EeuDSEe z=e>R`m+MiRXl`+D*RG8H+(!=0;+A8(!kh1AVGt2_AzwIk%Q=w;$0q2~ZmkM#5l3h$NKpcz{x#s0yrE7MZp zU%yO*F=yAj`r2>tR~K%3hh<)VpKYx|ovengDJG{Nz6da6 zJs$3U{xo>s^!!inFF#lRzVGAg&)3yozH-a^XZZiu(fK&x0?=vdulWTh`Wn`WyD{TNzhi#OAqWNuS&zx0b$4>Igi1bnkbEj>6mL z%c>1$Dy-dhTfeL-C`e=TU#a<1)hzbbHt=gGFWGwc@cj4RqP#2aU0=TU=08zAEmPL* ze~Y$HpKQjoY=QEf`){u`MOj^=2Ysn=SmPB#c9R9ePhVM^XF4Y+7 z>rKv4>iP26=F)1HNkL)ZuM%XRJhEOA=XdDx@5;HSj#UD zp8tOP)-8WFd*&T+rSF?ws0p6k^0I2@V~wck8(8wyZ)_CbTqC}$({JDT*#cL8FA#Cr z(#4c9`9`+m`=*qoD=u@*i1jyP*>vNO>Ex%8mh6X*Ej^(6uG(HR;K%kO31)Gz6XHK; z^f0R}JgIQ}-nUbci9Bnb=NhlQ$Qv1r>_?Pm z-R+qNT%syj97_+aR@z_36{UIz}De04f6 z(W^13>q&!iLu1RC5Yycyw%v)dzh+Lpt`?B{G~9QA-o>xCPFB0erMH$CtY@1u?Lx^i z?XU+Y{f(T2rLR3XJUObN*nHv*&ZJX69p{@hUk$sPR@Ls!D*Zxv=1VPSe!;`DQkh@Q z@##6@W|wPy^Il|u`AzKxgQ`zf>v-c{uH7QZpO(tM>FE?1S>LUvZ(4D>r&mpVD%P`M z_Cl{t%Ovq+gGz-u0GOvdFjam4m*8sPz-s zI;o?(%F}-AV|%YSHM(bhk6_^{Wj!y2#S2@Cmx#!)6wG^ZNpx#ASFHS*|F8K{l(_D4 zX6}<+V!1-R)NO*#>PIaP%8m-9Rr5q#3Ei2u$$eRx;2G7&8>}wR`Ekueihb9-Oy%E` z!ld_H`J8s^!r_aD9wx09-q~X_`LC+O&V%jUWrDg*TZ9$9ww_qzGI^rjtk^vYXV`ky zsYrBg&+vZwB%$Ko>)@B?zMa|;Ix&2K>w|5xBo!Yxc~`g#DXQF>@?xUH+w~G#H5axn zHL5r!>FOe4*p#{8-*3sy%Wq06Yba^I*zWG+A|2b_`%r0vY8ltJ`);w%8cZjCG+R;T z>9|#3Qrw;l?^V(nfi*b{a*}iGPi|(`k)8Ib=IqLRXXliHJ6xO_6OR0zvwz1EiC==P zMkiP7-tow96<=!Oxi8;1Qhc2b#NIkrd*%2n!}x^%X*M~B4p>%An>)k&sIB&lRMj7+ zPf6{0#K>MKaP%tIZQHJIA}ywDTd!;qoBwcq{EnH=bT~KpMVT;X1Uf&HIvZk=yUyV7 zdNpe~r6){tH@7W)a{T7>kM~+)))u||x# z&>AywmdV*ByW(UY>UmhaQ)1C{xU}n!ROheUaOUtyISl!1DtZkH`z{xm>)eUwE;6_$ zbWg8oPD)Z_aNNlP_nd8x&($OqB0p)kbv>E9;!XJK+kbr0d4lVlUu>xTGlSb^M@7ZM zis_MalBRH~=x}g9$}y~7k``v~mgyl_rJu+)^^CqSqi1YnL)pC>XS2+{2bI~)+;Z<{ z!GsRc=ayB5HWiEFmU3N_(JQ@F<6L*hODi|I>Cv(yX}tW>$JYydY4|KSH+bgTVighL zgt+OM(;3hC{@ly*Tu1*w%Jfrjv^pR3cJ{Y^_Y4=GwW}xLRWx^it#gN%kIJkLJs;~= zS-!s8*6+GCWfJSM|Gaum9b6rYPfyik$iDbd?tfWb*@+Y13>K~B-yS1y&gZZDNvx|i~ElBH-npn4`-`1S zlB+z;-FU(lS-zDKTf=!Kl<9_K-S5mkwc9tG_etO6dG$qw+hqeQN5=!^wVAcnnP@$2aA7m!O1MLe#cwyI($Mzl+%1`|YM3RT|jf(=tc%zwsHJDO>wiU$~KZj`?px zWdQS(R@XoCmCk;?C}k!*vq$q;ljHAH@y>nO60L`SxuncjW==GEYUQx;M48wNU!}Dn z!5`|LGJcwT-sak()?jU^sO21O{yhTIx1Q)Nvou)Nb!GQy700$Qz+CsiURZEoF_y0hQ&22ZQFS>omEFJv4f4p(=%<@O!Q>DcA&P#T+D zcGOegb6fiC3yO;!mn$i}vC{~Xd$285|Kd@ZpBpM?F<-j-)HAsBK=~uL=_i-DYIUEq zzIpuD5|z!i(x(kxG@qEVrZ@Ma-E_|A8$l`6)Ahm`{)X_pUdOiW(5ljnel=6uKcCK& zk^Zqn>7!-0OZJDk57Hj%EuS6S8rrf~=FZuesY?9+3)$Q5af`n=x{kr%ddr32ipG$M zqWvvO=jONOPfJ%i*R%2SlW_hbK{JM3HG5JY&CiUf_VaskYBFc6mx!_cM(^OeGrrGQ zee(1Xt*)otjv>W|RtEj>)YHv67_z6QVDG0hkLs83FHjIseKz^gZl8!Ig*#kHBJ%HN zRldzpEo55id|;i;hK?NLRV#EE{Jl0er1v=TuRQlMX;O%^|D(-%C9KZR)zsS=bbUpX zx#zCy_|lwOv!<_nk6v&}iJFvw2TjJkz$9GxS!z zFOvw=$c)(et}Hy0@$fBa>D6`~{~Qz5B6yDq@kBoijLLk_#GOvBB zAo%REk_2~lpV!%`_nNk~wtss%OIY9J^}(fAtP?qBFL3z9^mTX2-Ya{<_dc9ccDhPf zXye?&%>|a{-FB^=o7uU&=$Bsljm?7dc!;O?}g*~fCfM|NB(Q`z~-$V=2*Xf?Ze$-W2H^QU~1 zS^M(El9uqS1wrksUDB(LPv88mX!CtmrI1H1N$N*f9%OW8#qjJ{Gk=1%@u#1Ob`d!_ zs~K*e*)~IjDSTI^_LZ!lFGin3EG9*!${t(vb(!Mhh|3F?MrW%!$G)0q++lV^OgQtc z)-%lsMU$Mmr2bYNu;VX2A&~l{+1@Pr?iy41{k`AvPR!o?(_HJ_lGVzsnzgIeb25bg z%l>t9-QThUTK8oxOt|yAv2Mz~K;`9z{ALZsx2|uWoY23)Bs)-T^6r0yZIW%Avb&WO zt{*()T3|Xy^kLt>#I?W6UW#-u`fDqQzB!!hW4QE{r_=9MRaf|xoZNJRt=WGG1TMMV zmUvX=!*bT%n82bX*COuKZqd5);LC-HX$x*Ct`eM_;2*K!0*2^+f3e&G4?I#hdp=A6uNz>*C9A z>T&6vMrZf5wrbZWTMV!4xbOAMKsl+(!_HuzjNXdc@cq?ycYm3)-##hM#Qcdz%t>Ci znF>!eg}yVk)Gk&JKcATBtg@*0&*`Teb< ze9oHYAyFj<)>&UGE_c}4KiPMk;*t;U>q~ZTU9hrLm-ncBd;6th_q>*DI{l+O*V|_! z)7C2sKV{ghc{nL5r}dqK-s;&lktXTyCi$#r?0i-mxpE_`&)=YkNSVuw+`HMtvbHMS zp7o;e!@X-g2^A+KCe}ROq|p`bS)GucJ1O(S#r1Q3NbH_);ZwoQ|JD}1|E?UIlbZGN zOf#cjc~AGrU^Ay8{>&|n&!X}r8@$*9SI0TreiJjJ?P=Vnu9J2zn5H`ll-5Z8*EFeH zv|69{?79EvH3S~Z<}j-YdS3q*sE`oF68!b;?*5IMRy(pJe#LEYy&e9}b)E0C+{LH9 zH7rfm4*7erugEX+gl%G@pxIip_gj7HR)-Vo2AVDj^@JOS$1-ZuKM0wmU{dDE5~a(j?*f3JBMao zlkN5GnRz6##=d3hvBT301GMjMKXG`91K0h$-5PJd`0dxPJm|8{IOVaS@Wafa(u}3< z^WX71p6`;_WAjAv=acgKn6;;O-PK&Vf0=qmsZaQ+XyaFQKl>f0c+Z>cR`Yew7RBRB zyDLr_E*aQd*V$T@Cfgmb;rf+e;likS|M(I=d|hGb zw`QKu+Sq_21+i!MwK{C*_x?Uh&QD;u^Vee~*A~caKH|WWEO2!BVM~*;&xPx+_&;*Y za+w}nbMwR#J0^$OcQ)B_pPk2hc4DS+zvaB(fSZ#KiKX%5j@T{e0 z;rz2Z75_Z?bg|jo`F>79;JpclNwCPs?b5r`X8K&O*SxWD%6qZxLqMp>9mga0 z6s~n2J7>D#cHaFOgVp*ePx5X#G#`KXLSB#AyxDzA?40@64{Vusq4`Yl) zO`gJP)z%k%^c;6DR&ey4asT8ic}7m5IyvP>mzn~c)=mBQc30Wq`a{d5wDYZnLl5sf zCx4A4;`HAh&#r@Vn|;@=)$!{)G-;0HTlVbd$?458DK<_O@6z%Qt?kM9UT}hAf=R`M zY0Dz4(*m~$J^%gZ%ae;IPxl^Ch*+xsgmD+2H2VkTA3GRtH}6&b!Mg7^zu!CCA6cKD zUH$5>{(ax=6O*gsAH;u`uVedf^W*e0e)akGH*BK*OU*Zs{_|zl_Qtwiev#t|xs2Wm zRtW!`TvH*(nNamN@XopdX?|r6&BB&1XBAp~x%SEE{SuL0nB;NudC3X!+XwEyQCN3O zi@k$UZp)XQ8N92kIaj}a%ku8~k4`Pw&lBaI%r1T#c*nGPp52NVPnPb-OqKh2{oShO zu65^0U9A{#@Snv5`F{C4p;>lwjvr$4Df(!{+x_?a4_p2<`zl!#Sl4tM(yy**^{*0r zn8djzcg>PV;qH3rtMoq2FiV}HxbI+CfYX=BKc^b+S^JSW@%zM-^&vj@dsctv{P=Wv z$BTQqzc>{?8`(&m*~M!%;kvYI?xHMhJvS%!vq!+F>|9tuF;?(Uu*IPP%9aM0= z;~KRk@Jnk+87EK7k)ZsguV+1s++K6%PsZ-t9Ao~+E?dm}FUQKB4Z64HY1!&0Ew&n; z()ypvZuAM4lKGH0bC&ugh8;bhe?GeUXSKlcoVlFxPqr-F;QaJGho*{2Ezjnz2RUkT zbN}#vIJ)!_=71u2m=H3cXn-`Jh-IClIcVrHh|vD-r4c75iI@xQ_5Y##E8^*bRL_-P zU$lPMCzu;AV|Re(a6+4;0gu_gs{J9lUZJZGCtGtgIjvQl`t#FM@4fdjQ_E)kKl6Xy zew*Jf0`J&X7l*l(r+xqW>+7R8UuVwzzxesh-Tr(L36Jzv%j6X7KKyj%%;)KgH=V2$ z*VGU$YoDIJpC|23_0&z@@-{p*e(JMdZr>wc9@E_^K`9$AK4f}rC;L5W=aQ2=@jXk{ zT)f6B|9N_!A-{dk?*&`@40+qFJ}1i7n!GzX$?M!%wIw3#rtgxEoSiGb?@8#j%*TH} z+^uT3@%m!M-lBsSKG?1|*JG8kliqtNj@|grmUV*Dx}FyOuWU{Tvdt=Ue0==xo2I?J z5?9JT9XXq^VR^C1oppRN_mbqFJDD7QZ1rQwnJ>3^uP+X}7@6Px{qa2|y&u}wV%7@J zKjeE%)5|fhWc$B+(aL9j%q=h1%2syQH=H$x%iw49noZ}HswN#ZT++K}!jWm0Z{C!! z-}6v+t^0wNbaZalc8U|7 zyypCmThXg)_#EZx4oauSoaL+UIWRpxjJr8LL1}~6E&lV}l6r?b&0l{zf5Sa2^;FVd z-@AK%J^NYJZLYldnA@=(kwQ!3g60HIRPd>~vw5J9QiL^3#6At^FX%@L1u-lAJGx>KYehG5m2!nQ}4CW!v$$n?1_{{d=6A={Xw4C%||DG$ax%Tbm>-*Jx@58ziQNb2R1H^|N#etTcUJ-uOMInQ1T6r}Zr92dg&Jl;n0z*OpYi9`5`z zVD;2d&m;+OS0V&U01HEjp8v8t)x3^0S`#^lD(c;X#|%v#UNAwa7l0WFYUU z_~l}m>DeXR&&0?x9-i<&ft$~Yej=6`23l9;;7|w(~s5B`=oVk=G9ILi}{j~ zJZt8p$*nIt+-4_**{~R&T{($!f5nmO^PT>S$o;W8$bU*>t!T#M13i}}98O7nW>R^} zH#V?h+rG4#t{=Inz1Ir4ZyjAU)l5G8rseOscTTyrN&UF;_~+@CNt*r7cQOC{p7$j| z`Gq-WoMVn@Ta)kozJv__iSIpsltj0>oDhG~`C#qqsM0KvRSdgj<~qrRAKYNLIL&eI zgeafcPt+WjDr?+}o;G`fR-oVR!{+Jj{E;h}k6OA<->@d6YDw||1)03RMiPe~6nZ;* zINN8&-w9F|>qzK`VA!#)GVU5n%~XvgFPI)nH{U$Aj*V?+z{Gu%12?}ok*Rx1GW_rP z8ig&N&#-$hov4-FuTT)EUn)@IF+ub1tjNvpGV1wms_ou>^TLbZqVpazqe)SU7 z|L>s7pXOJ#(d+8Fhu0^ICruH0G0iyg=@RMgckj+?bW6tW{hXjT>11i^yUkzI!j-Jm zK4yn_aDV35{xxE~`{t|ftiD|jbU)a!2j&&QO-}7OT$itr{B5us9MBi-QHaG z_lwy6p7wJRadM0}bNVFXl&~pIjPI8*B!qYTE%|iuaO(OWlF#dkj6EdsS95dU3CET9y=vvUaPFS;+=!eE=~=&) zS$s7^n`ytq zk*hqn)@)mH_NF)YweXPjVQY;x7ne9in!NGxnQu2|Q?JPf?yGawY| z0b47sNv^vn`PXi_)5pB2?3;qteYvG|VWn?oC37x={r$VnOQ)!tpL$fl#&!MMr>spX z;qiQXA7oT%-T`Y5)_gv-UQ~5U@=bg&=`n#}4Mm;bo{3vIz{OAe$Ev#^V;zzsr=vV_5AfV^E4k$-o$mRsZ?t69V5pM&&r~& zvgg)6xLUHKQ9V)M{hx&8XPuHF2!^9A$VZ<~5A zsDy_}ye^$)!x??_+J-#IHCxyVO`NorUUobfG^Oy6?7kD-lib)Q?E3eI>8W|x;dOgs z&7z~5nWPpLv>v`Ye_E>LYd-&nLf;}9SNy$MetgfQjF&v(7P&mftUvwUBqaKcQ)K1d zqf;BK7I|*eduH?AJLH_j1>0B0qnLjer6qg~%etYXyymOo=@%|nDiecPR?ltA+$wg_ zv-pQx+(b7C*^}DaE&PNoEj`?yvdC&uPs)maVf)J`s~QES$DU^B-nt^J!dflh_u0V1 z^W695M9uuCxBrQQ{riI7OSXRaC;G1cn$@hs+ub8(`l(G-FZ>}N5Wu_r;VQp-M=LJ6 z=}gK_UnOC9VYWh>pFv>Pj&GlSZ`X(xVLTA2!le6s{`(yl^>^)A!Nd8X@XIq@Kb4?{ zuW{SH|DGIMHYc!h;Us-)nMr4>PVRnr^47b)4)M3LHZAiW{Sm5hmS2&7Ms?5HUXG~8 zY9U(-yl0zVRttEq+BL6bd$(H8m#VGOx0WudnX+d6hWuZWe$!2CI)mniZam2Iu>6am zhHd-GXs-FGif&UIC$oHac;32~Ih*bO$H#(lB?j`f^B>GOFyH1v=aWBP zJ?|1)r}5q`aT8Sx+p#ROYpb|#hy1T~v5GxQFBr~kuw!);Eo42uEu!J zuAjAD-?&(+iCfMf>i3gZ)1qH;%5}(b%u5gqa}tp9`I-88!sb@JxXC+MxLuqNO^|rK zj@*NM(KPXZCug$(|zR}5v zACCQ>7AYg4IdNmOn#2@;#(U=N=^U;T+%4PREy-hIO`bbBLgt+*OH#+lBYj=mL0KFV zPJ5i=dmk@iz-78e$u$8bdSr?#>%z>dMx#(9?EyLLLPrP zYP>t5U`}g}fm+|T-yNwEQxo>a{E3~j{Icb~SrRSnE8V9F3Pn6Rz^i8!a%_iXWamcR z8Cv`KOn*E{uwvs8j&HiY*T8M})pN}9#oE#5&Er4EU35vH-;5` z-u7B_vCN0-FWgHP9#nPx`z%!c->#eNJ1woapRBlcq%-S?M#4Yc8#>&)hnLB7(nsFDb1u`Y$gPP|jVg$nw!zh* zt&nETBy!e#9o5ndiWP3w3&HuPJi9y`o%U+WuP3`@}uIu!+<8 za&|V{WfuP|`Z|2G{;|d#UkeU)-xlLZwqtlGuk+NL_u3v|#k6xf+MG6SzB5N%KUpeU zQ+cQCmw2&|PlCFcMlKIN&tDv-q_|btoRg1pMb)J;OLw7?ZTs!46wYfEwzx}fT_&%m zw4~8mtD|Nf+l0_72YPGncAR;Weof_cL_}st4#R>UE91IO_oS((E?IIy{EDn5dli$^ z>(sz&?-MfCF4?9sGvTaw>rtMvlLa3yHB5f5zwzeTIjbHnTl46-2)E`YMFWP^4Oy~2 zGWMp7F8q&~!=u~2lo^Yto;dL}Y{}cGceftyIQLY>*K5w1niMTY7u5~Z%ADlPQtLt( z53!is-*NC$9#?5g#LX3tMK}V4X8zbJIO)ds$5ll^m#uRb9PMo|-eRLDWAxr!YjPpp;Q=G$DSnV*!`%4ttX1ZYrHfyY9%#_O|t2V&CR- zr+%{uv3)zx6%ahnRHyL4sj{S%{VpfEs@;xk>~wm!>B?DcVUB<0E4wqS4SvNXziQRI zCbpqw#vTqo-@;{f1zHEL@42|v=A?TsYfQy{J=4i|>N8U^93<1YZ}7e@n0uOW@hUA# z35leeNy@Rl{Zl%1zQ^kx`h8$gNAlF$Um2fxwdr@qnumB>tGy^**|q*?*vXAgq(yeb z?%U(NiutU5K`f(?o?6^S4~u8_`5ArmtOecAg!#8O1i#RIHBnQ!FhgSX(qu;S!;Wp7 zpXN?q0?e)?x3i-jVwuZAajYwJm>Krq7r#SG&!IKQyuAZJMEw&ylMk zv5u>}vz4A^a6DP^x3|CNnb%CshYDAFt|?3IzOqwbiqq2apBGghe0aD0l5u{e-tJQu zS9u@bDXZ(*r`vI<_)+BXHx6!d=Bb>Wd8uW?&WGO_t8U~kiDF7k<`yoU8uiuTj_Ug_ zDcU&)v>WVRA1l)45@*&8D62oImr<~2Z~tBae%}v!E-sJjn!hF4@l8^m$Fh0z+e+^; z-OjiB#93OuB|u>B)Q`Qrvt^DYcCVI|?C9^Fb zM*A0heYJUs)S=rEoCSt6ZyHZu@rftB>CdUpe)AUpx!n&5R-~2l;laStByP zHY%UH>&TbbrduUtGx|>P`k&evQ}zCe+SSdH(Wy>Fn{%g1$7*X6De z`17DE{^K+C+2@wrEj#oy{o^sFGJoBCO^@k98;s?*M%-;qe!a;rQ%h{xWfiXMy;`Z)^Z9(a)&C}hUV7oyTUdEC`oWRM&o0W^?O}|_eLVZ| zDhZxBIj>mKzm%PbH|$LJR^PQ-EE!mA^G8ATlv}A0zdxLe82kc z>^+@$-FcCM-`VVWJ{GQ@dp76mqpR;;ZoWG?J^tPO{d;%cvignSGOteZy*bM=54a6F=rEeR(H43qyqz0gr1=Q7ZMbQcCQkz6kGd ztN3luEAwmi?!w?H0XJu_ww*Ci!)(c|YqQOqZa-UJ_MbgKFzf(k7ZKd?%TLPUGB!0b zhVNsyz%ssT0qRT=9N*ml;5cx zRkW13_38R=)dnqYe}d{(UL?UZ{TB-X(MI{^BOSOYa{`%q>c*|5T*z{afR>M)IBNw{9=LsqcR`kMC2# zmgJ5@vkorlS9JUP`Q-gfft9lZ_ei%MbWlHk@%_7p8g9ZZ(++QEx7E^|BKgm2e#`g5 ziV}-OTRH4_)VDtU`|IuG!-3kiY{_g>pYzs9@Vmd?Se)FR&sX#%uzi`ZbXRSSgZxy% zOSc}%f9BeEkmXjN#H;xdr&zRktXO?I|2~Bcu3 zC7!OZ*(aiPn~gh2u`lZA!?TV(_cT_w#q(!{oXRw=nQ{Gd-oLL$A8LHuEZAqN6TfOf z`*-$K_w2;J^AS4@&w1Z_Zh7{FyLw5!T-49MlkYyhdwlOX3(HxCZHqA7Zn?7_ zp3juenlfwm-^jLjp0Xe1X*!u(Swmi4nfv*0zR5JUzb&GZI6d>VCf!&z@B0M5{mu6{ z_KD72KSO%jUG_CBDSi{IXV<6lecdJ}ldIVwC=$D8#0>hT? zciVF2ykF68;__|z-qKHo>J0|cF)|z~4oVv$4?WQTEa#V*oYfPRD!MVo zm(`E%nGY5matmfF?@PS4$S-Pv$)=ew|Lb62q)V7$1> zRB6ulb<(F+CEKnJ*6W|?Q++IU=93xMKdLz%{3*f{V-Rny;UN4h^WXgi4!dVIHQnps zyt(39h?(`;d65+kyWjM8+@Ht9TEdp7sQ7SJfSS|GQj>2!m z3tP6H-tA}cs(bCyuhH&nnYzwhZ<@3wdggR1d-d5$^+H+Nc?UBZ#ARLt^9l3i*cY-K zeto>_diOaS?nxy_gf>XsP_nT2nJt&UZ0F~uB$J~OCtTi`EWI#u#$3i(JCd(#O?O!S z^c-UvxA~;DLUT`}DSn=9#fK(u`km#;*3hNGeA(fLiOR+aDU}Bm>f73P&Fxg_iQ3E( zsl2hJV{!XU;jda&A636zdU5{M#PDRjkFkCHWvm}LuCl)Nv5|2V{jZu)l(AE@RO*j}7k%Cr4_#!HL!2YO4lExPk4&hs&= z8;|}=>kkpLIIWv5zvyh%?0o)Ynr+YqrejV!Qn>fOt9a5Lx$|nq#miD!54LB1DUND0 zj);yjymDP*&73E06GZwpNqF8{esaI~#TNdL4-*VGo1|oP|FsM~dM27FU*u5PR<2#X z*23dK`lXgz-opVYhG4#Vl^^QvGEhR5(b@Fpdn?iDDDfS)- zYLN=`%U)PmD#Fqi`p6?P-`{HQy9F6uwhepK0fyeev>mF8R+*MV$)EHhzn$zwDm2q|i+Ex_rTvC3_Wk=BUInYe}s9l)FY( zwN&!azk4^|9W!G7$fc9NWuEqndg}nC*F7=UJvgqf=6bC1HmGjJ@>k}jvd{l*s{8r; z@I{5H1Cw?N`ARM0zW(mb`_mIGx1DL7ugz&9m^$gA*vC+9$Iu^VC;0b?Bun15KD^Yf znd7@=$s(y52X!x}8V=pC%T_jLzB=n(+pzEk%X%$~8{6MkbIqK>w)CwX-~G!e5j!3{ z4?S)1wd=u}$D#cEB4rD<{(Nx9VrHo7qi-#*cb%11dokyt=Y{a8=b8P3_p+R2p6cG* zR{1H(`TX)V$NNttcvPHn;}40vt$M)!3TMefv&r7ftG*f4y@O ze`wi9b#8DK>@isru4~oX;GDDAc)jwUI@L)lPh0lpF5q}<%CeQgA?Q??~ySQ)eAlAvHM=-MH%I@(-(8gT3ktwRC%!N zj9&3~*G?5P$y7V3z+sJWM%ZKupEA=hus?)Itr@6Pkn!vs0e%8-zIg8HTKDX*ZZpo&PO{>1- zXfL-A+i z56$G*)z6A;>1|GJy1V3CiuZN@|EDCE$1KRX6PNmRZRMocl9kt&|5?bihI5JVs)|Ab zM%hO1b8Dif9+}N|fB)jII}8tT&#GP;%2`#}e%#aC*L?H4O>VA#c6ZfIzrG@3V#BK_ z?~jdbCY!f#n?G1@6k)ets#w)?i?hpC-Cye5d(VphE>dk=x##BUsasROelqSecTLN` zq+2oDFzBJoiC6dEO-( zP1tqiYPU|2mBsZ6smmu$O1@a>ytmi;*frM|ndk4Wh?#Ivy1Vtt0-+;1LJ>cAZ<1Fj z`pA0pz0Y)`_LxTR#-;80EiY?M%S5$)6!nt4Jhy(ffnUMCi>yrbUnZVD@b$}$xAp$V zuC2Z5Z~7>1@wutT%EDvgboAef-E-V($LMFWO}i#Cv|;7b?xn}W3unD%pUfiID4MgJ zHU4AAg81t%WAbi4Y`g0I@~+BZkMb{FjdNc;)^V-a+S@r{`p!QxX3h4gAIn@>Om(j< zbiA5*-L@_|bmFPiQ`SZJN6BTqE!CWJ^>p{q4Z#bK3JUOLoc=N z@F}nAKXJ)moqxKPzbqj^PH zs?1N>EZkO#L_f1Ry?ST@n1FT%Dv9&YIPgB7EYb4x_+P1`?{-3o32J%T~eQ}E$S6N zcX@BwYi-}dCnNQ&td>`W{x7_yuhS@xV&@w=j&;ozma8eLAy}*?uXBRUh8V@Vmx(lEmv~4`>G?k zA@eTq<}5p-ZJ4a`G2m*fX5zEbvyE^1H-{x#?X3MdM_%u%pZA;TU7TBbQuz4GgW z;nwW+371}XT%8)t`N%eP+m2Z6^A~2NvvllU;ArV;v|;5-o3%T&uD|rVxo_3tqsgE2 z*`-&!divvDw(E-|$(ggQUepMGt@v(lYuc~{OGnH?!9W4r5i>Tkgm=U&O`xJSHu^rP zdFdq?3Wk=TyHE*s#ID9f7snhg^otYx-%)!|jxdoN}iA{kxst&b&OR=lDSJsg|%+wVthUe0hEC%%6$d^^&$f`u}PF`unkaew=!H z@6T7IxVxQq>#yzKxBtgOrzig-KHuGaUjHGZ;uSregI=r4r{9n3_|p(-z5I>Rn|Gh? z9{vC3>B9^$`LM;`PbbFCndbJa+m3}*y#HLI!mW4zYXZCtf?oW6|3F_eY~}a;mKED2 zc(3d6yDvTbsOjE*8=32_uRXSW-^%~{|GNBN>zk*4 zsM=B1*`KZ7V{~`*zY>dEsiFnX19iMuSAL6sp#3pc>Hn^(=ilQGzMeYO?ZNw}kMb`^ zhpV#vWQj4&*8eJB$kg&J?Ct*s<_RB!Zr}abuJt3ey71Q=0fn3U4_C(q?3=8}xvcr_ z|I?0ox4iWKeg9-%uvR8kYw49org}G?n(9pSSpD$sy(LG54n0UdUUWaus-j}*%WvCD zCD-4&^-tpel-0NQXNvDX*f}NW<&WJ(i4#}f|Iea)`Ignj{VR)$uQC*Jmsc?`{W*7c z=KYn4yY{VaI&k~zDlye7|MuOR=_+K9|5Neh)qken|HMC>eVVIb;*&?QbHzkXcB-z) z`p86ja_w=q^46N%GXFYKG{e9Ubth@nzd-k53H;q;F<8J0h zE>R7g`Wd^@=V>%C&oY1A{3!4GagX`W!&<3sZw z)_WM2Jq!Q(egDB(O-z~_@?ALB3I3{!oX`K0(YLRe|LZBK=NlX!YVmt2*d2(IU^w5d zR>-6haX)Y4=_eJA_d?W9rYQ_ z{{yxim=oOdZJJ8Y#YVlSKclYNop}``S9>UT(yB+__AzZ%oN?f3sqsmc>x-*Q1zfD_ zX4kG+VD|o-!da%vHv@d_E{pWV=rBFy=i0qs{c^FdX)|gR9oNRmGg#iM;J0t~HtPNy z`dWmEUsvFITHw7tBQ`i&&m~%jK%~jY+#fa1Xqx|yzPFTBHVZ+k{UUE0rNblS9 zX&Z}0uJHpgMJJE-e|=N6Edtm-tz1#_;$D^&vd$&Hj9|#VeD( zOxrMT@Bg!I_nFt%K)as9?*XZj}P9{Xx~8 z%o|@PIljDPeC-tPDrw=4yf?cRC3Hu(_o2 z%4Lp)rhnDzGY?u`g)G}^ztF9;?)S8HCRS|>WveZB?&hpo!s@NVy!Tc^+1Up1nH{AG zC8_UAIg=jiM4q<0m+(XO@!wh37-g>&u?F90&-_uw!_}PVn>n+hy?6@G0&NWyBcZH| zOFD{|Uh|S!^l#5m@k2bUS%OAe8&xx}-`H8vUaTsfe$?mIx!KKY+!@Wzu74!V5F0Vq zCy)D1OL5ubr;A_jmtE_euXk~W2LHk(_jOWPZ1zt(*~)mzeBP$|>gQUI%kOyjedS7= zd#7D5dBIk;>K7jK6e4vZ*1pL!xw`a)hN9gz;mJ*A@lCSKYu}fIt`v~fJ?JG~Eb=gZ zzSkOI; z()u5YzWv_v*JNGRDR=vc&1+w%i#%4>I9f8b{lF*R9ZD=U2_nD0Yp`$Jed)Q;iGyk1 z1!de7C0E_K!qt##62mtyrT#?8WFN+b{1zf6+vasLu($30s_D5;Op>>|$38y&mttjn zfmG>4-d}&?zdg}OhiHuS`syiQX2${v2kWXjBF z=G8@(HOx&quFkdn?vf6v&2M>}Kdsf8bnnHJr6;wUr7peuqb{+#K&ikbiy^NmgX{3a zxf?_-eX(3}Y`>&Z|DTgb6<&r$LEv(0I9 zJ=^>b1+CAT&2;d-{o#whT@PxVU*YOduOjE2RJeCfu*y@d*(F*R1Nik{*m!x_ajcS0 zc~@~DCuAqf!pbG}b>C&hh^nOlY=?UFPF{QNn|tcuU4z$U(JQ}v&2V66zfh;| zT%5>#?~K&y*1CAcBMY~)%vo?@6YpmE+sC>}X80rrFXwOu&z?hnkAIzNrOyAFkw23cU5^zoaT_ z$jb{kzGXG5-<&EFQ(Cjh=)Z@t?c#ou?t5W9*Urst3>UZF&9Zz?r+)nOtE}6ZC(o9f zVz57gn&kq_kUT$;E`Ixt#I^M(D8zbsxQ>F8Y^Z2I~ zrZ10ev@_u|C@kD`%Ob$=K)coY%#)in9Z#G0m}+Gny5^R8T;g=OP^RtUZJqa(rmdBF zEMs{(RrTxaIXTnYUi_SqOD zCvS4d4V>-3@!`RP*{e#Je%L9xTzl@jd)HCpv>vmsLWU=2Zv6N?z)*3Y9&g5}J-cr8 zGr2D)d7=N!@a>kkl1&E2t}|uc1Yccr`a@;OIo%ZgBZ`+dH3?o7g)+ZGTF8<;@rzFs` zvPz5b-+}T7^~pZVR(o50Q9iurMb4wDW;xaMY_;=d_IJF0opxi3a!b{v9Xs~S(@^bB zVY;w?>ZB#oHBLIL=eqyb?rELq8Qv_Mrm=tPIZdhb(3^Em)tqabs-|t5l>c~c!{)2y zx+?cK_*4bW@l&(;@NZM?mr&VTqQz@JOHTY!HLF2Sm&tkJgkwK55A?YjHO5!}sTPr~ z=oOypQYaMW{k(hA%wMu`syi&RJQA`6d>`1IoNlvx?z1I}+^@X&AH2`OH0u1Wh;<#l z_fA}#${XYP#MR_$U)IxYiOcl&WS-fmeRXwF<%*X!2L*hC&YXGvVB&hq7;(v*ea4zo3_9yJvCh3@~eXIH+ z@bUYG0*UL@o9eQv#{HlX$R}x zsqtRhT2NYgd0)Mn@|5(;<*_@P_nw>NUftXI!_YsZ%lpvf)z_Kd z{Q5ET@E;2;q3cT*dFOW92#S5m&7Zq4=j_v+t&g{~YsmI(ezd@Q<3aUkzcp2y)#tu- z8*g5_B&~c`t_A-l?#bTWuRff+v#@&h!`x|6d@mPgq{iF{`6wtGU=!i_v0!$@i`@Y? zR?Mi_yC^d&Ppc{{YfG7scAW^fTGfo-PpXVto)+4_*XpbOc_oG4&2aUPB4vfB zdulh%eU#|Dne_5i<5|zQyK9&>XaCf@aQ{pG`L`zLS{Z-kKifH5?@rGrA)DjVwmvZ9 zoZS(g$1nBsr)d1;E^7{}UscnKmc8&e{*f=W_=rH>p@KaR&-Tvo-xi#*@|2_Te1R`Z zU*25h_AIxsLu&)C{Oqpko8=up?XSkC$een4mSyLahixky*WO4ucmDRW*P*}KMXGre z)^GljwCV7>jk9`XF7)0FI>e-;o4?m{?Xay)#mdn6OH;UwimfGpJ!@`i5Sn$5kJ8aJ=<=d~utN?WcbS zw|!seaqra+?{gQVD?UyT%9UDlo9%_7_JxlJ5c)h*t6nt5ikE|;_P&NDF*+FcVI7`5|LZ2tdfjgVj0-$^o`O~0~Q zp>F|u@4l}N2U+JcDs}eUJ9AWV{w<@R>ix~ny?3+xPEFp$A3NnrmEp;_LvPDA?Y?u2 zJ#h(FPiE?NzOTQ}ezyLdt0ZUlYTNDn-DzK9lDy`>Q@(j^$MkQP*$sP^q)aoroi4bB zx0yF0p=ZxD!w0{rB7S*XkdBp2xBR!~q6JIx^+WF8B(v`1zQ3aK-MEZ1!Q-#P%++7! zK2dpabN2)J4{Ww?X63pDFZ-LsynpFTDfbENZ(Gwd|Glu^u(I*&;*w+f>M73O=RW!t zJy|n9pmX1%0yq6jXKy81E{t&dx-HiutM`+-+4Hnj`n&qBvZXf#b$#?widuiJJ!adt z$$3p?caI2dviqkOu6DgI@{ZB#U;CJfJlqpyi-h|5G^<&8GMoxL9X}UFI27}X0eISeRI9@eWr6gSCwObSWbG9-5Hn4y6O|9x!P4n!@7?7{i&;dy|RTndX9dy`_h@}{x`(7U(!C# zIQhPC0Q1C?oXq}Fky99_g>YV*Q#bz=pVQXD3%f4Xa%J7o()3w=JEdV_wE41$#Hybl+WRtxvq}q1s+)|^MrUSMT%7Nz=cUas`R8e{r7$zhasA$m}nDOQd>**~!IaopuJmL_s zy)Ddq>Up5qh4ksgS$VOS%J_JdC-6P~{zW@dYOY!Il%tIC(&ERDT=^la<7fY3mj&B) zyGQ9_e-w57S?c&%2)~{c! zt>|$26{}j-$sgG$CcaN%$>o^xQ-W`9tqOnQBv-l5e&XH3|I#1ID7uHvRqql=sC0NX z_mIMSOVPxme?>n?{@$SE!5iZJ!dI)&WVhlhsjEsVTkr1l-1w9&OySjOskSwXTE6o8 zo%INx6Krk0_g#N`#i!F!<+UCLS`UueWo>3V!ICh&Xwt{~LVL@$a761@ha5HKycq1v zxsj*M=Xr(eQ?a{VTK(E;i`UJM^giYqEa7%!=b@kF@21qt^qF#(eN-;~-EmicX;8tu z?QgQn(sSw#>a6}e|CNrXn&Bq9zX2z8uCp%FaF^$P!Z8ZfgdU;b z(i!s}h%SH7^Z1F++a?>epC`f^{xw+Mag5=g!Cg9atMXU5ptGmBD``m8oc@2r;2L`Fm()-+B+I{}^cB5j{{EggC59Vp_42i@#D5ul^Th2bAxV06?0hJxLhWu^Tv)p*|V%N$Tz=wm&KxjOE0H8Gw+m1 zoo}Q$_3dQorQ3q0yk~LT&RaBFRF8j$rE^)e*S%EhHR9pCh1N%BTwSAfq{1Qo!1RQ< zG4s+c9hI+h@!&kjTg1i5WUD=ytzYN~AO8~z?IksFG0z@nf4CMOs2pvwNydrkTFj-@ zt`BzA+sf)qmKCTk3h`Bb@v%Z_3um0L&c@DVdcs$Jq~7~}qr79{G?_^&HQlqme>0w) z(x)(|_L$+>i=uWyiQLQ7GYTvs#Lx|Y4jw_rZWZDD_&vN$0TLmOBwi>g~>R<8^0E+wkb7?dLN!^S8%b>@ojzdh3%( z&%TrdTKZZ$dd&O!W!mLgYVWc?7+Pkld4BM>ms~4nU3zuj(Z;T|tFPYKbZ1w`@w^@D z4?bBrFNZHvsX=-Bl{+a*Qj3)@pUlh1+puuGV_{Mr&oUkPBl5b7wg^kTns`*5d#mb0 zdkYzkfGrk#Up`jUx|aJ@;X>b)N2j~@GqZj@U4c1h3?2#w4H}!8S|AM?TVf0v8yOf7 za|^}Zn8;$8?SkKoPfxwSp?`O0dCTt&+WZ?IJA2;Tm>L!{)q=lEBXE_+624P?UtWJU zH89RdFnFTpyEG=XKb@U-!TI&ly!&o-IOehZHU9VgV)x`~{y)$Dob{~QJ#qH_bN>G= zD@&D*{}+6GefD{OLx*3!GK+%G<@n8?bK>J~jdqRXI~8x)UYae}_xrbV>h8U=P9oQG zVyk!zU)9h3*V^F`8~8C#fUU*vyurKfyKy{f9J<@@zxlFYNkH0f^(vuz$KQV6ZM#qG zVEfz5pPx>D`gSmH{ZzRo!)VYV9_u&X?j=7zmbd@j$%F2)s~meos`vQ!pW?`T`)zk6 zYkV?OF8hREf=hfh97+f{Fy)4STxQhg=GYC*+eJzq+6B>% zP9M3tSMrdX=gW=Fz0(_)DJ`t6`~T$L-+c4%_4n=Uc7DI?Ht){wwtruLevf}(|NZ}- zpD&)A{w=-8^|7$x%#5ZfszPzUTt0CGW$#M(tLD(-$G(oIYg$jH%eCg!bB&y@nC0BR zcrWzBp}hE}_M!m4Jo)!m6t;dWs@`^Znr_A88>iJ(&KhJq-=2TqrohXWS=*;OA7Ib= zU8Qc|#&zOBuH5?EJ9bKv(Ts^x{WrhTRQx$BS0?RfHB)6q=1dbQzO2r(p5t+2*LZQ%PxFMc*P}^hg&z_u9w#MMOlvo<5)%6Rhx4Z6 zww3KOOK(3ne*39p=WXp5>qPasS<4<=j<~US+N`rdVP$rgc57&TjQn*ms!#;!ONDTmM8PhxForzBef;47bhRC>n?_RE`wASRh}v(yh_BW~Gm0)XmEE z$I1n6u8CL7skiT%7Ww*Var2bxoZyM`WcKTXcXco)J-dr3iYS7~mb1>%Lx@}8--&*i-)2+*!W%6Y2 z=*4i)F=KQ5BBtl`L-ULIuBB}L2NLhRGJIqom$v%i)k@j-8Y*QEC$iWv9Vis5NO*EJ z{KJY{7Rm=r8JDj}P<<|G=&1RyRXydS)!vX(Srv&#oXjPbYNZ(S>c6*ZJ?5bM;mCyJ zmuIS6yqIWk&vCl|t9ge_(Iviq(H_AmsO@v^JdddCd1t1{BABo$@sIc{_I%6ymIsBjvq^y&!)Zn9(Mo4 zUlHS!EB6HyE6R1AXi77)E?blJTl+81l65n^t1N=gFnzg@f2kxwxlZ?VrmaS=#`~@l znVcS`f(a5YkL{0IBJ7oRn(6wNZ_{NH+9tH=FBhn{v!5FO-&TLkAFm~I4{geQdUk`H z#+;69H`Wuq7510>yv|NLEw@>jBdXEfbAGS9&e5xTWlDc`{nmQ?Fh-V~NnbChqW)Wa;{jfQV# z6@C3P<aP^ZD5|iWs2ovE~C7OXmMW_Wz{k{yqW($w$#2v%JoaW15AqT05F-vaop z1#=p{&G>NLBU-+Fi?D-Xi21AwOt(X4>x$htzaV#R$5$CWrfr5v-*%+0Jhx`cVx==* zZhT%T)Y_)UrL4%5d`Z>RD3r@}l&ziSNBscD-1c8Tht!bLJk#?#ij# zX9^_Te{9_0{;a8Hq5s_3r`J47XXTMi{jOlb68>BKvF)GTdt>V+C@j3H)B3XM_|NA{ zE<5zh3aQ+-ao<6moV|r7OgZM?n|9@S)*68q6?=Ei`~Kz4bXmzc7pAht_(a-fwo7lh zHjj1FwHckRtq)G0D-TZOw5pn$yg1h|{LCSD^JO9Ha@Pws&i$_Ky09-#bmsNUw<-%0 zwWj@iwWnWn#;K6}PnlCbWlhXo{#A7DeB8w$t71Sr7J(3`Z6K%ysP>_g}=;i9j~h#Ts>peY5q*f6TCIaceYwD7ZsI@ z74)>8v5$9tvGh9CiFN-g;+`sHP5I?NVVO^{*{rFFYnjb0f32}NRyK)a(%D4^TsL(8 zwY#F(xF|}8lJ#$Z;3*}vUY-h-qRR)I{(+sC=%HHn%$7G&v zbFZFu)sA)PE-(K29(^lzC2eOz^TDQWl`b7WiAa|eY+mHGJZXi zHSd|i^4ezGW1eZMI#chSzUJY3!tBAydmE3qw^zD|?wp;ib><11?V;pXvKoC0>%A^1 zEIFwgSST*`p^)ExgUwVkr?;kMhQWocz0t2z~x@pqxGaWW?R-9mD zIG8&j?U|>FY!G+C$vBhm%mttRWCoVrGJk5KRI;(W@I>V6iHcR%AN1_=3u9L}c~Zh_ znnKpfra6~4d+S*1(1%ut!pdzzK~%qi7(qMqEp<;ZYnCR6lAH(Aa*wQcU~ z>93h(xf`rEaGLIQRdfC=c;erIrw8Ket$HVaRbK6+6E3sL=|$zKH?b(UJ|u9V9Pb6Q&Z(I@cHHBb+pm|mO0fRS1v`tolP8PpJY1}} zT(0(s@Set}lV^SZx=r@!xl3zvX3y8t**@2Q#}Bo<54JnkFWdfh(#0#cr+M0U|5tG> zaati)JNb<7)!S{w(VkOfwg#SQ{5^~5vZ8c&=HqqiH$5q-p8YM&^~y9&CF9M_=CLWU zf%BHyNH1F@pDn$1?##6luPpj;uv;qmSWM#oDQ8z($o`n&e6CtZt4CY4XSSCN>kOH& zbCF5i8>bb8FYQ~mVWLCmT+Zt^x5}4h{Q1Fuy^5zQrR{9ZkK-p(-BOn~_AYrnZ^PoW zhlYuUzRB)QWy#!mf!BZXO}}MD&1C#?24bqY9xEAi>f@4EmT)E z?bvkW?fnkNTbfJi?Bi}YPcg?2G5 zQ;fdosLCI{!zr;@BJmYt9 zs-*9AkuTq}lbk2S9bH$F(;DseQm5*#m_8{rcuS3tExBQ^+M}V!;HA|{_gBvE=TQB?57*9$y{+{R^An3Lv^WY$>JE#M<;Ce z9XoR`;PBBtzSFDKLQ0&@7HjFZIL>}$vb((C?wo?j-&XI4dw=Td{2eELOkS&J#XoB@ z*Q)ZP98XtEKmH^c9>XjCB!eL-Z$(Y$M}6LpzUpjW(|2Z_vDt39%-E)@Xt>|l9-MRJL2f^^~5=S=tT4cQE0e{l%MaDHkmLHA2X+L*ev|4sq_rGbIPQ`t- zJbiGQGqcqc3+bm%cFcHfbT^Lk)rO3$l+xzZS6@2&zLvxlO@1l+&R=xPC9~@tEero#dk$v^5~W zwcJXZFYRlZt6szDRZDK4)LZ^*b?oXV-)?hu&(ThO6b-pIJfAwk-|0XtQOF z>D86j`|CV*E?CkonbXO@Y_f|13tLHjseOQ?J zF=Kl2mX1|{b+4uy{8~|wbos2_hac<71a;E{`jq?BShbKHJ8Xj3uWjFJ7-}Ki{KBhw5l7Oxu6uXqDxLImsu1_u znLX`S-{VbhjN;9d|ET&ln@w|HdN)bamNSK8-F>B)#;a1c;br0Rvv!zeg|}~B@NzcW z=5ISz@4b8MU)zC)>BZZ$ioRLtJ##AE*>hye4A-xz{h3##Y_`of_md^__mo>_beGvO zWIA27^jWJ@azopC>HB3pAh+=Dr(W z-6#vz{jwnR_IbZmOY^ViS$&^=wVZdC?IrhnZYCi)9-(^=$6hdbmLQ(8O8NBtTQ8m$ zEh<|3+E8VCLU?SyAt(2}e|_g(*z?_Z7aMzM;gX$JjV}{9iV}>rv+7Beu2$P~gki1p z{n@J0Gu`f0G_K9IT<^(LcR^8SPVr+;{bQ!5?@g6GV|8zpqT7jQQM}$9@l)NpgVsDe zC)AeX@n5>a&wRtyXuXRg_PH9mYo z$5fAdQ%gVVR_x?%+48r9OZ(2T;knC{rgRy2@vaarT9m%R`PyYc(y4?Z5xeI|rCGVSw84taM`b=I~k(e)NT z<^SHFL(P5&YH zeILhDMF9>!1;dm@9*r7O=Nobj<091B{`?C08g+O1xjT}{$|@FLY?trewQJh?Y4hIu z9aZvY{TKYN`s14?|HS`&`N*%H`6XoDzooXd)t~Nm>ikzeb$hw|oP+E^uP*O!Sw6?o z_V+WFY5a5SzTVQkGirm#mlP#D;?I1}<^U zo^FfvQHugTRNRbvP_g*Ko8LM9(!J-uZRjhy^(M|N>o?!0>L5nr1Wk*CrA=;3TgtmH z7JgTj={2;Qbx0vqIM8axQAvK6tCqjJ`fnfnvQhq_F#D6NP)knx>yE-FXP>{_GkwbL zsaxhxFxeeZ@h2-hQ~OPCbJB?&9@5s;iJ|%q?giyVf=tT}cQ#&*V!Eu~=r1;nyLESx zh0anj@s>54_cm|#6rS_!oKsW6`lVl1*WQ2EZT5?ouT8aSRqlpeZ{`RqDko0z6ZPuo zH1y(5ubsT%M9H>=b=Uo${Qk0J%GEC)YxEB*HJ9$5A1E`G;j7=QWlA>~6Mj3cihQ$* zL(|u9$_h7mn*+1GLoT-5{r}5ydav|DEmbELE5;QYLkk118D#Z*7V6DyG85dv!ThO! z|EOe%xzJvP(~~PLGT%#A_N=Z5cy%J@NYj>H>6P#A#kH=gP9j@7_-HPsy?TeUX`)=93N>P+9 zJy6cg%lFOa+|sr z&7u7;Q`OAuRG!uR*t7DWCVo z0UajkT3g1ZOY_tU9+rmL@Otq4s8Ws!KAd>2tz&~+3s2?xrr0^xgx}|1aCdl|`|JFK zpvA4h4d)uI@{@(G^`G;zv;X-nWVY%OjYkdqUN3iaFfg)Ol#3g9{d{onHe)_IjJz=T8>1FQ1?9rZd@XN&~CTqeYjD95T8h|FNE# zF1E&Bx#+ujO4GKB+8r`^m-u*n6w{V?S6Kz#u{yqFM~1pWN>#Gds!mRs1#MhRGqT<- zQGNe7UBLSw_ne1{e%tjJ*nJYD9nZ@C`n1xE zT-RZ%mvz;#4DQGU2ScP>r@LA(L@>9wRI+g7JBX=24^9c>vao7D&9Hs5LD2S&oDN=o zkJ{}U0-ic#Z7?#J%(OrJC?n%RT?YMwoC+r$c0_I|-6=>Fo^t$qtRZ2aUSCHA^qyv`Q*$~fZgPKIy%8m%km zI7=^AjXEH6ukt~!ub7+S8}}VeSv;F~f|#qAH|5yW*39wGQ)-&@g?tg9ogjOvYMOk`1~vF;DWA4bEo#7`P^_Nd&BcGE4QbD z7B_frI5|X!clL3IuSyFR;Fx?UNKs&^>g94@RlX!;slYgf;x~oo=Y_G<%Ix)awUyP3 zHFJH>uqb%u%nV*r=8hdx{Hqr)W|=2YSIVn&BdhyjOUydZJrUgP4jYKmZHksQA?N-nG>EqcwzhF&b+(I^0l`Q{nZsT zZn)pOA)2vy;)kihvf+Z9HTRShnxgxgLKm}0soz`t)qJm;wxjger6`RGY zEzBjZeF7?{~uIMvsqcKu;gjZnx)Kvw|QiPjTDbv zow?+3^ve>zV}>WKQkGrd)Utb4_rCD$Y8i)x>MAy`t|TUL?b+4waQgH5j-BT>$r>!s zSY)f#V6f#%q4Vu3rc}Sg<*J=;{+mdz`Qj8-BeLP(7s(?DiECW8*ow~d6X`em9USAw z%ww4SyE}W%TjsRhHOsH<)pj=9a%-odq&q5jX$Pcz{yQe{Y5 z7VZ{WcAzEQDL`zxhpLWz&QnHb&yLO47DQ>?b1GAmTdY!IF6H!1?CRP-oOZEa^50F+ zVBuS6BgCrwS>T|G$X=bIwT6>)i(-9$36y@UcwQs)QPOL}8pZp{&lMd^?g_PRc()-l zK=8Fo!R9MDw{}ZA-k2!b@N%t+(od#hqZM0f-RGURw|n_fI8CQ_&PSaUXPY?pmVPVu ziBFqZcuv^p#|ln$)`{GWOK%jIZtUd{$?0^Ci)2+?R8cLM(KUrvk9pM=!A7w?0Tm|_ zd5XSW-)vS=(z+t!>5&P!E~ietv5YM5NXRt!Tz+lt@tAbY2Mbh|KDK&kd+=Z2*9RLE zERyFwnQ(jU?E4>g z)*j!qL+;dJ*9S*eRM^x#KegzDWv}Nh-Ua>B?lwrd>^J&zQhJTf-6`!2H_k=~)UREh za6_VjcebPgb7FeSgrwB431{yHJS>db+#r>=^ws4@x4-HnJ8Lc5^iW3df!^06jl~B|2-k)_RU+m;j>>)T^qPUc+HeT?rUc*%wAJ&>gxD2B1`s#sA5r= z?~+G_aZ!96ecFTS$3z+Oi#gYR46iPI-7rf#=+*1~__iI{j}dMAT=@RvyW|Ci-Y za$kRX@wdoV-HYxFlND-ne{8S)v8Vr@v#yCpd8J~n-K+Qa4!_zNrPN^b=@4sV^8NPv z?X}SXX7c6Vf4`_s<(jzf@Novm!|#7TuB@+FZ_gwc_E<~I{dLjz+sZ|Py?K5gWmB(J z*6(?7F&Cq z|EVisl&oXGzoMB-`*m7jB)2(tr$k(0NR^C;^cII8UjgA_sklJ%8WGXyJOUdlp1ht~ zuKnyv!XEvv5*?Cv7Wf$YoI2wf#Go9vt=@TqfMJRK-<0;zd<{#E_)#aRc^}crYk5{U*mdr`c zn6xu+b*%HITaO-ONVK?W=ad=OY;j%oCMDEC;_AD{wq|v|1Wrte{p?-V*y5XgV(GCb zdci!;T*Y>OQMj=&YqPbcYQj`K%@dm4TVK6CJUw2=8#_N~YG1j5hGk@DJJ+@yE- z$()|Hqd#Za=ix4W$gJIG`?O`Z7*|88?ZpWjd!%mtt(Ca-#;)~bQ@ioh-RvJUmL8b4uYKoYA@A7! zfW3lVPe;Fft=6-8H~PpfW#0BeP0Kv^*o@VM zVNIp7r_RS(MM?Y*B<4( zYuEIGeDwmOeH?-gZ-2FUhpS}I*~&|6Ojq#Mn8s}V(RpoA{_Q2Dd!86AY@Bp_s}LV! zh4GWZ?8`0rf18rs#MiosWW|0wc>m*$jqJx(`Es6%eZGF`676v2gjLs^9)_}u+y339 zwX|^EE|CSoZw}>&Pr8(PboY6a^z!5J7ay#6At>hSThHozr4H)s1VDpWfcKc}v;hj1#gl+X@rX=4>jQv%I4)ec|($xo>wBp6N?VJH@3h zv+7pwUi%ckxViHUrk-3{5|d#n+C5uGcICkWx8L`8B8A?b37sY1ZNE8qLwxM9QE}s@1!f~_qC2@c21wgHl=4F`!^By@+}wcu+G)*;fYS;igjto z{_yD8VsCNAKg(_&dUh(oyy{iw!$ak*QB`ewDntauzOXEfR^XXyx_9GZ6K)IVeed#G z%u-W-eyfOHG<}xmb%wm--MPkl?wx;Nuxi?RDb?Nl+|Cbkt$(zNcDtl!xqrFXU*;yh zG*C&gR`Kt$+y1Rh=VrA(HG9PzBD`C|;%+?0#no~Zd$o$UZJSqA-S+ml{83|fy+A(3 zSlgM_UjnbqZ?9_JVshf8dEV}9l|642`EDDBPU=c%|5TkQ8-@9*i@46!`n>OaodF{7rNtV~GG}8#S zKYP`ewN+R?t-pFheqwa{g%?-$O_^u*EA?7?;;G4vj7M#Y6gDPoH@I>+KKJSUY~}}R z{$4(>d8#Mk(CkM%GCXbP1@flwZ=Kxv!~E9K*aiPqi6+iz-(i2RcIxhVRspwffAdtn zvwG&&O5dLHDG{+rKAC&AJQbO#`E1wMXzj)2-env3q<8&!_gJVc!K}fTUvcUs{*MBj zbK_RGMJJ2zotCw2$GnVerafMV7d^bSt1W=_$0iele(^csM>A$g-rcbye)qQn>*P*K zSiTXHodQnsnp!7*o;rjaBOCK#3TX4_WxO)0~?_;Tj^-c`>nnAp^Y7xm;t=u4M8F&1= z@X7-3{n>Y~bj({9ox`TT(>^kfCHe5x4$}|v?^i2ialLwLBCz~Xb7yl#EpBBp` zX!~|OF=M!OHf+|nz03Ekx_d>br*py`le*nz8+{}_7hmN`eIKiHRCQV?Smh-juCEQ;IbZbdfn}j_7Qr@ZQa4U>y*K0BuhHh?@#|Ss#Ot?m zEN2q7nF%v7ZWc<`5IU&1O7xRox7$DclAM^}vl|!8edfRIjNi}wr5|>md?Un^quMj! zT)e5yiQOfezq_Abu(GtyaXE|CStXs^aE*EaWxx7p_0wialeBKVKNr1vV)>RImdU@4 z@ufMPm@)gzp-nTRWe#__2nvTyIO4ngv~9ZC&nHEvYkKy3PwL7pR>*yj%oOoBe&-Hf zW4_t_UWG@VtN&-$ezW)qmhm>wC>nUY&BDR}wtv^i5Ol6CNEESu*T@jGrADkI*n71bB+OLQ2b~JCFxjD~bMgF~2 zi@zV6D^gVC#j8|z{br(6`L#pmrpnpL{!H0ha#m%NNadd1eka3qUq7TSd=UJj;fk=% zSN{kv%d;XrMIStG_%AWJP?KL$WpwU@sFS_i*CSg})Qnu2l&`8x6+AIHHtCdKM1qL$ zMDrvO;murj76;QMo*&}Rx^pm|ySiDw>!d{5(GMK;X2*EeCwgcz9+}r`&3KyoX?ySz zcj<*oB>NK0`O=EbYmBYTJ(*|MGF;wSI*h_TdC!V(BuDzz z&)k>0b5rKe*Xo4Rewv1w502HlS;)O@Z7waV5jv2-d_Qq=s1tX^Elte_H_m+6!eiH- z%aOQ5Do$kHb?&qni8Ma;B4Z1UIBJ~f`Psb~`U>3MkJ5#GpLqg(^)b!#80ybeE6 z=KnZH)%3$Ik9(6hRXMBf;i^j1m|1!;ydo=a(-}dvIa8Nk-Y`KxYUfsAg_@?~P2My3 znwo;#R_r!gw1$J5W!IX|UyrI!Vb7eo`P{_m#>!WOicW~dFEO9GVDZy#k289Kn;(0g zpCnT0%c|rhDD(dV+cXx*ZGO-5o7~immI_DSYgnR{ZyQ%PbR$)D6BUs&!tss8fiY}fc7x4s-m59rvp$!_)R_=u@10v*$2nXBieip6s2oSGq@ z$97pmWxAuu0m}n(KA&M)_3k0Z9~S!s9cLyxuQ>LgaHedkX;5H_X|dt!&Y&WF#*&N& zXLoZfXl(VppvOAzNQ9R8*VX*pRTEzF@9I_()^*_8eauxvJfXSeczfu9LUXwqtrbrn z&;011xuR&dfk@ztiRs5~EDgLG>Ns)2;*3p=t;T{!?pFKzq{fTaNwT(2eqQu)u}t_u zwdjH)lcM%%@wwZs{h?fG*rl~dbYAMzH_V;i71lm<(RlqS$e-izj@dgVGik6fwl6-J z*3`IV?v=+cs#-Mn&s<_A#1g@JgO|T?9oGlH57AAp?W{axK4+JGl4_D*JyY)TV0F~O zgbx}^QtVP+`ZYbM5SXKEwes(t&5QaYI?_~%Pe1z?!Q>=%YF+ncmVXs5J00IKb{zA2 zD^e`H}#M26tbz{yTriEBybY z-mML5Hs9FisO6}AYU8?~o3R_)wGL#>UXW4uBgN&=+Q5)0ubnt06fBQkoAmg<>8h51 z-sgKw{8&3#r`RMO`LIDk?uLFs(Sb)PWv{PAZ|BYOYFYeI!b!5DDC);1VX1ot>t;6J z|EBQpR-<%4NK2KQjESql7Li5$I?uG%&$=AEgl)o7;ob|!uByt`1iraAXQ|_=d!p^` z%OY-P2;Q>QKUw+5L`$KYRbTvwNT&GFePQa(8r8j<8K)e`{N7iQm?;#!$ya&t*Vp~K zl;*q5EOFuBd!1l<>tp)+=_{0SS1>n9f0%l7cRyP|qM}IXp5D|?v)6x2@7UM)B;&p0 zWJ{NaQCUW-dCwax*zUBgW{QT^sdbSxns=A%`TtjC<*XTBw2h`^CulBkc^Uge`>dwS zai1pL9~C<}g%AEsOm)Am@L=_!h6x3y-p@}6VSL9rb$>Ir$I&T~4n~vqUpV_^m0*0& zi+v6Szy4G--QPI*aS?Bw_gOXGl5;;zgJ;&Py0+fKs?tVr-eMjlcNUImZ;uO_w6INj z82LRhahm*cAwTm4HU3pn()HI4^v@Smt>D=jy+)!XJV@Hfvp>T(#k)w*w03QMn8+UK ztO@4bS39HL=U)Ax)ub-C!DC~I{w3X9<33%3_c|#Nf6l31-NAmvL!eyn$^9F8l6!kx z?lQBf@wA@f``&I8)vL#-#(CGvZL^i<_6ZZU`;;BF?fieP;^}rRrrOVaHrwii&aL5a zJJ@5(@4sU8@jK4-?RPnz{p)zryrpXE4AH|s6{fK*zNItss+5il6JOcYi3UsBwWT<8 z4T?2Z-i|t9#C++*PSqP}GuGAVc9p8^={2>Q*t|ESX133pDU92*axA2To;e<@eSGrS z4BJ#QRdI%ScXm}DS-QjS{EG){lP)s8|7m=V(M0FhME~p$LUXgtq%NON5O_Uv--2V0 zt{r^#`t0eoJzpDScT8P-LFb8*$)4tV{`vWN_wL2)|9kY?*OxaJpZ%J@y{7oD@t^Bw zcgr7~e_KBP|Aw8V)xW>ad&(-H+VSe4vB1V7j}9>%Y;#Gt`B290@|5_=e`n9mnjmpH zZKmqUoD&ny1hY!4-oNtA`lvhIw>stGIy@F1{$QMZQ{Cwh`Cds(4ycv%c9Tk>WsfE7K}SnT^ge{$_1Ud^uu^<=nVN!A0t@W zuB~nIUaPM6bkh7E)$=c`{nlr(r+s^2q#2s&JICDOxIau9l&*#J z7uQd?u&l&$ehSZIVU_MMM{E7lY>r#Sj^7enXQ1?P;e}hgmLAtu{reMq#HD9V3MK?LY>U?2(=Pgrku7?Tyx1cq?MDw{VVfft+b%5<_j?L%9q=$|;JPxc@C&!A=(z^oS)7?oR@@wa9(>{O zo|VfX_Dbk|t#s4tpJw|Q%0ni*d!$cUyJu;#&co{W&U2ha_Vz5w@r$v}zFx+@DrIBM zFR|Ux(`DY&-zZ+Y?@597I=0#K^erW%cCem)-{!_8ZK|*Q!YTd6217w-WBrMp?|c24 z6;?0&tZfsS>0s7={^G2P{>EFq3g6jeUX?#++iAWr`+3a9eMWNYAN*Ij*7B`6F4?(F z=~|5HHYb-9Up=3TGqloYi})U$dv?E4mSII(vKVJ=NssNR`K38|@vPtNJ4;1Vs@`w? zrFCM8yJ6*dtrZ7;y;yp6_a3f8OuwsEZx3|zdTy@F9;KrZ8?^NyUs-FVy8buS@MBkt zr}hQ?7WJ|Vzj5hW%B$p8H_vYnF)LiF-V%J`g0u7ABXT~BnMvZV2Vz^MBm`zz>X3;$*YWUypbC^!~j`xK(aam-odrg}Mu;X(_&!nvy5l zHcjQ!qx_j0{TiRU{`w{MeEYifeS5lp7VZ9JG9 ztF7Ldnf+BKu4Uu?#QPd95@(hjTHNCCdC#H63;)imzA78MZpxR?_(d@@jOQ=8Zj%}^ z=j|7UrwZ0eTLfI9uV|?`)o<%G{IXp+t-Qtb@090-xkj^6TMMpq@7?S)!$4ruS)u2X z!ngNkPBfjXcsXzJu|S>b4O3-~-PybS=f%e+maFQ|eTtbole63V`mzOq%V)eV`yX>7 zSjMPi+O@3Tx;2)PNB($4DoibP6x9#3zpVP$_O&C|&7?P4I-;s)BByo5uY33?-0RpU zN8hJ&!ZU-Dmaa@tWZlT#{B1S2ndQ9`$!9l}x4yCPOX@AUT9>KxSo`M23m>=MQxlAu zTw8CZDRC`GQ}WGr#_Ln-UZ)+>*PYeN9n5pEw*9!q+b!?Jg67>@W3e)CGDBC_cSTFD z@F>l@o==^9eG5%o<$ZkRmuF9H_|G4_y*VzpZu?$;z3S3{=v{wXg1_!y zU&8ZuiTE->bALPk!x9A(Hhf&Rd&BL>;z_S`?&+@V;+njBPu;?^hLaS(Mfh)4p6euF zwny{t@xA|UxV0ykMcjS%Dd5=bq_0H>KXp%)&NbwE*k8&kxidHPbI`{Zu~$#dznIIo zG2!l10h3Oj?@H$vyo#N zxBU6~U49u}(-e=z{bsO#_dWB)tgoySyCpR&`VUt%B{TQI}&pGLV0jwShB%sFXu%^JeIvQImKG?Z1%P5d&+7j8dP07-d?-F zM<*xp$KFHp^3>HVdsnVJ-!%Q>mD4S3(cBs_i^>z1Dl*2*DL>=p&eL%2^#sRDa~}52 zZjiXdz5HwIWvgF_lDxKalNk`254S6EgmX z#GjN-Qd4t!^y2Q%X@`X3uUHL#H%(>5GhY?=A_ z_~c*jUM97kn(}kEeOYGx-M>eIcPVmTxGya|q2~01B^p1PW*LjJ&1J}$!P?KIXjdO$ z*Ep%+m#4|Q>+g2%j}s7R%fI@t{`$q+rC%2G38~ctx#yQGzq@kr|3hyxnEk%pi<$H3 zn2~VQ>&>f`=DoT7|J16z&$tU*rd8`-&@#$d>bIg)R;Q`JVofg>z2_Yfqo0yx_aH=i%LuXle-u80IhgbU9iyq!oZ4?Rrst~>2caMq6?X3*f+b3)j^v(zh%NF#`2>JSV zU9i#a*{N^UUj4S+wdIId;M&Itc}(4 z4TK_netP;|3*A#ET3)&&((~2CIhEB9ne&%=ZoQ>HyLGZl-b~ZFrv{g|MqZC;i;bCG zy7c4pnLoEiW-T=+y0UJ5%>v%{ijNuMww$#{s92I?FSYV-q4(vBS)SkjFErdg>+asq zJ2xqQn6_o6!Rd{9k&o}3yrrU^(amXiYUjJF@9(PWs-52Cw&T9TyX^L!hu3HSXP)Dy z7MPlsQe0A$nwX0iLIDkzfQC>^j7{K|7#SI2S;%Av8iFA>uyQmea;3iCUE0}LiP1c2QIBkJ7REJXuM{7H#D-cuCkQ-|MT@8?^-m)@R>pIf^vynXRpCy{G!mN(DX6Bzb3cb7!cl^qpdC7#d7<#+-^+(D)D)Lq z%4zK9|8aBXjo=y6MDHE{EB|44ztxHQIsZFvys@0V^;)n&!k3?{GqjE6o9`b#lct$l z=jANI)>F_m&uZH7zEjDX3qM_cwLtCRL2V94bt7d@wxX@Vg)Emgd9iJ-ueH!xv()F# z{yFde@cBnCHr@S2rrwiZ>s$Q!>$le13&k^)9G)h<_8FV_)GEUEWdq_PTE--)tFxCuF4z#$@NxDrTL?M zLBTiX{(t)BPx$=OTc1VE%nwTR>h^0ntyu8mb>!Xkvv~Jp%=&NiS8p-LZ~YEau2~LC z!Y0=BE}b)TO6l)>&)U|De19$pTRcwPJ29+k^1l!!?XCCY&)wedcO`OSS-7Kb;IF@? z|3W4=tBHS-@cpUCs$0SRJE#;JHE@Wd8sTGP+Gq*)pqlysV}~S#NAhOovZ)td4F2h!ME|UQ<|q{o!7{$ zHnWm;U&sDkv@mJdRiea_6{`sk3 z=e_PvyC+YrRr%-_|H^gQw=;F-YpxwwVZ*U^7U$nddTt&5MmN)sX-Z2!w#l^G_N731 zGuvc|`Sa%2mV7(w_k2N}iGb!A8SU1&pRIiK1oSGt-@G|F{r%g0)t|q8dUG;KKIIeY4=?z~+pE2CR_Mb08DUG}8-XrH=Q8CSkKP%Kf*wlzDQxMzkFlFhxEuJl2>;(_4{@;!G zXZoAl*{yX(Go!y})+#zbqT$bs3-<@sUaBGdYcDAQ_&qTp*MVeeX##dU* zzid%S>(TxDyLnQuitDZ?c8op;Z?1X&C!|a9+@!Bl6)u_W-*q&($8XwxzqbODu~C)X0U+zZ`q*Bvr1fOF%L18bM*&a|z$XW7V?a(8A!nq_|ag%77A z%_H4@6-i#+bUXiLqGO_IK!9__O9i;z5{_^Z*<=3M#SEeSW>&rh1*B7DPAqEaPN zQtjmD8_!HODGP4cCinEp^7{fmTh?A>DsUEHSv>99<>Zz?2eqY48;bnaH#mMc__2G* zN-u`LKN20}D=&!qO7C0LdqrjIO(rY1$wjx%$xW_0v}1PFJ?*3=y3Qf?caQNp%;9TP z|K&aBRyg~ny7Wuw`)}{j6n^z}&C|p4+q0(lJ3dwAdU;Lw*Tc%>^~Rw~XI8hY-?YR; ztL&(q)8f8K_colH@|%gdF|ys|klO6)=Ps9N-?)-~RNrl4&5;10R9 zQD%olwyw|1Sm3eR@70-AaREVzk6jLYme#tWxv(|$mA%o9su*uWyXLF|(Xy-Swig`q z`@(F?(mf^bsch!_^Xw~{ZEcsVHO>iIrobD%tgv&%4)Yl~*WNq*Ui08^OX1nn8EmxbHyLAc4}`3LACl^0opC%< zQ`C3k(j}*r&L3J_x^>&ppPaH=kBfK32R(irsuB6-|I@Q8bG+-tf0jH}W&T|fxZ~XM zbY1^S&%jSv(|)m-9)5MFLW*;NOXmBvOD84XT$)j~XuE#dAC1*C91&Zec}V^SeYTi({(2*7MIt zB>v#}n!?;7!2G&(Th+bqx);{=xg3&9ea^Exv~>En6tAtJrs{V?w*`0SY+6`+>3<%3 zk}rRmv-R=q#nata%V}@tl03L8@~rahy_&BkL`SA`riOZlo$j*#=G*Xs@!DK|1M>oh zf77n#%Ff>XCA@9g#8a1AVl{h>{@JxYe^%OFddQ8#)%;1}6~@eeQ#seh?va`$yjnQ_ zYf+HyZC<9Mi~7q=1qxNq|41y)eYr*Kz+%m_1`7JVl~<>(aXDu!u2PXH9vWvC?P$sQ z$?yE!(`i%xJzV2=(8pC)eETx4T|KjB3u|As+HiMm!BW8wQ=fVpExUeyVq6dF-RTo2 z`MFr05!fe@b-Yb^=IM!x&EA}l57T4&ZxI>BHlb)%H-oe&OW4W_B9XnfcWpKcJ=VB= z_1&xrzx>qa@42GA`rcP$mU{a#z00a?4t+ZHlwHxyJ5nuPN@vp_zwMqoOW=Lk#^CD7 zZSrz)-4KO zc@|yIdbL1jipRFcUN>~|jDE))6q-C|@h9fIv6(pw%*S^>2ti#H!r)bYxqQu)kb&Xj9V4E_WYEM65be|t6i*=Z@aB%5tr0f z_QShA7n{GC@hJUz!)k*Y$9FE<_U(D1se6FH#SIN%^FQ5rlD3yq+Ab}$qPKFw;`fEs zoV7jNCw5yNa?j3AKBckrl^X-=rH5tDw%<6;_0oG|(xgK>RD4Zc9i116zhqlFSC&uY zmYMFcOUDyi*Umn%y64ubx{%dxcrUz|5_$hPgV_SZ>|^?tBDu#Ek4>AtMQl%anB|2> zOOy`pn&@0IJ0M#&TEnkA&i?$}4V^dQdg?y)ocP{xqUWHU&*nvDW%sVD7+y8hd>|q< zdDD)!CX3l@b3f0R!u}v^%UPT351IxOw;VLp(sXt=OIK$4t^PpeLD-aJzeAQreq}Qq zV#J~R0;`}|C#Hm^UzT=mwD}4$8B@IeRT{rz7lzC z<;0l&OI%S;IJ&Pcx$GH}dvDI!wmY)PE-P$y>}r0!p}*5`(dm~O-xN(semk5MNHbY~ z;7;i7&x`sNooKaR!s*GCDi=*ia zM-7d28~u)cF`Rm*dYXzRflYccox+SkIp~6*p zAx|<#qu6%W%MS#(O9Gxb9{qHxxBQgKJmc>N|2$1#ja4|C>rrPC`SEDuJ=qNx7OpQ~ z=#o#f`FN%)OT~K0<7;Jy|HWS9`R~&$SofmOh(o5T_)gHy9MkBfb8e?8M@(ANps^@A z@BItW?z1wHk(aK!&wAd2@?-q@Yp)_(ED>?B5#_iddtlx=p(epKD8;DsA1jjaBlImJ5~wv)_;=w z{$c6tk8{#iUo>!uxaulBo2$t+Rc7i#4)FsC9L)C9PF3)VGi~7VylCc`Dzzlhx2^j0 z?(goK`DIi&)6SiZyI6Hf@Z8>am!>8*DXjeG_Che@jfszxI>)7ejng)Fq(E&JB9|NN94eQKU=EFWj&@9=Qmz;XM>$=v2!i~3skZj9!5bxh*JoHdeL zvhAm_HqGnV<~U)Fh*hTS`T&t>+54w?T$(KH>a;dfufOHgms1+%yB@zf_O4>?jYVaR z<^1mrpKkXt+g34s$*7&bu-#0 zzDkbdo9^K;C!Kj|)(Y#>9~owSGRxCmfBG|{^vqYxUwTb{{J!bVz^5;Ac~RoUbc>rI zb0Z@7!nR)enI=5#T~6ND_toE`R|m3(%t zYaEi;CAgzkTzP%Pe`kl_e!I;Vcn&2PmWX03zjgrAIN=wdAe_b z)^b-%LnY7umO^W;ggi*Ej54sW6=Mr%nB%x4M`m9_Mr(O)U(oNLXO~(Ye-W}$YUiFn zlS_^Jo5B;SuBg5}chS21;HA49rgm0E{S&Mg6kauPbp4|7Xo6^C599LJ^KL$r{PXV4 zhh)8=QeTaWvJX8%Yb_enoYD&3Jxsi+QNCc>q4kw_B^X>IeCwt;37?ytcGg3(sWf|c z6i3{Zr_0MDBMn*CZ{VL9+E%_O25xk-7U+~Kb`-DYO3pl+xG%YM97}#w(Q}AC%rW z_e%>pxrDYKR$UpZ^$+FxLjU}(`O9{}$ne0*<9~nkE-kZt{JFMDvGYU!xqsXy z+jdRBGHwMLjRKEbnOT~_N3)EuEC@0Jjc^ejw~CGImvJw;_xzyUFLskJkMbIVPyPPT z+&J~f-KSNl-bRel27et2H6}eUR8d_Q_WQN$MEBH`u$1!i8E$P18zbgUO^=C}ImvIm z@x)XYg_#_?}^?qLkkG#kJZts#)Gw(i@ z*GtKie=3yPW4->a(%p9-Z+HK{x%%+ZSkMTTE9iKp|FwU_-?+S5C;nb6alzu_;UDf! zZ};9fLt)FE|34RqtF{{bwtq1BgWbFRmN8D*f;Bhn^K|96ZND$8xAl^@!7?93mi_U3 z)9)QV)qD57PhiLufAPwGp|}FpPV;xvTar_34*9?@aN2`fzDLW&Xc{fbJf>SAV5rW_`c4 z>M!>U{x`q=?fUamFil{MNZ$WdroT9sW%>3b{{N&Prah&s?7!H)35kYY4;RNy`Kn>`IYs3cXxY#*?qs4tKw^yYD+$u7SaFR~}87Qo+=EukOfZ0k_>( zCbs{)?NRrSG5(PIp+hZSlY07>@$~V=AH1~3@S^t{4_Av4*@w!TB^1P6pMA`$tt#6w zh1g&w7M3(Cli_e??;1t#IP};!jc|z@1hVAydQT#K$U8-a2OyAP<(P#P26FWD_{GT#0 z>aAvQR8K4K)Tx`^wKnALTqILDGkn9PACfHWDM`*Vgyt|;Go}30sGp#3v2o8gjng@E zj|n;+KY2sY&ARV(o!x@cz?Mrt4_#mJ<9ofehC#7QqDl4w<;{^1N*h)?CEO|zX(&?k znEWhJS3)^4fuCLKEbF(N*Oh^XD~dby1>V)aNVy`+iBAv~JB# zjP$+qZSO>G!LOw=4KA$qxxYbOaLo~?hu@cat&%ztTp-n1{@-}{qmvBh`8K38a(+zp zKc9MRx=>2FfRX>6$4a@Id}^+-C{FBj2{IGPHP^9 zdg!I+V-4+ICE@w&HYxIm3FKNnFHBkG7W1Anc&>r^B@L@d^XnaiBNs-^I$5>$;JcoQ zTXodttmWm&{L&J3JL|;GxWL4qmrT)K?Dd?7jSj5%t~YO%VQ6vZD%n|`Q&-%+nKp|{ z>0P|JS=6wn9O$mKvC4JLT&Ba#a%B@OPpJlR z)fL{l^#0=<2eBgx=|U1|tRg9$7JIi|xybOjVXJw`^tIQIHCzzb!5h&O=pz#{=>UJC zEkg#^q(}*IO&tvhPpvL#iv)#aw@pj8vro0z*%*6RVEzJG0rx4}{1|@NzvR3iabk6N zHnUhCgXN+M&AqY4X}r6OwpJM3T<)NBk!$B7XK7p3E)Ic%PMmVzr8)fF>}UEYOis+z zS;E6F;Whg{gS1IBb4G;z3Ffuerz>|mpFR_PPW0ZX*BT-`C0BzB6tm~84rpI^V`}if z;D(;q^x5CVcy4j_c_}GJ2VXH1?$NkyAP$}x+%2%DDcV*X=wYtD)&EqVKAYk);(?qr2K zS=|oTKkSuXxu-qu#>M5Ob}fGQ0)shR%nSC;<~VBh{dJkdUWITs)y*qED~0G~EV17d z<~F}nN&nit?p2e%Af^YObf^%I>}kS**@2o5l2m?ZKma3(}&69&U?rvoW}%dFl!Ug}bY~_qhemJO4^LqKl<*)p9$-1@lulEZ)Am zs@|rPP%!0HRmAePb^guMBsf;K?@-ig(DV2glHI&s``uDo3EQwDH%md$vy8##BUf|I zpVK5FJ?Yr=nco7glr*SEW-8s>>7gD}wy3Azyfs_LmU$K&+y2ek?s9Uj^GvCnTbT|u z1r1VHs&5Ii-nBm9y=L1NhMO%VyH9WZ$#lx`eSBuyjqNuJoKwrYI64~Mi5|Pw^xp4h(Bk@oH|5O2 zxxdM#zY%_N-8q=|!iA{6(lhm0`ya8n9z3+B(_PqMzWeKIn#Jqoe0lG>w;ui?cXp5A z$;FzXPKkW`%_h&6oV-ZV^2t-5l4xe#2MsGvZe%Q6!D{Z_aOB3kI!l(V9URSeE8cfC zpYl6sqvw|_qW+0v|M!?oRYqN*$E_M_VtLo|Yo06on6PmnOHii99?v!A?J9~s>=)K` z>pOhbyW141c_E8wj{4oRT2+C*%j)Xa^!l+xz7=?0b+Je&UCr5P;prt-FWu}#qjLVA z(cSrO?={R?D%*}5-jWi$SAGU?2Rf6LdU+D>||)3Hm->ZEp@ z`b6I3$_C@>n#p17`Fg7UnWaj#b%t}L&AnnFpDrf5EWtZj;Ov@f+jEp;R6n@geRO); z=h_e4hsBPZ+L^b5nK6~&_2CzNDHl`w75^M6)bin}*E9OSv^#`B`KpiIHHT}0iN!pn zOE#?FV7Aq6IIU-OP4{1>MWfE`?R&fyd93mOTh;6Kr>DC|Gwwj6v=JZMMy44nC*JZ^ z-K084lI5k@mSeLVj9>3&(Y)1ltd8yVgU4QL4-`y|d#`iJm)~i@bA?Znrq2?%Ak^`= zM&kMQhVxhcbnN4gO;OV@&5xSFZlX5^TCzmz^7hv9cy_f z?31f?db*=RURCGX9lpS9hsO!Oqw3FhNcrSUZrf?>u~)Am+q3ILb3#(eM~&$d4tU;P zZRjTND^zvy?s;`58J8~tR|EHa{qSX%%Zfeoj;WsZzLu1=ZrSoVHZK=$V!0@E_v4FC zUN5#!d2?0XG(zh|z@FTE^%9@itNI7xmnz&QO`nlzx8vr@s0S7oy3(!o z=BK^hbn(o}iy<>+v@5x6O^jzdu$wE#?Zj1&EzdmO7_Pl{_fp8VEJpA5Tb#V-**c4U z?J{}mVP&DH`g{^k^44kZU&=>5ZEn5x=l!1ShMFUD8hd#A1%;;+vZsj3{taZeD729K z9$g&ecT}(8`^u+klPXd;*|jS6SV^_C^lqE+xzbNS=)BywS8F~z@4T_xDLqxj`KD#x zo$e=(*5A^&(y`pA-~Cn3wtTt%CDqmJKlMY4{!QCwFBI-=Hf7ck^{VEDPc%#RebN%= z@JSU8W)JsszrDBRrK8EO154(0EfRSaxZUH_7Pp8ko8MV#3b!4+m^XcDWXZ}cxALZB zeiS{pqT6VXQdY*+j);ky&vk{bIA&h0>At3^w>;P2!0CyH6VDt{pMG*i>~zbsE0T?q zcUa^q>&}`uHsS9O5uUbL z(@^qzY}04N~&5@O&0SUZwOWKU8i`I+w=K>A{EW% zirNDryz-%IIWLrMiJQ={QLXbWv8sl1o1a?YoD>``}IKni*<80)E_H5vMX@j zbT7u+Mf@|@v`tR5o78mfncH^*Ggje8W{+1}>qh%)e`^$8lw}uPzy9Ej){NO_H!4Q{ zz4U1D(;F>wez#|KrSUwKW{JGV#thC{4%)KKONeyZzPyFQfnX%!+1JT6bRP%QX zA(C5X9Qm-QM&sMTM^dvDO0+z=O@1y;wXZp!aUxh!Sa$wZ7dN9Pe~m-W$+ITaZ%Xeo zEfiRxKL46Kx7+q@(OYZZMA(Kexb(lfp`u9R%?gH?`Db|7Uk$7^)SS2Tdb7gXqZ?CJ z?L5S~=4G$v_4GNplV*C(nYYqcJ2?KU@4FKcdsmhg&Rf#&V==Gl6qmabyQ!Q?n-k-g z=Ji2u%CCx^E0qoQ+HVy;L*kZU`nHWTw~FrcIF)?e)HbzXMZWH-StlOtdT=yi$wl4M z=fkhO7v0s>VgGslr#RN-kta2*++Ti^sj8X2XL9yy&z&i}j1t?Y)|vd8njLDE@wV(i z(lim)q??s?SLgkBWTu*EJm2|urO*AB#rtpU^^-iF{_2|NpWsCccdWHJoLLZ5&vT8# zu{`&Sn#}Wm3DVE~vn_+-+?^&}mAaj>b3xZnNnPbPTrZyT4xO(sJFu$1~`E|p|ziy(4`}|2= zvh(|0Z=A46mRKyW^+enJUC^o?OQF9FGwxlGoS=2!PlEe@)78E!zpTvEXukG-m-CTL z3h90^2Fsn;!gaGVn0{{w=r;RS)9-$gW%7)SJJNG_tp(ej*qk?QkGl9~-o6%VRYtC} zRdVNe4oqIA`u3>R?gW$mD``pZm=5?J*}A7$jhjWK{969;sdu-Z$c*>qzH-5ib}kt2K93C!e$G`W#)v!tN-bm{G!a;CB35FHOaQX|0z86#8K>+-?hnI=cZi&{<9YhT2y@N!EK_g%M8#jRhrM0ZZT?7QP1_o<3A zuck%{M=lgux7u!!gT{jFs{BcxUfxrgFimswTRx|Shh1JD^|WGjOq_Fc+MI3MPy9dR zxo63%zmmbGx2Ea6t6ZgaSJG|yFRhJn0n6U4^t-tF*C+KQOBF&_EnlxcpRut@rNGZ} znGG|umh6kliQgjpf~K-gJQ^U~bk6S3TK3vUy8fD1*9Awa-;r%`=hmC{u}$Go#KkKw zmF~^TtUrHJ=()}kk^1|0T_b!OQ`YZNF}J+3)c@Uv7tR6BUsN*Ryoi0@=*>1WKxD}k zl|LC~-+bO*Pw>8_om;Zvk%v|Ox{z~avHOCT9Gdf1HO*s|@{UZg!(kH>{1t;-oBy$# z`7>c!-<67&A@@3ZGQPFU-R7|R)xS?}A`X@}0wvgd_AK6-Kf|f5V2<+&7skA%^|rN} zk2`JAQsQ7;wr|Vq>^Y}?*sky^IKT0m3j3DGxiv>_-502?_q=gU%6G#8W4^qAl50x5 zoBy1aId^l}0wso8gHld zEN?izRN7}a&UxDQtpCbSl@A*3tu0#wuT0tQXZKB&nml3lt4EWwv(h%22+wvnTLGjhL=)@dM01F5aY7`hP0pm?ps-DY??}$ zFYDhrWymSot}lOn!cJCs@0)j0FN#fGy>Go5lRmegCTc%pP*|?#GFzqP%R*v|_xqaO zPc1pUOLI?($B*EuXMemGsC|lOERxIT(hE1q<(6c>CKbG`&DDqZqREq&QtxE?r%C89 zJy-6N{4)Q`JeBLuLvqTC*e5fGYQJ*Ooo=&mSz2DTW?kO&G_##Imog|jwbkcW@~Rx) z^31$T&++AzwZfZEt9bvszhu*5He-8}ogX_*i-P_HmoT--E-y}c{^>>L#-B$t_ndS} z6+A!7%sQ#_mgwv&&T(OfIP>_Q%|nAbUQbBqxONQ;NLH{x}{$Um2ml;C-OYK+O#Vr&3j2m__Qr69lw1#;rqSf z;xuLfku$QEifZO}nKOjh+9T%*q|D>zU-?BMJnG)5gd3NVn_mhSdHY@8aZpa8VAhA+ zMXi7L+vb>acpsm&-%2fAujpuxPQxoEp@LHimdmf4=@xwKy6bpduT$wcA!ZHz6vkQ4 zUaR{}y6kmxf&InubM47a9nTEXHLp0T9aA@K^>ynK`M9&$sb!J)B!?rSf4*mx)bh$| zHj8U*mrnmT%gC{Z;k2Rss}&|6*VNB^u6AX@RPI;2JQ+uq%a@CtTH43DVy1e&~ zQ-u$w-8`S*tg|!jN#2>|3nyr>m?iGoBqcX(^7bX0#5lcwF`FHqJWKRXxkt)zuD42$ zrZan*+!H>#&*F8N?jvjMq~JyN&ZY+?4IR%kKPb6%FYph?6Xkm~uX5$>g}Abfrnp}B z_`5uvNiE~2sr31`HZ>Yc&TvW}2+cZpyRi1&*7XHX1D`c-;Px2_~J#;QS*!`Dw~7++;=JNtL44lQKEl#vO0T7S?7~iD|OdjFV8P* zPW(T2b-$Hs?Y8?{?oBuA|MqF~o5P2`e4l<;t7aE3Pj$%3O*Ow?AD2-(WWBw9|Gz(K z{K>g(%PY3AdR?mTQ8o40{3WAj`NqW`=KYy9$9q9=fZdaq)FC}|7ZWN{qpC{S^YonUh1d6eC7AfZq@#M_P<~H zocpi%Y~24Q{@+eK3qtqTLl=bB7eN<< zI{yMK2)*|D(yhO@UuH%vNKOgfs@whFJ;=hPCa?f^c?SPzqoJ79%|Ctzm|LND(;KV zxVF#DnLYdOXXcP)drC_Rr`_ALG&J#l@vapu99x3xPQKND^{M~%;`%s&^LfG_#b;WH z^DeGayXko9eogTA^EFYz+~qs2y^smKbFU)o`?-IqN=L5ho!dPjb;5c{iJSw^-picu z+Y&H2^ysXAzJFeMHg8qj@0lBQAWTZux6wXC&Nx@D=DzmzO@Ytu_I*nEmhniW<=+2u zd)9aUV*ke7-*)oQ&a|?gg5US~%zT`95PI&1d!v+owIN$c6vy+N~Ug343#Tfbd8 zxt4r7S9sDZB%q`3sEYfooGt&Czq?@_k+x?iZ}F+JkH=4+^cAxf4%Yp)M|HD2+my4b zTypeRsaQ+TI&U;@scC1~QuX!I6IblHpHs9YhGS9R-EvuSgUnfxGNV%s8+I4V35hitoVWgd{@$Md3Ey9zUoSU*@6V@x^Y;E! z{CnSe{@(8Tcl)>hzI^ld_wxDqkLB%~?2V${C~E#z`*Zl};x{SDUfyD2w`S^k9at5`JXDz6rEb5Ovb=ez+KGG8 z9!Vtz>Y34Ew=WjG(3?9^l5sy1SJKCoCo^W8)lbvwP0yZ}Ui?`uQba&|(pJ&i46b`` zb+t)MQMl+jeZf_M){QP||%bZ@poZq@S5v3zIK&eqP}bIG#*#{AFy zj7d5_(^KZ@@b6pEZLiwK5VYjkmigwlB?Ubfs#wZ@lMiE9a`uj_H;k^sJnViNa#Db)*w@eT8wptw4 zl~Fg{6v?2A@fH)a$DpOjYNSb28wzOq$n$q|*er?RCOGEGe9{cKwOAvOQl z%p+3EBUNIq1=oImdHEucteFTha>CE;&5k?49_na=-5K;HZ?llQL>} zZl|UwFOia+5ooV?OJLsHsas+%?z5O=#4vfvTEXKp#0rn4UCjC!WPIht-W6XXx0+@d z=)B&&Ptee%TYIgc_0t)5PP}eC?K*$4m}6nzoRfiPV$7uNzg!NTo*Kw%D&qXtB;;%0 z&rLRZx4!vxoesI`zWc=PmHdykZHYbcUMZz2{jkMs>vIQmcKP)jUi0s6&heDUqkYE9 z`piBYdTaW7-`2eSj=K}jN)&A?6*DkWQed92>YCN+)_}C7vwoLdniROCtugRHz)#ap z-fjDjTngd;=XJo$Cur4LiTn+d`eh$vU#hsJw=SypO02}rfat%LS0_8@Y1%jPDL@!uy)I0KTn=$TfJJn^7lELJLiPlVo@{>eQfs8XtJ8L+`*&E zi`RTmw+YgIKS8{T|5-`7-_MpgGB2*RWh)$QSn|Z*Gluuj;|CSFXTw&XPG1vMy7o@P z-t0Lw465fJzBks<-`hLu`;3)4V|Jf8P_pIdxhnT8JICpjj<@clvIQ((Z1P$+aF*2B z`9j{e4h4UcpXj1g=gD%RON$0$lb$(M{D(JMC9$Bea`!Hi^_}x9<=Qz$$ z(w`R5X8G~cu8*SJZ9H64jaR*{m^1Og-qcRXvg4OpTe)-Rh*hj#{@^X&BFb$n~sl^ZQ?CPdoTozBp=heX?eZ_US2k zrgJ?{?~l0Qzjl&`mR zMk)reEx9b9?kV@#sY7z|XUUqZtZL2U_dH%2`&2GD;^V|L@qp-OZ5;t8d7Y&vU$Dr| ziBkQW$>&$S@ahyb7T(@OX@_1R9_@H359=k)o&u`8OfNP1WtV>2aw1UaV9MmbLTQ2< zGdlB&r>~Xye${Nrv(f_Fj{PSYHw#UAlFa((TdbTxv%wGLZ43Q=s-~a0qWUFo;&%7L zQ3ZAiKV925mxqS&9A8m+VR?~gXi(3?5Z;5A4s|x1US>W2uwRH+-m`yKeuVAu$$j2( zy7;=QoP_+Xk6cxXvu6opoUGnr?zH%8_{6f)3#S-OH;tNm{pwD8xs&YAYBrvE)w%xK z$xNq& zlaBo$$Z_}F-COKw&)-{HJpHq0?^kC3i^pfa%eo!DxTiV=Jih`9&PCG8^p1wX9) zcsSLAHU#`r07Ar{rPKKu69=3Eeo3%#=ameQ&Wngz$d9eZHdX_l3(A?si+A> zG04nIYuw7bU~;kDE0YE&C#z%i*XQdmFn7(BXiK>e;_$laLg2>I9cR}pxFUY;{*i}!#XPM& zV#;sYOt?33d9w5?)?B57H`US~9?MhBnC$t$=4_<<;=cjHEAmu(&96nwiuSv3IO5s% zi=Aa_Q@yzi4Kxyp|E)ZxB_aJjulCHUL>9NaxqmlDRcKm;gtw`Mn7LdpZf#Lao*gOS z+p2T^%&9w8EJ;r{{hYLePx`p&fC|;@C;t zCzicRa$v})<*q(9MR~8&saIiMceCcJ8gMog&HWbnF7-s=?;go-`D>R&@lN`#KI80_ z8Jr@!uh+at?FkcS-?CEU-jUh4%T_0?xPIh7u82{#!`Jz9Ed3uJSsR?sxpwxQ75qWm z=askkbj{@zxw_GlO)H}}SYm}#9q;nXom1ZEdcC`)XPf^<=lJwY;9j-t$y}jJ=63yNejkjU zEbnGMYwHoXp!>z9gqI)BM*ryyo6Ml>yujJsb@kEI$19Fre%evRHz#?msN9pKK@M-V zB|2AYsJ-PgIQ}}}Wu^mzeC&}v0Yjsbz*P(MuP^Fw)?{&sO~<>wt4gA{MI}uz4WG)=uXoJXmr1ym8R|#k0d^WlFR$F1#W0?CDM+H!+31ijVBI8gpkKo!xkp|7=Wd!}Zrz zyA8CgtzU`keEMdhsMh+_2W4F)+c#zUpLkXi=)Eesf5YE|wfgpuX29i#xK=BiKVGX?1XctXVlLB z)}DNiJ{+!WSp3~`Vp#Uq!yb3+Qqv!PpCtU8?cIwTYkPn89+L*mZD3(H?QuMTTCf8*TA85{1d47@A)RBYOg+eN2$daj<^wTMrrrs2e* zUgM&<8Nc+y#P63cyS7E{uynNWh3L=Xum5d2C-bgv|0~J)U7rQ5GxXfB{x-H`2_k9x=w=6swsPu&GhRtt3W+%J3kFVU5o2z{I z$mK|8M?3Z6bp8)B{KQ@tuYLY`jcL`q=QG(J=H0rxC34#-%i3ADau)B-a({}WDtxlPlYp}`{=FgAq&b`&0_d!w9#jWMy|I_Z%Q|*E`zd!SA z{ohZ2y8Ad5mz{a+A(7+!OWVjp!fCaoLgn?dY#YsvWSIQCcjwpELY0Ft(-jjm%@XQ2 zFBXkn{!WzfpuxYO={jeh=Usfur^mQS{a0LD?m7D)2ALy=3vG6uG<*NA;q(X3f3iJG zCr+CE<#^-w%j!Q)%@Y3k-Hm5z$h>ziKKDMl|2SVwQQTAY|Fe@So8$tX97{jze0$cX zKP4G^U$5PN(=n^KB*pxX)+FhlTGQ9r^Ll8XT>YG7LDrAh2aL`8d_KOcW~!R>YgSHC31Z;J7|V)CW1?0> z?v06_EaN`)-t$KJi}|;GFD%^?UvcdW9i+3-29(7INRN&Jhxrzh(BL$q^<2A zmio=7|7we}&C+#y=GjbtAG7J+yCW*)P5);9zqe;s)u*lZ_x|~(^>^3g-S_qV@5k=l zJL$9ikvmo2PnueJ?C%Z+Er{zIyfl+pB^t!5xQY{WLtX z;(yiOc$1DRXEpBm9!gm7`uU6RFCS{C3Aar9eV)H6C`e=Te^Xn|_mBViw<||=KREnv z*S0@v{{8y;aK+SlO_9%d>+EIw?j=7z_O8Bs!sLD{lesqn-h9-w)ly!v^|$_X(La2` z8PM!$~Ycu+~% z5uJRrvVOPDd-gvs3Sz7_$xna#^Q~LPqFokMMQN7~ZkSf7AY7<&Uv|ozrs=cF^ZSpy zJb6j4vvSJC$=aWa-Sus6n0@j!Qo0sv);`6o^SF7olEA}vVxGU!D(~KXyt?_&5tT(dpY~IPO^5@jDU%L z7n&!pvDr6?O>VF>!Tu~9d@;Kz0<8mckKbBd#^H0|FT*|ur&dZYh zZTc-+ky)E3ub6V|+!WIQ7Pd8|Az4LUUVf*n>fU~-x@deu_Z!p85M?KAc{P)lt9MT4 z=6ts+s?ED*VX0i~O^%?Xw;2mUPg|X0Em-qB)#89jA{?xE4~(c@@UNpE}?uU zmZ=`C*3Uh8H9U6lOp|@J`QF01@bvVkW#@iQG80<1K=%2Tbq)Pn3NJZFEHd7dp%i7J z(|(Ylw6?oyA>aJi_}bF1Wy_6^S9M3-3dFlJ6A;4Z269cse3JNPPICA@Jh7f zp5I+xmUEZ4_%L|=jaYkaySAxqKKtngM}|MEjY^MyEm7+=sg3xQI89C>A+%+=cV9|b zgM{e&vn`X~bh%8nd-!5)(T3=(Y{`!J%l%OtHy4J-r9EopiRk}a)W5-0kz;0fui~90 zTOVmW-j;M}mlj*d{V#&8Wm%i%-9GR2dr!@BU-r1f^_+zq3%nnE^PjoWicx>^iZ4&! zS04KsS>I7Mx%d3G@8o6r0D zeLeqoecxrkVe+Q!+pKFmm$jA@MyG1D%-?3U-Hm%)zVXv3u<3C#bH(jrGZC>zovhdaX`o6%m0kVcdP~KlGvF!)*S4Nt@&WPH+*vcM&<+Qi-THbuMqUCT;cxM zg)g(W^{KqHc0(^`OiACh-U$`Om4}24HoP-=Xk4eWWWP^>QlQ7{Yrjt{e;KWj^gzW@ zbbDXq2kAnu_G5jYV&CP>O*z#Sp?JVK?9CEmJpn#HhpW-jU)?XRF1^w`uS0Q4L$$2= zm8jO0QmLsbYz&;Mz3Z+=lq~+UWN~imu7+#;SL7euV7Zt5z|&}J#*$W%meU9P)`)Q( z|C*@&zSv||&DVv0G?H2l^iSHk@J!lfwyPmw?~(qW zVTh$r3`^EFXBo@>HxnA1^)`fR>Seb-xWgcA@#p2r!;j3?^@}o@MeQ)MV`bFaThO&` zJNJ8cvHL2$iG^{dcHd6leEs>CP6mVTulE*0^Y?7-uTVL7tp4=GmK$q!&1%|pt$thM zwI`R0rUw6QWIEe@t3sm7pkc+kPtl=jt~;#ml&h`ETJV1I`i1w)882JP7HM(*le?gy z^Z7{$Ph|HWvr_SM6WAwls%tV%mYeI(#?r!kr`xz=`@DXxx6{~Wi~d}HLZWg_kWiNi z%l}Zf^FJp}jB3>^2>i~eeOthG<mwlQSKg+AA}5xx5WeNobusWqbAKhNV)u z&lUCdgiOA)qGqM}l&wA!o|qkNXj1ZE@?GM4$gM&7gB8bY2BRY{cvv014lgY>zq~^E zsm0a2N(jahttP z>seF7c`x=JtoOgn-gU$5frPc1`RSg7X;&p2<}o{lhE<7n9_ayBR|B}G_(z|9dJBch> z@6omJROzN*{f;S8brDtP*L5#?95LbAVWZ3H&h4q+UKaEy%nPs5iDcU`zbWReCC8S6 z+bl;kr?2q+y3s(h`^IY-$&QFFli&N_h~Im+GtKwLX)cAD9h0{1Iuus*|LFvF)q=v} z1BUF+uUzY06nt*IuGPjbB96ZjmPIWza6ho{vfBE)W>F@a{T9VWd^Wgvu5IFjb9bvZ z>T>0sR$cnfM*FJ9d*0lwZiQ3oODBsJiR4vIH-9aYoUzEOBt+1_%izqbHQT2z{={&3 z>gxR}LRtRKf6U*s1@hT^XBA!S@~G?S%I%ITtPY!51SToVo2{Q(>9|tZVZ{r#bz8bD zch>P0^qo{~;M%p~+!Q$<&&@qs(@t>*<@zr+)_gC0($phLaMko<_gw6w`gd^FtzdX( zdAdhpmD>&*&nccOFHJU?xp}E^s2_LC(}!}qnOwQ#|Nh*Rp3UoH&lu^NK4q!*>-VBc zJXcy6-z<8hbJ1fOP;zR5ZOut`t&M-H-z7bs zG_&#U>l?3DxlX?|dxFjUDOVOdM=V`sEvnOd=&F=<|kvl!(aMUpVK(X_1e+!bPrC z*{OVRoY(r~)E&{2KgCX})~@(kIjj9ZcjA}4({hzM?F-JH-dfjZ>A99^=j+!`npEDr z4Ewc`mwoE0h-anu&PFDlUClYo%JY6!XGo=_w8VM7IiD_nnC!`K<0Rl6+myKU@S0-N zzu8--#hL5ODZ1VLLM*pM{(On6@2dMZ8sBO16rYR`&r!c)&(&4_c;ZwE&8q>iCC4ru znR2UYm6<$O$SUcJvma*$8}Aiy*6hvLu{~buqrf}A-8VLT-%<8per)`VkM|B8+vaWk ztRer9w29E=1QTu78(W_-WCS`!UUA@>R$8%tiu@O)O}<=)H;;s@yrIcB>uR{q)00Q- z|Maa{y?ocwyj1_c8-3pvEBudjBq^#;YxIkq#V*YN4CHG0bnGxO~v zKQ0y7`BX|P#<=Q*O5UjzH(#IH{Ml&I44EiH#VsmqIXhQ2%(&dZ`S?cNiq$K3pJvVe zaPqF$#%X6OSUOp3zQUE6rVlM6&tE)x{>5?5lz+f1ZsINqV!u z=C!0RONvOlRrS0V_0xA7@3&o2Ez*~F(c{vIi)X{rm$cM>jO?2juwzm9&l=;P`K=xz zz0BVj+a8t8*unB@eeb=9lgi!O&#ud`(3nvv^m6Vz;cc73pI1*m&E_HW+UnFx1mn3b<7n9j@GIoyMN!{e_raQM9EW7og_uu-krMg>hKS?an zThIH!O?QhT|L>_$miJRnZ*%KR+OxGQXXy{A+0(l|J^CQ$t0`3NkXcfhlbfb@(TL}t zLEEcaCrd>?ub9;}F_ZUu^qG>&I>z}o>RM#iio5=)vYwr1|5G*3)#4!cwS-TqaAL>+hjZa-Uw)8U%uS)ajQh`RR-Tph}SgSIm_^TJOfBX=7D9oAP{cqu;jMO!OuKauRm<*<03pLTy^f2tRS|a@L zDo4!9r@P$!CtjR+{&vg!WfBWNstdJs`8=rMD_PoDY3XxD{N}kD&X9KzkNU6P7rRs~ zcSA1Z(Rvf-&bhfvS$Csuo@#Q{jk3JIe8sn^2CmhL)2A%tx&7v*M%wwbn3AQo-d}cB znTTY5_u<~LD$Cu*Q_t?s>RZR}ueV$fbhIz&&9RkBxL@{3lsx<@9)5lQ0(}jJC(J@Y z`g0qqmQ3|n6*c9F)q@>6Z)`ZZ_zouHi4lsNuuJbjv5?&$Gv`nz=k!|M0Hk+ENAiGEh$ET0Xc2qhlO+A0X zs9}BZlo|V&9;|rcet>ytgr0`}3$ZeTed+2`4yI{%PRcYcxhrh!T%N<_z9etU^<$y2 z3-4|#NI5s}PPzDBM~+>c$}8(c7WiE$-}~xAr1}j3bGLcN^7nk-?Rt8$?xd0_%r+k% zT*!I-v|Q)YvW&^G!B>2Jc5C~kM^0Xns>!rY+~Q#S`Q}%}iyq&)UDC}j_rvvaPL->l_T-|Z1| zDvo1=>583kmg^qfaewY(wqlLvfv4ZT89sb4YkpmVjYP;SHgnO6mdeP>23s9C7BNcb z7+h4^P_j`u!>_CE;A4fA5pm@YkA40b*Us1b-{OD8ye}_QOh4?@)3NO<@?P@uz2Lke zw&(YbS@~ClY3R(D;{H(bwB!sCn>wS)3EGx#wCpB%^_B#O2J(7d*L`tsZ=Rn;dfsfq z+4`%V7>QKAQ_Z((y(gQm7Hw|(=idbbZ?BNxY5(uZR9{a#;gq8JW20tZ7IV$n*N-NZ zdGnmx$un)O*izZ@*{lCId;4pe%lTSzyxo2O%g=?+-iLo|oGJ5NJ*dcgo_|g<)A7oO zw&IKRIz?N{FIV##8r~IYYkd1Du;KTGyT0d{6XiKx6o>eAtty?`vyE@v{Mbg$EUi11 zE6a@TGQJ9UaeCRUt-h}W(yx1OE!Ig~x#SYRV}zIB_sM7FC3!DxY%9+Dm38Xb%G1J= zV?3Mez6VcEZ+>|@u42!BCUsX)r#oy#D;}Qb6YG;~__RPKVM?vPylusY*u%e~-@j&w zJaJMw{O+b72aj*xHoLMQud&{&XXh#YKmV>=tJey&weL{;b46O)b-r#qPdD?gl8WlD zraifJ3q$6dc=&X3&|9OPS81iUVlG}~6MAxMmQh8U(G%8;mSu2f2F`<*d+L&bC9=%3!nee7a{!W_kGj>5U5>sHn_{ND@qC+-9ipqw%1^k6&|M-M-vk z{oG5#E9Ioz_ma@-kFTtJRcY?AknN=X&-XX4K6^1!UhjVXrB@5u;!j<^Kf7Fd>i>zA z-#d&;VAuqK) zZkT?7P2Xwv*Xx;KPOm+x{&1H4SkWw1pKd+%V_Hp{>Dw*ubx)OftUY$z_3|}d;YUB% z=lLi||F`-(llj^0ip;gH1{^nER&oY&)LpsVpqaWoNXju(Dau>NG=1Ytn-I^aB}*?D zRtXFEmnmzsD!kXJGS{kD8PVMOdb8NMNo9}!x*V!}@>EF4&1+NQo>@GLyzKhKb!0f# z#rw~)Fv|O5aMn#jd#>bton7l!Pm^SGu=h zKeP92%B~(BhZqwTMAuA6{9t79kV*OL!H>^g{5bjH;k$oH#b0UyW-mVe=k>wM?LUhD zJpOR@*~O0qMFLxEEyOPf9Tc#0y&$%&H~dX;f!Xhz2?svze)_h$;;GVtCC8TkiK<@t zr^5WK3Wp(w?}u{|2?wRcSAF{aA$}28NbIhanmh6qZSI~Id6T0%T~wkzi@W*xfrKqf z&it@aJTJk^T%a@2Ol@hymJbaUw{@3z&b)F+;<>1wo@?cFIZv-`rJA>1FS+b>m~&Z% z%a;@H*My49Io&^**F*c&d)Lq}+dS@zzvP}~STM=zX+(%eq58fxk3Mo8R4BT|U=kVJ zETyZR7LxLz^`L8K!+-G^FP-BJn7?+hi7PqnTCnVwbJ&d)9f^xox4qaQUMhc9C~MO$ z&WktAGDS-6W%}mCnZG>wa;wO(_m&YYXQy0JvQ1xXx%pK6?4*-RZ^(q??qAUzZ9eDo zTIte_t6Zw)TnIY)QS|`hou;m6*Ycbg0l_21!7JX0zP?j*sPbaS+Z{U6ucLTnte44H zgg-wVXxHngy)kXi887y8QW*lPrXPBlYxcrjko99y(@`#-UF~nLoLdzr`jodUUM%?D zwuz<}M0mfJrq2;Gn-OM{e(Z#vr*H4IrX3H9Qo3&&n5}vhShKHi!+rDa^|w#?>{EVJ zEx~ahh_~+R-h=rc_1>+~n{{o&4&J_p6~+gxR3?=fBsQd-*v zQgd%CkHhq+T~|1tD=^m)H-%>EBfp7G6cc?{8qLt8|@9x=E6rjipcKDUY2DTs0A zWFy|Y>qD~JjdGW6IJKq1*DrvjzQkJll);or!6|kuXO{&34!yiTq<;3?yDw+V@epxZ zYk9aLEH$Qi5}TE5*9;LRjn~H8gY|o&R9E#2C!R^z@y6n$ti)=4?#@ket69`GI&Vw; zXu}_LyNAQDn01Lwo~yQ~dEAUAjLQ3MUgfr#`fF#(Y>aWJ%iX~+JLtCsBkF7+%)Jfldc%tlD z#Hogx#~Cg!*ivGYHq8M7(-#Qo(~oZ7R;{|k3! z!VHH!-!@E=IyHUO%A2?R?Nxr-eHAU8|Lm{H_6tF;Sno~!_Bwc(rmT=g<(`6C*++d7 zEjAtgXXK_b&*S@vV_UiYU1j{Qd;b^DiH@>M{j-^(XSSPc`t2+wqi5ZFS5f4wxxK%( zv;OtpXQY%Ale&%AuEr%N2$;;YP2W1fcwgfD+d{u?Z}r@L@Xftywy?=Rw|XviOzw?5 z>+8zU-z*e*d)uPTS-+}8W1n`i9-bZTRdO=@({_38$v(D|7V|_sy&}g{b!3L$v-{^t zy#-t%&&14oqdOzd{&k7@jS!oC4hFZZzR2ugaXY^~D28dP%l;q#^%}WSMG85ecs$pS z^X-56;P4XFrD?Y=dU2=oi3BOvZ@w*c_0*4>-~y@ z92GovU3}j!yW=wpd{%#JmF{McJl(K{2dH3pO8#jxN z2fbChcCXrGwEs`h%F4Zh&38C{t^ZT|<bGjNd}G?JO3svXIE`Cy50X`@&~)T{rBD$Zs)Med4JtH z|N83hWz}oH2=r(Ma~#ZXzk9EG&7B)>pIcl0SmFFxpjz~IMY|nn((CqqU*jJ#%o)}X zLhFyO_Stag!NLZ`jq_|Sn>?@HoxmiH=CbY^>%Wm`1bW`2lsi-pK|2VJm2ztM=u|<(BJN_ z&bjx-N=MD*zF~}Of4KAcq@t@-N=! zPY<%*8R+GunISq|NM+H&_d%K`7=Pza<(kkN=FD?3@4xfyyxb33B75_ftUsf0GUL>u z_P`oj#5TH5m7EIqaTexr?Vfl^-lBS-BeCY}*t8gJixi~ajUtU5vQ@IMuW%DE-$ ze3J5cG@H}3J{W25Dc|>I(RRM%sdJzHR=TlH<6(w*%op)nQ}?~ox=|&Uc4z9UcKz~G zd}gNtm1||T>YJ@^+GHqcbK~vP1&c54Q#a6I`z}>hys>4vr^2aYZy)zK$YmYee@=dADAY0k|L)t)2V2FqX;s`j zqOnwWwvV{H|NI+|FQ1d%ws3uh%7d0|KC*IGd22)F*N3`$OIIg?&a%ZZ@LTbwR!bCX2Q$&)!&NG zo$OqC;?)(7-wb!pHr3s5^w4^BLs;X<&Evgq+b?sUa@9RK`Q6m!$s6katT5ThUBN9m zN6A*exnRPl4CzH19dt8;m+}4)J}Wb+`0rVJ29Q0u+P%3 zKEGe~TszB9`d8lUcPuhbB3HJFMM(%nABw%8x^`;df`$)UgSgMf_WN`gSk2Gq47}jC z+cDN@;jNXv=h%Camj%R6Tr%~@yZrqs27*qWoawI)39wkav_EOk^YvZ{V}P26-1R?q z`+l$8`(>I=g;T=Osoxo*yslcbmVcQc?)Pflyt4|$&E}7#*Azaz`Y)y4`10mWe~$=j zuh+;BZ&|hCvZ>vz8(xy{o&GLqQ=Pd)j?c$_jiGR}G-s~Qo(V-~T#U5XJ4DL35Br>I zeBgTMX*YpG+U=_u#xEu|!;IC0hzY30X>XPP(m z^OqU%7%}wK9du?gF=s7%>}-F*p=lGx{#MCS-D5W%K5zKkQZI z3q8CK$qDPEuKS8lIcpVaD|7EeMM=2rypQeA0wd3a z_;Vj`-j+UB(7L2P>hS-$#-8b%bMqW#nlx>8nYm=2z=5xtldnzOq#=>Uw8QG`?Z+ms zx8_|sWI7?fHu3d~ZwYZvUPNzyQ8ml*Smocd11V@u}4hm z$<=)qjvu{tBU@El_@`P0WKYMh%tf}z znymBgh?3Gbq@GwbMt!Sb^hU!D1x5u)) zI-a`Lu|2(bOmb&}_sMYmZF?+JUC*0qQGDU1! zvLsAC@vhOXBZoD#K3I8A)l%pzzH~o^ZDJG0^O9g+PW!c$36oYdZ#=p2)?;3O$@O8? zOY~QHU!8Z_<^A2Pex9zl{zQfl-<|6EmyS$Xzck99B|dShT+_}?UqplFZs-(#w0%hu z=Yq7ztk%-1qk3h*=X*ZcEpO)uZT}T`@N3u1-t|mJlKbLbO*ma_#f_ z&Aa(-doJYg{&uHlZ$G!9rDNvO$2R){|9+HoJ1-a1l~~ZSIp^CRE8~6tJO$+r{Is%H z$qsaTaiIOwYW+AiABVti=}9cvF2y>F{8BGP&PjBU$WWL!>)z}szh7LBo*DnQ_1%%S zg9qev*i_#rceI-R4Drd4jNSEBxA#4p;L|rN3tO&l&H1!WSU_KX)5;l*fsUUJiCo#z z+MMUf^T_-|q>|p11hGO>$AkAO6Ba*j{jq#*^k$EmzqvaiWb#+sp$d z+z}l1Vvb)WUK|MB;wdDt#{XYNrpw~ApK&Z=6{nqq*PQ*cV2i`iop*&Vs_b4qX-ejs zl_H#}7i?6I=B>D8=zrkC>(6d($v>4vuWAsBnh~&a{+S z7WlU%g1>lX=(Y9LYKIu+FTMP$;rzSWeIJ_4<{aMV>sSCg;M@!ZGEsKt9F$?)w0&f2Sb$L1Xh zzSAjjRz*E-z}DH$#WB)eW$2U$u@1>gJa8V&fE?0^ZeJQ6wMj= zGW6D(WFNg_6>s%}lipuWQ_gs6!oy;EP5;!B6*Y+(*SRuw`JP%{!(nFrCz5;5+h;q! zi`BlYsylanE$Y3Bup3Ge=AsN*~8DZKH|?kJn|MzU;HjNUSMTq zMk({(Mm=-MR4-2n_4}{clv30s4jXLdJ@RClw8y!}lMm7Gkb;}6z1J2rti@O601 zmCmEGi>GbfFEnFL#=<38SGbgZU0wEUs<8GWt!o#gFUf4{OqS#bE4=eDo0G#_dv0U; zmT@YqX?EsBNa<_sZXoRJOKHPFCNpBtI=1xBV)~;wD|Xq&utML;Yg>h$N={up`${6`QqIliPO+*SW_)(_ z!tV6dJT(o^UAc;GuYGAZqsR1Mj>?4ec;gvyuMIU$X6elmdE9J$=y!iz0n_xnH&=C! zw5*BGc3rgO@tapaLl<4kUwth9ykwBnThFgrZ?eRCHY7`|_pa=5dbuL)=|Uly3x7FPx+&#&K~UE8qW3pCxGyf7>eb%YyeLrZ+Lnfsn!V3*zn?BVdM0J2 z=GFI_b6G9Q6xX=4<%*~}oSX7K=E^eZ<2JW0TC&f-*YVe5dFYI{|8IQ$segKIkz8cp zn)f%ZbZLLlOkB5EJ}JU<$ui^AFn8{CC#Oq#Oegshhy@aFZa znALK0OH!QnoOF)AE_)Y!`e5Rvzx(?n&)lY^i#^Pr75SeCalf=Y&}oW9w1C$hjpclE z&K?Vu3DDn_&$KA@#btlKU=3a~?sQk5`%5-)xNqNeqJ8q>r2g;mUYaix78oe=t-9dZ zae1!KeJTDu>}d}y>o`_V-m(kb#nKw-Foqf*hw7~SweYs6Go^dN@ zZ=D%fuf6ZM#mWBk9n^6RcHFzQsGN!vvQYwT9@?7Dx3Rc@r;s^ ziOO25JUcwrZCt%m_m#?{JsUhO9dwQBX#1J`{8*&3_|nM5QAS71JR;AoSeiB0wkfl7 z|Doi7a{uk(g--;Jm2a(jnB#fvyp&jh!NRDSmD?vAyiv2g;YW6I$mwQJo5$DX{xeMA z-pjdxWjS+Wj*-?w&38Rhe(4lGPk+gJXzADVpB~e>&nrGKlM?^U(kg9Tz2^D)srycD zS#ph`zw*?bmYmigP0bLyPi~zTQevn0=kC8S+1u3XjGEO)cE>L+>{(||vOHpS>?@e$ zH#Kg)L8$Z0Y4?*?smXqN8eHpSYj!Df702?=vqT;)d$i-jtOJvoWH)$bFz>WEvTj4| zDi1$ho6mFN&%~6^U-fk9e}#?ey&0c9b{ZN>a0mR`7-lDV;L0B_))~J_o=*FEYkl_{ z=MQ(=r6rX8uIQ_jc{hsAmJl$QAO2!-j8gPzt6xXwNLd@r$_~^Rb6PeNyAiXtoUxc*XHu*;RO}P^jeJ|Yb z}Lsx8^k_#)=hB z`@24<9GNHK*X^A4Rl@7g#?1%PI>Jt@bUyWrA>~c85Z~wX?Gxc_U$o)Y>cz5+eLDj*%OyQh zqO{L*s3<7=SlpWW`Q%?Oz4cQAwAlO4^Vdpf_(haO_TAj9!d`oAL4|tWhP|@S{&KC~ zk?di2r1e%;xcLt66XNb4yQeN?W?Hp>PNn6lc_}##M@}tUYO}Co19p*Ibm1jx*2!(1P1>*r7QR8gUs)58x#0-zU(YHop@?n^}=7Z zoH=#L^Os~x7rOD^EITFf=#9<0b?z6$LbpklO3$9M=FPdiukG7X7%rV#C3gSO&y1<% zf87pEPyQTxnBD)*q~uV$ZOYHXeqQVR_H|ad%-dbz7B4nEi!A2sTzK-ako9ue=p|9& zQ~sY|Tp!7#VQww=@1y{ilE$3x%MQ+&lrbeI^ZMl*t5*eaWz0+wzPXBHX5=z{ZJB=) zrYpTVvo}QST1wvDn7|N|is=5h8|-nnuVijnu626jiM*VOsp}@@ymXJ%wO^7RBCo+O z6E`uJv-8t;1*3B>>XaFIMeaPf6ZQB1ggM^5uOy@w>~KH6`38gO^jV*89Jn&^R@F0y z_JY5@zjs}dQ#F>_JS)_7eQ|d4#I1X-eSOw1{pRZxUCAilGgG@ip78v>JwC~@I)0gf z;Mt&%z_N=n+wO&Kxg@vDb=k@@JI~cmT(VSX#>un0x>u||(bD^Ay3!}@yRPS$l+0Ol z?tR_e&G4`2jh<49&AqrI_3TN0k9P#y9eF(Ec=5(~DT}GcJ8OQuKXh?HboP8JDWCMW zoH{eM`5K%(Y4vr*>{6RW<~QHk-^jmx@uzK4_V(BOx2`6K*ZYQMDEDZ~n{Mmq+c7nG z*_M@BE)QC4)~-`i`@Lk-r_F8WuI^LIn_40ld-nW4y@C^Z($mgvQhD$&Uc~>$(!G;c z8hy6jG~duB>ivC%?TLqYjY}G<`kYtkM;HBBAY1D0ey1#PZg3`lZQT2AkIA2NzA%TL z{njh4z4zMMb6<`HhAoV^c6O?CfsN+&$($RvEH5rt=&Q3ym^bys$#k0)u>z@<9h1f9 zG<}`rck|*CyIH6Fyr#7*sbJ$so*JuW{z`wsR2#O{cU0o^bBZmJ?!`=S)Aiiu@cdU$ z_L3YO_3#T1R`q>}ko~E-*=3RDd9}wqpDsOG5~JvuekGZAnxp#f+2^(fcHK>>e!pFb zue|9p|AbjAPgg5spHN*c^RYt3!|&A3+hX796wCxW^Vj`jpD8EZh&eO|9&iKAVVPJO z8N=tZOt8#nnSciI2+n8i1)U;ryl`5)`4{D9g=%XuuhqWjU6RQ?DYHrB(DFYU4op&L zI-=*mu&E{fz5eSLr(Ug-d&97q$CcysymznG*zB{>+8qBLycj+FU+uR~uQtE`^X}*D z)g`6s<@K}v|9biA>r|cpil^@G)}Qx)QS+;w-$l*zGXJ_Alb$jzFOS>px$Exa>EZu3 zqa7s>i*&ct|6dB~sauL+3(@OKEVyDsF5UXO|7`gD3!%bGu9p43`tXIC;_3BU{Hk}^ zeoXz}V)jGvL-hZz1yd$p3w-%^e*>R<>4e|;9e$a6Zq~PF-^#on9P&aS>fL{X^;5Pd zI^Fp%SwC|@&Y%10^(t+Z=k(Wp72%2a_9QJWn4>P=`0$b~U#@JtQx+oE&o%Y^zshG% zzPoH=vdpWmosc-m@YmmXelNd?E0XN@A6(bk81v|#ZieZx%ANlW12b9|T5mO(%oaTF zocQ|Lb6$M(bg=sBr+nq#y1)OJb>-Fa?>_r<%9rg;YWKFT7S&k+(-k^=k*QdK(7hmbHI$6H(Q^LLfrZ2bk zZZVxNJ7rcAFXR3u<)Wgx|DP6Y;4^&qdz(u2#kYI-J_cLe5tQ(>4{ObQwBh&tbLam| z5(_$Y?$H9%`*NGAGLK&MwzQU%U0oL|e@0~Ogd@c|kM_3Cn_^%3Y*(KFr^b)X&8=$g z_CZk{0j!FzSD7x|{MWK#{>&J?q&R!o&M zRJ;5A>g3h=>*L;+u&rG@^AKP3+@|f;;&W%mDBSt|=;GD%{(blM{(XA)d-(jn$Nl1J zzp?+?uP;~MSugkZ@;meJc-vdGyL%h!SQ;6#ob_jh96K;oPED74RTf)g^2D_QiYM=N zoz&Wy>BabE_JN*BH{Bn$pDVXAjZB|D?ahLy2OooPbj^}Un5=x1|AOe^MSXYniGQgy zw%pmP@-lth`ZF?pE+ruXxl6TvhziZOtBhCN&T{+emg~cM_=&^k*QqUfe`NES3MAxr7}YDSGmhP( zxPPJJytqc+Lw|F(C@xi*w#q%1kdCY+K&v>cD278fueRS(I#_eff8Tc-pe^ZQ_1&WH(LQvehv> zS=adQrr=LEoV~NnB2R3dt6aPNLEI*;Z8f(wG&f9Ti1rIguYYQrY@p0*G=XEr;Xt{f z1spnw?b|vOo8N!2e%Met!S!gPnB^X?1vw8FAIsk_7n^ds;;O^nyad^std`HOv$@;k zT+#}3eImz~xI$%7`kIR9MTzg3wmGb3Vg4t?YoMKdN26;(-7MyKhhm32T@u~wUr$$P zXNo^bwwczu={o1*5AuDt|H{T**`V<`(RTR)%an%0hbLc2Ucb9e`A_oaDZUSlG$xe4 zUv%nnAD1@MvN`We_1_=NTX8SwHs?+2fxya-!WRb{t(Q!RLbHv_L=Sz zwBua#6<3?`YW-<^GcHWrvu@ht3w^dn>h7Pobxc#t|MrPi$-QT`nQY?U`;uLw;YzZf z{an*2h8Y_kKe{)uQfepD@uW0)7WbliQF*P3Gkvyy{9{|gvME{qu+sDsbAFz``TE(D zxr-Wfk^}|T=>*p+FIcpci(#t6yZOzgrz%!i)p>ST@3F5_*uLkqD%(nP<_)`w`+leP zOW*A7n-ue(uhD+Tr-GZ@Ld~7`9<6+5a4!BwTzg*A8wC^n!nrr31n>3TX%X-&{@Qd=?0wczmEl$GX^8C_w=dNndvmZfOg8*e!Lcv8}_dk>#m ze6mVzn9^;tW>v{qImXNMg+w05^=j?P{;aCn2`)M9 zck;q(Z*g1dH!t8apKx_$$mPg@XP#%Tsw}A66uXOgcaMP9#NG&NhgWP?*(Y?Xv^JzD zNjOQKXh;;9rMY)}b_-j4*Ue`w@x94s^*Wh< zCT?ojTz7qI)wf{f1xsIPJ~|$48o!^(V#T|_xqB8Y%duo-mOGUvcGdsWbIW6`&F`Gv z{?b0pEK#_4!cy)l?v<(Mj~;2AcKLad-@=Kh8KJXpIcdknuxx$rzvRzfFYQqES9R?B zl>Nii?mX6M46S;wSnaV&_{F+Fe=j|A?kQY9XTM+cdVebKgoT^;KWmBSeZ;)1=jmLn zJh7Kkmnu&cB(s#rp^{vR^MGrW?Gbekjn*L9Q`Qoby-EUrR(+ZSHo1Hs%_qvFv!i+hW z!V1-=F{eCLn%#1KS?~9gPb^B-Zmmwgm3Va5HV@N|(r3HvS{E-`$m{LWeqC)E-`}&J z%L=FNIqB$k-+JNno$FMaC1+k}`{j8MYBpLO{ra4$NXeY?9FKp zJuDV|_%KB~Q~k1F9lwR9yUyXq%?}^*8nm4&DXe;sc)Gi0nqKQ>p|Hey(SH|jF0}Oj zpefK_`{~nmF8v4t%hJ8Uw`QJtBe`mn%8Q2=A3W)Z1aaJR&iuhu)bpO?JY5OV3~r*o^m_#3S}pQ*fI zW5~<}SL`&J@80zEw)(!XK340ABXg3~(`v)}-^^0y2XW5kIx<=Gg83&kkGQ!lf4ZM> zp6zr@J0$u@)wc7+@lz=seup*|JP3U0v#{vY^cn5vwDp3tqXo>1xmI*snNs}9Rd8ns zXYCvj&f?3i&tLZR7kR60@9g*cV|66>$hC|A+Ekvtu=D#^t&zhLrn1?28q3|QM_a^y zJyr`lru|5s>w8Cd_N(+oD?HD1epj}6Qu1Zi#=L1|MptWeKL?yY?rke+kbB&uovZ7f zzt!A-=c8((Pem=d>~d(vq6K#ZnDvW1-sgVGHah+C;TZ!C1J3sc>sIB3&fc~3owBRx zy0qBV%V8zmGtb;_TWz2$+bh4RuP-Lqdg>lMwz}Cnm7LfDm;60;T|E0nm0@;l*6k(d z)tVbcgH%Mqgx|I7uk>~G5Up9owPE>-@_daWt``KhzP^^%WRs0Zqz|q8B#pbHclMVl2~nUkiFBY|UYP$|o0i`an>Z?8U9WZwbn-yYNW*%NOgjjZHr- zY_spwP0kKFbj$B1dr@NC(%3!oYy-aq>9Kr!UH$5fP9T4{23PLoz_U7`Too&mPq41L zUA|e%L_XrJV(6~TZh-|UkDh#dR~BELyf=5r%Vbrib+f8pO?X}UVzS9Dk2__o_s=eH z@hD#S>CnjqEQ)54Ax+Mf-qouv-AhOi_u6B<cbuXU-L_;t1GdRbZDg=hVramZkY zkL0$!5hb2+57Kw^+?jUgu-*nSP`&!gn zmV`AsG@aXNq#_hHEqG!7r3w4xCSAXh=Im_3zP>x_WX{h29icB(0&i~XR5b12Ta?T9 zPu_2l$(82Ahj(fz2eS$)i0O;W$Xm%Xb<0cJ4&`�q0Ad9mk4zQ*&SQ)jN-pX@NN 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

hzbCAI5uLsw>JGFQ441^5FgB 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%0A@O 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%0Acw+yHnCSZ}Sc@3F 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 +BKpdjOm$p`BLnf%hlZCUN+8!TTjZ`f$0 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 -\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}} -\def\gap{\vspace{0.5ex}} -\makeindex -\begin{document} -\frontmatter -\pagestyle{empty} -\title{Multi--Precision Math} -\author{\mbox{ -%\begin{small} -\begin{tabular}{c} -Tom St Denis \\ -Algonquin College \\ -\\ -Mads Rasmussen \\ -Open Communications Security \\ -\\ -Greg Rose \\ -QUALCOMM Australia \\ -\end{tabular} -%\end{small} -} -} -\maketitle -This text has been placed in the public domain. This text corresponds to the v0.39 release of the -LibTomMath project. - -\begin{alltt} -Tom St Denis -111 Banning Rd -Ottawa, Ontario -K2L 1C3 -Canada - -Phone: 1-613-836-3160 -Email: tomstdenis@gmail.com -\end{alltt} - -This text is formatted to the international B5 paper size of 176mm wide by 250mm tall using the \LaTeX{} -{\em book} macro package and the Perl {\em booker} package. - -\tableofcontents -\listoffigures -\chapter*{Prefaces} -When I tell people about my LibTom projects and that I release them as public domain they are often puzzled. -They ask why I did it and especially why I continue to work on them for free. The best I can explain it is ``Because I can.'' -Which seems odd and perhaps too terse for adult conversation. I often qualify it with ``I am able, I am willing.'' which -perhaps explains it better. I am the first to admit there is not anything that special with what I have done. Perhaps -others can see that too and then we would have a society to be proud of. My LibTom projects are what I am doing to give -back to society in the form of tools and knowledge that can help others in their endeavours. - -I started writing this book because it was the most logical task to further my goal of open academia. The LibTomMath source -code itself was written to be easy to follow and learn from. There are times, however, where pure C source code does not -explain the algorithms properly. Hence this book. The book literally starts with the foundation of the library and works -itself outwards to the more complicated algorithms. The use of both pseudo--code and verbatim source code provides a duality -of ``theory'' and ``practice'' that the computer science students of the world shall appreciate. I never deviate too far -from relatively straightforward algebra and I hope that this book can be a valuable learning asset. - -This book and indeed much of the LibTom projects would not exist in their current form if it was not for a plethora -of kind people donating their time, resources and kind words to help support my work. Writing a text of significant -length (along with the source code) is a tiresome and lengthy process. Currently the LibTom project is four years old, -comprises of literally thousands of users and over 100,000 lines of source code, TeX and other material. People like Mads and Greg -were there at the beginning to encourage me to work well. It is amazing how timely validation from others can boost morale to -continue the project. Definitely my parents were there for me by providing room and board during the many months of work in 2003. - -To my many friends whom I have met through the years I thank you for the good times and the words of encouragement. I hope I -honour your kind gestures with this project. - -Open Source. Open Academia. Open Minds. - -\begin{flushright} Tom St Denis \end{flushright} - -\newpage -I found the opportunity to work with Tom appealing for several reasons, not only could I broaden my own horizons, but also -contribute to educate others facing the problem of having to handle big number mathematical calculations. - -This book is Tom's child and he has been caring and fostering the project ever since the beginning with a clear mind of -how he wanted the project to turn out. I have helped by proofreading the text and we have had several discussions about -the layout and language used. - -I hold a masters degree in cryptography from the University of Southern Denmark and have always been interested in the -practical aspects of cryptography. - -Having worked in the security consultancy business for several years in S\~{a}o Paulo, Brazil, I have been in touch with a -great deal of work in which multiple precision mathematics was needed. Understanding the possibilities for speeding up -multiple precision calculations is often very important since we deal with outdated machine architecture where modular -reductions, for example, become painfully slow. - -This text is for people who stop and wonder when first examining algorithms such as RSA for the first time and asks -themselves, ``You tell me this is only secure for large numbers, fine; but how do you implement these numbers?'' - -\begin{flushright} -Mads Rasmussen - -S\~{a}o Paulo - SP - -Brazil -\end{flushright} - -\newpage -It's all because I broke my leg. That just happened to be at about the same time that Tom asked for someone to review the section of the book about -Karatsuba multiplication. I was laid up, alone and immobile, and thought ``Why not?'' I vaguely knew what Karatsuba multiplication was, but not -really, so I thought I could help, learn, and stop myself from watching daytime cable TV, all at once. - -At the time of writing this, I've still not met Tom or Mads in meatspace. I've been following Tom's progress since his first splash on the -sci.crypt Usenet news group. I watched him go from a clueless newbie, to the cryptographic equivalent of a reformed smoker, to a real -contributor to the field, over a period of about two years. I've been impressed with his obvious intelligence, and astounded by his productivity. -Of course, he's young enough to be my own child, so he doesn't have my problems with staying awake. - -When I reviewed that single section of the book, in its very earliest form, I was very pleasantly surprised. So I decided to collaborate more fully, -and at least review all of it, and perhaps write some bits too. There's still a long way to go with it, and I have watched a number of close -friends go through the mill of publication, so I think that the way to go is longer than Tom thinks it is. Nevertheless, it's a good effort, -and I'm pleased to be involved with it. - -\begin{flushright} -Greg Rose, Sydney, Australia, June 2003. -\end{flushright} - -\mainmatter -\pagestyle{headings} -\chapter{Introduction} -\section{Multiple Precision Arithmetic} - -\subsection{What is Multiple Precision Arithmetic?} -When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively -raise or lower the precision of the numbers we are dealing with. For example, in decimal we almost immediate can -reason that $7$ times $6$ is $42$. However, $42$ has two digits of precision as opposed to one digit we started with. -Further multiplications of say $3$ result in a larger precision result $126$. In these few examples we have multiple -precisions for the numbers we are working with. Despite the various levels of precision a single subset\footnote{With the occasional optimization.} - of algorithms can be designed to accomodate them. - -By way of comparison a fixed or single precision operation would lose precision on various operations. For example, in -the decimal system with fixed precision $6 \cdot 7 = 2$. - -Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in -schools to manually add, subtract, multiply and divide. - -\subsection{The Need for Multiple Precision Arithmetic} -The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation -of public-key cryptography algorithms. Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require -integers of significant magnitude to resist known cryptanalytic attacks. For example, at the time of this writing a -typical RSA modulus would be at least greater than $10^{309}$. However, modern programming languages such as ISO C \cite{ISOC} and -Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision. - -\begin{figure}[!here] -\begin{center} -\begin{tabular}{|r|c|} -\hline \textbf{Data Type} & \textbf{Range} \\ -\hline char & $-128 \ldots 127$ \\ -\hline short & $-32768 \ldots 32767$ \\ -\hline long & $-2147483648 \ldots 2147483647$ \\ -\hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\ -\hline -\end{tabular} -\end{center} -\caption{Typical Data Types for the C Programming Language} -\label{fig:ISOC} -\end{figure} - -The largest data type guaranteed to be provided by the ISO C programming -language\footnote{As per the ISO C standard. However, each compiler vendor is allowed to augment the precision as they -see fit.} can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is -insufficient to accomodate the magnitude required for the problem at hand. An RSA modulus of magnitude $10^{19}$ could be -trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer, -rendering any protocol based on the algorithm insecure. Multiple precision algorithms solve this very problem by -extending the range of representable integers while using single precision data types. - -Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic -primitives. Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in -various cryptographic journals, can render algorithms such as RSA and Diffie-Hellman more efficient. In fact, several -major companies such as RSA Security, Certicom and Entrust have built entire product lines on the implementation and -deployment of efficient algorithms. - -However, cryptography is not the only field of study that can benefit from fast multiple precision integer routines. -Another auxiliary use of multiple precision integers is high precision floating point data types. -The basic IEEE \cite{IEEE} standard floating point type is made up of an integer mantissa $q$, an exponent $e$ and a sign bit $s$. -Numbers are given in the form $n = q \cdot b^e \cdot -1^s$ where $b = 2$ is the most common base for IEEE. Since IEEE -floating point is meant to be implemented in hardware the precision of the mantissa is often fairly small -(\textit{23, 48 and 64 bits}). The mantissa is merely an integer and a multiple precision integer could be used to create -a mantissa of much larger precision than hardware alone can efficiently support. This approach could be useful where -scientific applications must minimize the total output error over long calculations. - -Yet another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$). -In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}. - -\subsection{Benefits of Multiple Precision Arithmetic} -\index{precision} -The benefit of multiple precision representations over single or fixed precision representations is that -no precision is lost while representing the result of an operation which requires excess precision. For example, -the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully. A multiple -precision algorithm would augment the precision of the destination to accomodate the result while a single precision system -would truncate excess bits to maintain a fixed level of precision. - -It is possible to implement algorithms which require large integers with fixed precision algorithms. For example, elliptic -curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum -size the system will ever need. Such an approach can lead to vastly simpler algorithms which can accomodate the -integers required even if the host platform cannot natively accomodate them\footnote{For example, the average smartcard -processor has an 8 bit accumulator.}. However, as efficient as such an approach may be, the resulting source code is not -normally very flexible. It cannot, at runtime, accomodate inputs of higher magnitude than the designer anticipated. - -Multiple precision algorithms have the most overhead of any style of arithmetic. For the the most part the -overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved -platforms. However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the -inputs. That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input -without the designer's explicit forethought. This leads to lower cost of ownership for the code as it only has to -be written and tested once. - -\section{Purpose of This Text} -The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms. -That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping'' -elements that are neglected by authors of other texts on the subject. Several well reknowned texts \cite{TAOCPV2,HAC} -give considerably detailed explanations of the theoretical aspects of algorithms and often very little information -regarding the practical implementation aspects. - -In most cases how an algorithm is explained and how it is actually implemented are two very different concepts. For -example, the Handbook of Applied Cryptography (\textit{HAC}), algorithm 14.7 on page 594, gives a relatively simple -algorithm for performing multiple precision integer addition. However, the description lacks any discussion concerning -the fact that the two integer inputs may be of differing magnitudes. As a result the implementation is not as simple -as the text would lead people to believe. Similarly the division routine (\textit{algorithm 14.20, pp. 598}) does not -discuss how to handle sign or handle the dividend's decreasing magnitude in the main loop (\textit{step \#3}). - -Both texts also do not discuss several key optimal algorithms required such as ``Comba'' and Karatsuba multipliers -and fast modular inversion, which we consider practical oversights. These optimal algorithms are vital to achieve -any form of useful performance in non-trivial applications. - -To solve this problem the focus of this text is on the practical aspects of implementing a multiple precision integer -package. As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.com}} package is used -to demonstrate algorithms with real implementations\footnote{In the ISO C programming language.} that have been field -tested and work very well. The LibTomMath library is freely available on the Internet for all uses and this text -discusses a very large portion of the inner workings of the library. - -The algorithms that are presented will always include at least one ``pseudo-code'' description followed -by the actual C source code that implements the algorithm. The pseudo-code can be used to implement the same -algorithm in other programming languages as the reader sees fit. - -This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch. Showing -the reader how the algorithms fit together as well as where to start on various taskings. - -\section{Discussion and Notation} -\subsection{Notation} -A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1}, \ldots, x_1, x_0)_{ \beta }$ and represent -the integer $x \equiv \sum_{i=0}^{n-1} x_i\beta^i$. The elements of the array $x$ are said to be the radix $\beta$ digits -of the integer. For example, $x = (1,2,3)_{10}$ would represent the integer -$1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$. - -\index{mp\_int} -The term ``mp\_int'' shall refer to a composite structure which contains the digits of the integer it represents, as well -as auxilary data required to manipulate the data. These additional members are discussed further in section -\ref{sec:MPINT}. For the purposes of this text a ``multiple precision integer'' and an ``mp\_int'' are assumed to be -synonymous. When an algorithm is specified to accept an mp\_int variable it is assumed the various auxliary data members -are present as well. An expression of the type \textit{variablename.item} implies that it should evaluate to the -member named ``item'' of the variable. For example, a string of characters may have a member ``length'' which would -evaluate to the number of characters in the string. If the string $a$ equals ``hello'' then it follows that -$a.length = 5$. - -For certain discussions more generic algorithms are presented to help the reader understand the final algorithm used -to solve a given problem. When an algorithm is described as accepting an integer input it is assumed the input is -a plain integer with no additional multiple-precision members. That is, algorithms that use integers as opposed to -mp\_ints as inputs do not concern themselves with the housekeeping operations required such as memory management. These -algorithms will be used to establish the relevant theory which will subsequently be used to describe a multiple -precision algorithm to solve the same problem. - -\subsection{Precision Notation} -The variable $\beta$ represents the radix of a single digit of a multiple precision integer and -must be of the form $q^p$ for $q, p \in \Z^+$. A single precision variable must be able to represent integers in -the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range -$0 \le x < q \beta^2$. The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the -carry. Since all modern computers are binary, it is assumed that $q$ is two. - -\index{mp\_digit} \index{mp\_word} -Within the source code that will be presented for each algorithm, the data type \textbf{mp\_digit} will represent -a single precision integer type, while, the data type \textbf{mp\_word} will represent a double precision integer type. In -several algorithms (notably the Comba routines) temporary results will be stored in arrays of double precision mp\_words. -For the purposes of this text $x_j$ will refer to the $j$'th digit of a single precision array and $\hat x_j$ will refer to -the $j$'th digit of a double precision array. Whenever an expression is to be assigned to a double precision -variable it is assumed that all single precision variables are promoted to double precision during the evaluation. -Expressions that are assigned to a single precision variable are truncated to fit within the precision of a single -precision data type. - -For example, if $\beta = 10^2$ a single precision data type may represent a value in the -range $0 \le x < 10^3$, while a double precision data type may represent a value in the range $0 \le x < 10^5$. Let -$a = 23$ and $b = 49$ represent two single precision variables. The single precision product shall be written -as $c \leftarrow a \cdot b$ while the double precision product shall be written as $\hat c \leftarrow a \cdot b$. -In this particular case, $\hat c = 1127$ and $c = 127$. The most significant digit of the product would not fit -in a single precision data type and as a result $c \ne \hat c$. - -\subsection{Algorithm Inputs and Outputs} -Within the algorithm descriptions all variables are assumed to be scalars of either single or double precision -as indicated. The only exception to this rule is when variables have been indicated to be of type mp\_int. This -distinction is important as scalars are often used as array indicies and various other counters. - -\subsection{Mathematical Expressions} -The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an integer not greater than the expression -itself. For example, $\lfloor 5.7 \rfloor = 5$. Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression -rounded to an integer not less than the expression itself. For example, $\lceil 5.1 \rceil = 6$. Typically when -the $/$ division symbol is used the intention is to perform an integer division with truncation. For example, -$5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity. When an expression is written as a -fraction a real value division is implied, for example ${5 \over 2} = 2.5$. - -The norm of a multiple precision integer, for example $\vert \vert x \vert \vert$, will be used to represent the number of digits in the representation -of the integer. For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$. - -\subsection{Work Effort} -\index{big-Oh} -To measure the efficiency of the specified algorithms, a modified big-Oh notation is used. In this system all -single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}. -That is a single precision addition, multiplication and division are assumed to take the same time to -complete. While this is generally not true in practice, it will simplify the discussions considerably. - -Some algorithms have slight advantages over others which is why some constants will not be removed in -the notation. For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a -baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work. In standard big-Oh notation these -would both be said to be equivalent to $O(n^2)$. However, -in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small. As a -result small constant factors in the work effort will make an observable difference in algorithm efficiency. - -All of the algorithms presented in this text have a polynomial time work level. That is, of the form -$O(n^k)$ for $n, k \in \Z^{+}$. This will help make useful comparisons in terms of the speed of the algorithms and how -various optimizations will help pay off in the long run. - -\section{Exercises} -Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to -the discussion at hand. These exercises are not designed to be prize winning problems, but instead to be thought -provoking. Wherever possible the problems are forward minded, stating problems that will be answered in subsequent -chapters. The reader is encouraged to finish the exercises as they appear to get a better understanding of the -subject material. - -That being said, the problems are designed to affirm knowledge of a particular subject matter. Students in particular -are encouraged to verify they can answer the problems correctly before moving on. - -Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of -the problem. However, unlike \cite{TAOCPV2} the problems do not get nearly as hard. The scoring of these -exercises ranges from one (the easiest) to five (the hardest). The following table sumarizes the -scoring system used. - -\begin{figure}[here] -\begin{center} -\begin{small} -\begin{tabular}{|c|l|} -\hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\ - & minutes to solve. Usually does not involve much computer time \\ - & to solve. \\ -\hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\ - & time usage. Usually requires a program to be written to \\ - & solve the problem. \\ -\hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\ - & of work. Usually involves trivial research and development of \\ - & new theory from the perspective of a student. \\ -\hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\ - & of work and research, the solution to which will demonstrate \\ - & a higher mastery of the subject matter. \\ -\hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\ - & novice to solve. Solutions to these problems will demonstrate a \\ - & complete mastery of the given subject. \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Exercise Scoring System} -\end{figure} - -Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or -devising new theory. These problems are quick tests to see if the material is understood. Problems at the second level -are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer. These -two levels are essentially entry level questions. - -Problems at the third level are meant to be a bit more difficult than the first two levels. The answer is often -fairly obvious but arriving at an exacting solution requires some thought and skill. These problems will almost always -involve devising a new algorithm or implementing a variation of another algorithm previously presented. Readers who can -answer these questions will feel comfortable with the concepts behind the topic at hand. - -Problems at the fourth level are meant to be similar to those of the level three questions except they will require -additional research to be completed. The reader will most likely not know the answer right away, nor will the text provide -the exact details of the answer until a subsequent chapter. - -Problems at the fifth level are meant to be the hardest -problems relative to all the other problems in the chapter. People who can correctly answer fifth level problems have a -mastery of the subject matter at hand. - -Often problems will be tied together. The purpose of this is to start a chain of thought that will be discussed in future chapters. The reader -is encouraged to answer the follow-up problems and try to draw the relevance of problems. - -\section{Introduction to LibTomMath} - -\subsection{What is LibTomMath?} -LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C. By portable it -is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on -any given platform. - -The library has been successfully tested under numerous operating systems including Unix\footnote{All of these -trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux, PalmOS and on standalone hardware such -as the Gameboy Advance. The library is designed to contain enough functionality to be able to develop applications such -as public key cryptosystems and still maintain a relatively small footprint. - -\subsection{Goals of LibTomMath} - -Libraries which obtain the most efficiency are rarely written in a high level programming language such as C. However, -even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the -library. Specifically the code has been written to work well with the GNU C Compiler (\textit{GCC}) on both x86 and ARM -processors. Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window -exponentiation and Montgomery reduction have been provided to make the library more efficient. - -Even with the nearly optimal and specialized algorithms that have been included the Application Programing Interface -(\textit{API}) has been kept as simple as possible. Often generic place holder routines will make use of specialized -algorithms automatically without the developer's specific attention. One such example is the generic multiplication -algorithm \textbf{mp\_mul()} which will automatically use Toom--Cook, Karatsuba, Comba or baseline multiplication -based on the magnitude of the inputs and the configuration of the library. - -Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project. Ideally the library should -be source compatible with another popular library which makes it more attractive for developers to use. In this case the -MPI library was used as a API template for all the basic functions. MPI was chosen because it is another library that fits -in the same niche as LibTomMath. Even though LibTomMath uses MPI as the template for the function names and argument -passing conventions, it has been written from scratch by Tom St Denis. - -The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum'' -library exists which can be used to teach computer science students how to perform fast and reliable multiple precision -integer arithmetic. To this end the source code has been given quite a few comments and algorithm discussion points. - -\section{Choice of LibTomMath} -LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but -for more worthy reasons. Other libraries such as GMP \cite{GMP}, MPI \cite{MPI}, LIP \cite{LIP} and OpenSSL -\cite{OPENSSL} have multiple precision integer arithmetic routines but would not be ideal for this text for -reasons that will be explained in the following sub-sections. - -\subsection{Code Base} -The LibTomMath code base is all portable ISO C source code. This means that there are no platform dependent conditional -segments of code littered throughout the source. This clean and uncluttered approach to the library means that a -developer can more readily discern the true intent of a given section of source code without trying to keep track of -what conditional code will be used. - -The code base of LibTomMath is well organized. Each function is in its own separate source code file -which allows the reader to find a given function very quickly. On average there are $76$ lines of code per source -file which makes the source very easily to follow. By comparison MPI and LIP are single file projects making code tracing -very hard. GMP has many conditional code segments which also hinder tracing. - -When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $100$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.} - which is fairly small compared to GMP (over $250$KiB). LibTomMath is slightly larger than MPI (which compiles to about -$50$KiB) but LibTomMath is also much faster and more complete than MPI. - -\subsection{API Simplicity} -LibTomMath is designed after the MPI library and shares the API design. Quite often programs that use MPI will build -with LibTomMath without change. The function names correlate directly to the action they perform. Almost all of the -functions share the same parameter passing convention. The learning curve is fairly shallow with the API provided -which is an extremely valuable benefit for the student and developer alike. - -The LIP library is an example of a library with an API that is awkward to work with. LIP uses function names that are often ``compressed'' to -illegible short hand. LibTomMath does not share this characteristic. - -The GMP library also does not return error codes. Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors -are signaled to the host application. This happens to be the fastest approach but definitely not the most versatile. In -effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely -undersireable in many situations. - -\subsection{Optimizations} -While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does -feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring. GMP -and LIP also feature such optimizations while MPI only uses baseline algorithms with no optimizations. GMP lacks a few -of the additional modular reduction optimizations that LibTomMath features\footnote{At the time of this writing GMP -only had Barrett and Montgomery modular reduction algorithms.}. - -LibTomMath is almost always an order of magnitude faster than the MPI library at computationally expensive tasks such as modular -exponentiation. In the grand scheme of ``bignum'' libraries LibTomMath is faster than the average library and usually -slower than the best libraries such as GMP and OpenSSL by only a small factor. - -\subsection{Portability and Stability} -LibTomMath will build ``out of the box'' on any platform equipped with a modern version of the GNU C Compiler -(\textit{GCC}). This means that without changes the library will build without configuration or setting up any -variables. LIP and MPI will build ``out of the box'' as well but have numerous known bugs. Most notably the author of -MPI has recently stopped working on his library and LIP has long since been discontinued. - -GMP requires a configuration script to run and will not build out of the box. GMP and LibTomMath are still in active -development and are very stable across a variety of platforms. - -\subsection{Choice} -LibTomMath is a relatively compact, well documented, highly optimized and portable library which seems only natural for -the case study of this text. Various source files from the LibTomMath project will be included within the text. However, -the reader is encouraged to download their own copy of the library to actually be able to work with the library. - -\chapter{Getting Started} -\section{Library Basics} -The trick to writing any useful library of source code is to build a solid foundation and work outwards from it. First, -a problem along with allowable solution parameters should be identified and analyzed. In this particular case the -inability to accomodate multiple precision integers is the problem. Futhermore, the solution must be written -as portable source code that is reasonably efficient across several different computer platforms. - -After a foundation is formed the remainder of the library can be designed and implemented in a hierarchical fashion. -That is, to implement the lowest level dependencies first and work towards the most abstract functions last. For example, -before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm. -By building outwards from a base foundation instead of using a parallel design methodology the resulting project is -highly modular. Being highly modular is a desirable property of any project as it often means the resulting product -has a small footprint and updates are easy to perform. - -Usually when I start a project I will begin with the header files. I define the data types I think I will need and -prototype the initial functions that are not dependent on other functions (within the library). After I -implement these base functions I prototype more dependent functions and implement them. The process repeats until -I implement all of the functions I require. For example, in the case of LibTomMath I implemented functions such as -mp\_init() well before I implemented mp\_mul() and even further before I implemented mp\_exptmod(). As an example as to -why this design works note that the Karatsuba and Toom-Cook multipliers were written \textit{after} the -dependent function mp\_exptmod() was written. Adding the new multiplication algorithms did not require changes to the -mp\_exptmod() function itself and lowered the total cost of ownership (\textit{so to speak}) and of development -for new algorithms. This methodology allows new algorithms to be tested in a complete framework with relative ease. - -FIGU,design_process,Design Flow of the First Few Original LibTomMath Functions. - -Only after the majority of the functions were in place did I pursue a less hierarchical approach to auditing and optimizing -the source code. For example, one day I may audit the multipliers and the next day the polynomial basis functions. - -It only makes sense to begin the text with the preliminary data types and support algorithms required as well. -This chapter discusses the core algorithms of the library which are the dependents for every other algorithm. - -\section{What is a Multiple Precision Integer?} -Recall that most programming languages, in particular ISO C \cite{ISOC}, only have fixed precision data types that on their own cannot -be used to represent values larger than their precision will allow. The purpose of multiple precision algorithms is -to use fixed precision data types to create and manipulate multiple precision integers which may represent values -that are very large. - -As a well known analogy, school children are taught how to form numbers larger than nine by prepending more radix ten digits. In the decimal system -the largest single digit value is $9$. However, by concatenating digits together larger numbers may be represented. Newly prepended digits -(\textit{to the left}) are said to be in a different power of ten column. That is, the number $123$ can be described as having a $1$ in the hundreds -column, $2$ in the tens column and $3$ in the ones column. Or more formally $123 = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0$. Computer based -multiple precision arithmetic is essentially the same concept. Larger integers are represented by adjoining fixed -precision computer words with the exception that a different radix is used. - -What most people probably do not think about explicitly are the various other attributes that describe a multiple precision -integer. For example, the integer $154_{10}$ has two immediately obvious properties. First, the integer is positive, -that is the sign of this particular integer is positive as opposed to negative. Second, the integer has three digits in -its representation. There is an additional property that the integer posesses that does not concern pencil-and-paper -arithmetic. The third property is how many digits placeholders are available to hold the integer. - -The human analogy of this third property is ensuring there is enough space on the paper to write the integer. For example, -if one starts writing a large number too far to the right on a piece of paper they will have to erase it and move left. -Similarly, computer algorithms must maintain strict control over memory usage to ensure that the digits of an integer -will not exceed the allowed boundaries. These three properties make up what is known as a multiple precision -integer or mp\_int for short. - -\subsection{The mp\_int Structure} -\label{sec:MPINT} -The mp\_int structure is the ISO C based manifestation of what represents a multiple precision integer. The ISO C standard does not provide for -any such data type but it does provide for making composite data types known as structures. The following is the structure definition -used within LibTomMath. - -\index{mp\_int} -\begin{figure}[here] -\begin{center} -\begin{small} -%\begin{verbatim} -\begin{tabular}{|l|} -\hline -typedef struct \{ \\ -\hspace{3mm}int used, alloc, sign;\\ -\hspace{3mm}mp\_digit *dp;\\ -\} \textbf{mp\_int}; \\ -\hline -\end{tabular} -%\end{verbatim} -\end{small} -\caption{The mp\_int Structure} -\label{fig:mpint} -\end{center} -\end{figure} - -The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows. - -\begin{enumerate} -\item The \textbf{used} parameter denotes how many digits of the array \textbf{dp} contain the digits used to represent -a given integer. The \textbf{used} count must be positive (or zero) and may not exceed the \textbf{alloc} count. - -\item The \textbf{alloc} parameter denotes how -many digits are available in the array to use by functions before it has to increase in size. When the \textbf{used} count -of a result would exceed the \textbf{alloc} count all of the algorithms will automatically increase the size of the -array to accommodate the precision of the result. - -\item The pointer \textbf{dp} points to a dynamically allocated array of digits that represent the given multiple -precision integer. It is padded with $(\textbf{alloc} - \textbf{used})$ zero digits. The array is maintained in a least -significant digit order. As a pencil and paper analogy the array is organized such that the right most digits are stored -first starting at the location indexed by zero\footnote{In C all arrays begin at zero.} in the array. For example, -if \textbf{dp} contains $\lbrace a, b, c, \ldots \rbrace$ where \textbf{dp}$_0 = a$, \textbf{dp}$_1 = b$, \textbf{dp}$_2 = c$, $\ldots$ then -it would represent the integer $a + b\beta + c\beta^2 + \ldots$ - -\index{MP\_ZPOS} \index{MP\_NEG} -\item The \textbf{sign} parameter denotes the sign as either zero/positive (\textbf{MP\_ZPOS}) or negative (\textbf{MP\_NEG}). -\end{enumerate} - -\subsubsection{Valid mp\_int Structures} -Several rules are placed on the state of an mp\_int structure and are assumed to be followed for reasons of efficiency. -The only exceptions are when the structure is passed to initialization functions such as mp\_init() and mp\_init\_copy(). - -\begin{enumerate} -\item The value of \textbf{alloc} may not be less than one. That is \textbf{dp} always points to a previously allocated -array of digits. -\item The value of \textbf{used} may not exceed \textbf{alloc} and must be greater than or equal to zero. -\item The value of \textbf{used} implies the digit at index $(used - 1)$ of the \textbf{dp} array is non-zero. That is, -leading zero digits in the most significant positions must be trimmed. - \begin{enumerate} - \item Digits in the \textbf{dp} array at and above the \textbf{used} location must be zero. - \end{enumerate} -\item The value of \textbf{sign} must be \textbf{MP\_ZPOS} if \textbf{used} is zero; -this represents the mp\_int value of zero. -\end{enumerate} - -\section{Argument Passing} -A convention of argument passing must be adopted early on in the development of any library. Making the function -prototypes consistent will help eliminate many headaches in the future as the library grows to significant complexity. -In LibTomMath the multiple precision integer functions accept parameters from left to right as pointers to mp\_int -structures. That means that the source (input) operands are placed on the left and the destination (output) on the right. -Consider the following examples. - -\begin{verbatim} - mp_mul(&a, &b, &c); /* c = a * b */ - mp_add(&a, &b, &a); /* a = a + b */ - mp_sqr(&a, &b); /* b = a * a */ -\end{verbatim} - -The left to right order is a fairly natural way to implement the functions since it lets the developer read aloud the -functions and make sense of them. For example, the first function would read ``multiply a and b and store in c''. - -Certain libraries (\textit{LIP by Lenstra for instance}) accept parameters the other way around, to mimic the order -of assignment expressions. That is, the destination (output) is on the left and arguments (inputs) are on the right. In -truth, it is entirely a matter of preference. In the case of LibTomMath the convention from the MPI library has been -adopted. - -Another very useful design consideration, provided for in LibTomMath, is whether to allow argument sources to also be a -destination. For example, the second example (\textit{mp\_add}) adds $a$ to $b$ and stores in $a$. This is an important -feature to implement since it allows the calling functions to cut down on the number of variables it must maintain. -However, to implement this feature specific care has to be given to ensure the destination is not modified before the -source is fully read. - -\section{Return Values} -A well implemented application, no matter what its purpose, should trap as many runtime errors as possible and return them -to the caller. By catching runtime errors a library can be guaranteed to prevent undefined behaviour. However, the end -developer can still manage to cause a library to crash. For example, by passing an invalid pointer an application may -fault by dereferencing memory not owned by the application. - -In the case of LibTomMath the only errors that are checked for are related to inappropriate inputs (division by zero for -instance) and memory allocation errors. It will not check that the mp\_int passed to any function is valid nor -will it check pointers for validity. Any function that can cause a runtime error will return an error code as an -\textbf{int} data type with one of the following values (fig \ref{fig:errcodes}). - -\index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM} -\begin{figure}[here] -\begin{center} -\begin{tabular}{|l|l|} -\hline \textbf{Value} & \textbf{Meaning} \\ -\hline \textbf{MP\_OKAY} & The function was successful \\ -\hline \textbf{MP\_VAL} & One of the input value(s) was invalid \\ -\hline \textbf{MP\_MEM} & The function ran out of heap memory \\ -\hline -\end{tabular} -\end{center} -\caption{LibTomMath Error Codes} -\label{fig:errcodes} -\end{figure} - -When an error is detected within a function it should free any memory it allocated, often during the initialization of -temporary mp\_ints, and return as soon as possible. The goal is to leave the system in the same state it was when the -function was called. Error checking with this style of API is fairly simple. - -\begin{verbatim} - int err; - if ((err = mp_add(&a, &b, &c)) != MP_OKAY) { - printf("Error: %s\n", mp_error_to_string(err)); - exit(EXIT_FAILURE); - } -\end{verbatim} - -The GMP \cite{GMP} library uses C style \textit{signals} to flag errors which is of questionable use. Not all errors are fatal -and it was not deemed ideal by the author of LibTomMath to force developers to have signal handlers for such cases. - -\section{Initialization and Clearing} -The logical starting point when actually writing multiple precision integer functions is the initialization and -clearing of the mp\_int structures. These two algorithms will be used by the majority of the higher level algorithms. - -Given the basic mp\_int structure an initialization routine must first allocate memory to hold the digits of -the integer. Often it is optimal to allocate a sufficiently large pre-set number of digits even though -the initial integer will represent zero. If only a single digit were allocated quite a few subsequent re-allocations -would occur when operations are performed on the integers. There is a tradeoff between how many default digits to allocate -and how many re-allocations are tolerable. Obviously allocating an excessive amount of digits initially will waste -memory and become unmanageable. - -If the memory for the digits has been successfully allocated then the rest of the members of the structure must -be initialized. Since the initial state of an mp\_int is to represent the zero integer, the allocated digits must be set -to zero. The \textbf{used} count set to zero and \textbf{sign} set to \textbf{MP\_ZPOS}. - -\subsection{Initializing an mp\_int} -An mp\_int is said to be initialized if it is set to a valid, preferably default, state such that all of the members of the -structure are set to valid values. The mp\_init algorithm will perform such an action. - -\index{mp\_init} -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_init}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. Allocate memory and initialize $a$ to a known valid mp\_int state. \\ -\hline \\ -1. Allocate memory for \textbf{MP\_PREC} digits. \\ -2. If the allocation failed return(\textit{MP\_MEM}) \\ -3. for $n$ from $0$ to $MP\_PREC - 1$ do \\ -\hspace{3mm}3.1 $a_n \leftarrow 0$\\ -4. $a.sign \leftarrow MP\_ZPOS$\\ -5. $a.used \leftarrow 0$\\ -6. $a.alloc \leftarrow MP\_PREC$\\ -7. Return(\textit{MP\_OKAY})\\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_init} -\end{figure} - -\textbf{Algorithm mp\_init.} -The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly -manipulte it. It is assumed that the input may not have had any of its members previously initialized which is certainly -a valid assumption if the input resides on the stack. - -Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for -the digits is allocated. If this fails the function returns before setting any of the other members. The \textbf{MP\_PREC} -name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.} -used to dictate the minimum precision of newly initialized mp\_int integers. Ideally, it is at least equal to the smallest -precision number you'll be working with. - -Allocating a block of digits at first instead of a single digit has the benefit of lowering the number of usually slow -heap operations later functions will have to perform in the future. If \textbf{MP\_PREC} is set correctly the slack -memory and the number of heap operations will be trivial. - -Once the allocation has been made the digits have to be set to zero as well as the \textbf{used}, \textbf{sign} and -\textbf{alloc} members initialized. This ensures that the mp\_int will always represent the default state of zero regardless -of the original condition of the input. - -\textbf{Remark.} -This function introduces the idiosyncrasy that all iterative loops, commonly initiated with the ``for'' keyword, iterate incrementally -when the ``to'' keyword is placed between two expressions. For example, ``for $a$ from $b$ to $c$ do'' means that -a subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$. In each -iteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$. If $b > c$ occured -the loop would not iterate. By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate -decrementally. - -EXAM,bn_mp_init.c - -One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure. It -is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack. The -call to mp\_init() is used only to initialize the members of the structure to a known default state. - -Here we see (line @23,XMALLOC@) the memory allocation is performed first. This allows us to exit cleanly and quickly -if there is an error. If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there -was a memory error. The function XMALLOC is what actually allocates the memory. Technically XMALLOC is not a function -but a macro defined in ``tommath.h``. By default, XMALLOC will evaluate to malloc() which is the C library's built--in -memory allocation routine. - -In order to assure the mp\_int is in a known state the digits must be set to zero. On most platforms this could have been -accomplished by using calloc() instead of malloc(). However, to correctly initialize a integer type to a given value in a -portable fashion you have to actually assign the value. The for loop (line @28,for@) performs this required -operation. - -After the memory has been successfully initialized the remainder of the members are initialized -(lines @29,used@ through @31,sign@) to their respective default states. At this point the algorithm has succeeded and -a success code is returned to the calling function. If this function returns \textbf{MP\_OKAY} it is safe to assume the -mp\_int structure has been properly initialized and is safe to use with other functions within the library. - -\subsection{Clearing an mp\_int} -When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be -returned to the application's memory pool with the mp\_clear algorithm. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_clear}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. The memory for $a$ shall be deallocated. \\ -\hline \\ -1. If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\ -2. for $n$ from 0 to $a.used - 1$ do \\ -\hspace{3mm}2.1 $a_n \leftarrow 0$ \\ -3. Free the memory allocated for the digits of $a$. \\ -4. $a.used \leftarrow 0$ \\ -5. $a.alloc \leftarrow 0$ \\ -6. $a.sign \leftarrow MP\_ZPOS$ \\ -7. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_clear} -\end{figure} - -\textbf{Algorithm mp\_clear.} -This algorithm accomplishes two goals. First, it clears the digits and the other mp\_int members. This ensures that -if a developer accidentally re-uses a cleared structure it is less likely to cause problems. The second goal -is to free the allocated memory. - -The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this -algorithm will not try to free the memory multiple times. Cleared mp\_ints are detectable by having a pre-defined invalid -digit pointer \textbf{dp} setting. - -Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm -with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear. - -EXAM,bn_mp_clear.c - -The algorithm only operates on the mp\_int if it hasn't been previously cleared. The if statement (line @23,a->dp != NULL@) -checks to see if the \textbf{dp} member is not \textbf{NULL}. If the mp\_int is a valid mp\_int then \textbf{dp} cannot be -\textbf{NULL} in which case the if statement will evaluate to true. - -The digits of the mp\_int are cleared by the for loop (line @25,for@) which assigns a zero to every digit. Similar to mp\_init() -the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable. - -The digits are deallocated off the heap via the XFREE macro. Similar to XMALLOC the XFREE macro actually evaluates to -a standard C library function. In this case the free() function. Since free() only deallocates the memory the pointer -still has to be reset to \textbf{NULL} manually (line @33,NULL@). - -Now that the digits have been cleared and deallocated the other members are set to their final values (lines @34,= 0@ and @35,ZPOS@). - -\section{Maintenance Algorithms} - -The previous sections describes how to initialize and clear an mp\_int structure. To further support operations -that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be -able to augment the precision of an mp\_int and -initialize mp\_ints with differing initial conditions. - -These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level -algorithms such as addition, multiplication and modular exponentiation. - -\subsection{Augmenting an mp\_int's Precision} -When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire -result of an operation without loss of precision. Quite often the size of the array given by the \textbf{alloc} member -is large enough to simply increase the \textbf{used} digit count. However, when the size of the array is too small it -must be re-sized appropriately to accomodate the result. The mp\_grow algorithm will provide this functionality. - -\newpage\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_grow}. \\ -\textbf{Input}. An mp\_int $a$ and an integer $b$. \\ -\textbf{Output}. $a$ is expanded to accomodate $b$ digits. \\ -\hline \\ -1. if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\ -2. $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\ -3. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\ -4. Re-allocate the array of digits $a$ to size $v$ \\ -5. If the allocation failed then return(\textit{MP\_MEM}). \\ -6. for n from a.alloc to $v - 1$ do \\ -\hspace{+3mm}6.1 $a_n \leftarrow 0$ \\ -7. $a.alloc \leftarrow v$ \\ -8. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_grow} -\end{figure} - -\textbf{Algorithm mp\_grow.} -It is ideal to prevent re-allocations from being performed if they are not required (step one). This is useful to -prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow. - -The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three). -This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values. - -It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact. This is much -akin to how the \textit{realloc} function from the standard C library works. Since the newly allocated digits are -assumed to contain undefined values they are initially set to zero. - -EXAM,bn_mp_grow.c - -A quick optimization is to first determine if a memory re-allocation is required at all. The if statement (line @24,alloc@) checks -if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count. If the count is not larger than \textbf{alloc} -the function skips the re-allocation part thus saving time. - -When a re-allocation is performed it is turned into an optimal request to save time in the future. The requested digit count is -padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line @25, size@). The XREALLOC function is used -to re-allocate the memory. As per the other functions XREALLOC is actually a macro which evaluates to realloc by default. The realloc -function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before -the re-allocation. All that is left is to clear the newly allocated digits and return. - -Note that the re-allocation result is actually stored in a temporary pointer $tmp$. This is to allow this function to return -an error with a valid pointer. Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$. That would -result in a memory leak if XREALLOC ever failed. - -\subsection{Initializing Variable Precision mp\_ints} -Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size -of input mp\_ints to a given algorithm. The purpose of algorithm mp\_init\_size is similar to mp\_init except that it -will allocate \textit{at least} a specified number of digits. - -\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_init\_size}. \\ -\textbf{Input}. An mp\_int $a$ and the requested number of digits $b$. \\ -\textbf{Output}. $a$ is initialized to hold at least $b$ digits. \\ -\hline \\ -1. $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\ -2. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\ -3. Allocate $v$ digits. \\ -4. for $n$ from $0$ to $v - 1$ do \\ -\hspace{3mm}4.1 $a_n \leftarrow 0$ \\ -5. $a.sign \leftarrow MP\_ZPOS$\\ -6. $a.used \leftarrow 0$\\ -7. $a.alloc \leftarrow v$\\ -8. Return(\textit{MP\_OKAY})\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_init\_size} -\end{figure} - -\textbf{Algorithm mp\_init\_size.} -This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of -digits allocated can be controlled by the second input argument $b$. The input size is padded upwards so it is a -multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits. This padding is used to prevent trivial -allocations from becoming a bottleneck in the rest of the algorithms. - -Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero. This -particular algorithm is useful if it is known ahead of time the approximate size of the input. If the approximation is -correct no further memory re-allocations are required to work with the mp\_int. - -EXAM,bn_mp_init_size.c - -The number of digits $b$ requested is padded (line @22,MP_PREC@) by first augmenting it to the next multiple of -\textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result. If the memory can be successfully allocated the -mp\_int is placed in a default state representing the integer zero. Otherwise, the error code \textbf{MP\_MEM} will be -returned (line @27,return@). - -The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@). The -\textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set -to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines @29,used@, @30,alloc@ and @31,sign@). If the function -returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the -functions to work with. - -\subsection{Multiple Integer Initializations and Clearings} -Occasionally a function will require a series of mp\_int data types to be made available simultaneously. -The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single -statement. It is essentially a shortcut to multiple initializations. - -\newpage\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_init\_multi}. \\ -\textbf{Input}. Variable length array $V_k$ of mp\_int variables of length $k$. \\ -\textbf{Output}. The array is initialized such that each mp\_int of $V_k$ is ready to use. \\ -\hline \\ -1. for $n$ from 0 to $k - 1$ do \\ -\hspace{+3mm}1.1. Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\ -\hspace{+3mm}1.2. If initialization failed then do \\ -\hspace{+6mm}1.2.1. for $j$ from $0$ to $n$ do \\ -\hspace{+9mm}1.2.1.1. Free the mp\_int $V_j$ (\textit{mp\_clear}) \\ -\hspace{+6mm}1.2.2. Return(\textit{MP\_MEM}) \\ -2. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_init\_multi} -\end{figure} - -\textbf{Algorithm mp\_init\_multi.} -The algorithm will initialize the array of mp\_int variables one at a time. If a runtime error has been detected -(\textit{step 1.2}) all of the previously initialized variables are cleared. The goal is an ``all or nothing'' -initialization which allows for quick recovery from runtime errors. - -EXAM,bn_mp_init_multi.c - -This function intializes a variable length list of mp\_int structure pointers. However, instead of having the mp\_int -structures in an actual C array they are simply passed as arguments to the function. This function makes use of the -``...'' argument syntax of the C programming language. The list is terminated with a final \textbf{NULL} argument -appended on the right. - -The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function. A count -$n$ of succesfully initialized mp\_int structures is maintained (line @47,n++@) such that if a failure does occur, -the algorithm can backtrack and free the previously initialized structures (lines @27,if@ to @46,}@). - - -\subsection{Clamping Excess Digits} -When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of -the function instead of checking during the computation. For example, a multiplication of a $i$ digit number by a -$j$ digit produces a result of at most $i + j$ digits. It is entirely possible that the result is $i + j - 1$ -though, with no final carry into the last position. However, suppose the destination had to be first expanded -(\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry. -That would be a considerable waste of time since heap operations are relatively slow. - -The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function -terminates. This way a single heap operation (\textit{at most}) is required. However, if the result was not checked -there would be an excess high order zero digit. - -For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$. The leading zero digit -will not contribute to the precision of the result. In fact, through subsequent operations more leading zero digits would -accumulate to the point the size of the integer would be prohibitive. As a result even though the precision is very -low the representation is excessively large. - -The mp\_clamp algorithm is designed to solve this very problem. It will trim high-order zeros by decrementing the -\textbf{used} count until a non-zero most significant digit is found. Also in this system, zero is considered to be a -positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to -\textbf{MP\_ZPOS}. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_clamp}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. Any excess leading zero digits of $a$ are removed \\ -\hline \\ -1. while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\ -\hspace{+3mm}1.1 $a.used \leftarrow a.used - 1$ \\ -2. if $a.used = 0$ then do \\ -\hspace{+3mm}2.1 $a.sign \leftarrow MP\_ZPOS$ \\ -\hline \\ -\end{tabular} -\end{center} -\caption{Algorithm mp\_clamp} -\end{figure} - -\textbf{Algorithm mp\_clamp.} -As can be expected this algorithm is very simple. The loop on step one is expected to iterate only once or twice at -the most. For example, this will happen in cases where there is not a carry to fill the last position. Step two fixes the sign for -when all of the digits are zero to ensure that the mp\_int is valid at all times. - -EXAM,bn_mp_clamp.c - -Note on line @27,while@ how to test for the \textbf{used} count is made on the left of the \&\& operator. In the C programming -language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails. This is -important since if the \textbf{used} is zero the test on the right would fetch below the array. That is obviously -undesirable. The parenthesis on line @28,a->used@ is used to make sure the \textbf{used} count is decremented and not -the pointer ``a''. - -\section*{Exercises} -\begin{tabular}{cl} -$\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\ - & \\ -$\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations. \\ - & \\ -$\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\ - & encryption when $\beta = 2^{28}$. \\ - & \\ -$\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp. What does it prevent? \\ - & \\ -$\left [ 1 \right ]$ & Give an example of when the algorithm mp\_init\_copy might be useful. \\ - & \\ -\end{tabular} - - -%%% -% CHAPTER FOUR -%%% - -\chapter{Basic Operations} - -\section{Introduction} -In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining -mp\_int structures. This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low -level basis of the entire library. While these algorithm are relatively trivial it is important to understand how they -work before proceeding since these algorithms will be used almost intrinsically in the following chapters. - -The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of -mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures -represent. - -\section{Assigning Values to mp\_int Structures} -\subsection{Copying an mp\_int} -Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making -a copy for the purposes of this text. The copy of the mp\_int will be a separate entity that represents the same -value as the mp\_int it was copied from. The mp\_copy algorithm provides this functionality. - -\newpage\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_copy}. \\ -\textbf{Input}. An mp\_int $a$ and $b$. \\ -\textbf{Output}. Store a copy of $a$ in $b$. \\ -\hline \\ -1. If $b.alloc < a.used$ then grow $b$ to $a.used$ digits. (\textit{mp\_grow}) \\ -2. for $n$ from 0 to $a.used - 1$ do \\ -\hspace{3mm}2.1 $b_{n} \leftarrow a_{n}$ \\ -3. for $n$ from $a.used$ to $b.used - 1$ do \\ -\hspace{3mm}3.1 $b_{n} \leftarrow 0$ \\ -4. $b.used \leftarrow a.used$ \\ -5. $b.sign \leftarrow a.sign$ \\ -6. return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_copy} -\end{figure} - -\textbf{Algorithm mp\_copy.} -This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will -represent the same integer as the mp\_int $a$. The mp\_int $b$ shall be a complete and distinct copy of the -mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$. - -If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow -algorithm. The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two -and three). The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of -$b$. - -\textbf{Remark.} This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the -text. The error return codes of other algorithms are not explicitly checked in the pseudo-code presented. For example, in -step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded. Text space is -limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return -the error code itself. However, the C code presented will demonstrate all of the error handling logic required to -implement the pseudo-code. - -EXAM,bn_mp_copy.c - -Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output -mp\_int structures passed to a function are one and the same. For this case it is optimal to return immediately without -copying digits (line @24,a == b@). - -The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$. If $b.alloc$ is less than -$a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines @29,alloc@ to @33,}@). In order to -simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits -of the mp\_ints $a$ and $b$ respectively. These aliases (lines @42,tmpa@ and @45,tmpb@) allow the compiler to access the digits without first dereferencing the -mp\_int pointers and then subsequently the pointer to the digits. - -After the aliases are established the digits from $a$ are copied into $b$ (lines @48,for@ to @50,}@) and then the excess -digits of $b$ are set to zero (lines @53,for@ to @55,}@). Both ``for'' loops make use of the pointer aliases and in -fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits. This optimization -allows the alias to stay in a machine register fairly easy between the two loops. - -\textbf{Remarks.} The use of pointer aliases is an implementation methodology first introduced in this function that will -be used considerably in other functions. Technically, a pointer alias is simply a short hand alias used to lower the -number of pointer dereferencing operations required to access data. For example, a for loop may resemble - -\begin{alltt} -for (x = 0; x < 100; x++) \{ - a->num[4]->dp[x] = 0; -\} -\end{alltt} - -This could be re-written using aliases as - -\begin{alltt} -mp_digit *tmpa; -a = a->num[4]->dp; -for (x = 0; x < 100; x++) \{ - *a++ = 0; -\} -\end{alltt} - -In this case an alias is used to access the -array of digits within an mp\_int structure directly. It may seem that a pointer alias is strictly not required -as a compiler may optimize out the redundant pointer operations. However, there are two dominant reasons to use aliases. - -The first reason is that most compilers will not effectively optimize pointer arithmetic. For example, some optimizations -may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC). Also some optimizations may -work for GCC and not MSVC. As such it is ideal to find a common ground for as many compilers as possible. Pointer -aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code -stands a better chance of being faster. - -The second reason is that pointer aliases often can make an algorithm simpler to read. Consider the first ``for'' -loop of the function mp\_copy() re-written to not use pointer aliases. - -\begin{alltt} - /* copy all the digits */ - for (n = 0; n < a->used; n++) \{ - b->dp[n] = a->dp[n]; - \} -\end{alltt} - -Whether this code is harder to read depends strongly on the individual. However, it is quantifiably slightly more -complicated as there are four variables within the statement instead of just two. - -\subsubsection{Nested Statements} -Another commonly used technique in the source routines is that certain sections of code are nested. This is used in -particular with the pointer aliases to highlight code phases. For example, a Comba multiplier (discussed in chapter six) -will typically have three different phases. First the temporaries are initialized, then the columns calculated and -finally the carries are propagated. In this example the middle column production phase will typically be nested as it -uses temporary variables and aliases the most. - -The nesting also simplies the source code as variables that are nested are only valid for their scope. As a result -the various temporary variables required do not propagate into other sections of code. - - -\subsection{Creating a Clone} -Another common operation is to make a local temporary copy of an mp\_int argument. To initialize an mp\_int -and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone. This is -useful within functions that need to modify an argument but do not wish to actually modify the original copy. The -mp\_init\_copy algorithm has been designed to help perform this task. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_init\_copy}. \\ -\textbf{Input}. An mp\_int $a$ and $b$\\ -\textbf{Output}. $a$ is initialized to be a copy of $b$. \\ -\hline \\ -1. Init $a$. (\textit{mp\_init}) \\ -2. Copy $b$ to $a$. (\textit{mp\_copy}) \\ -3. Return the status of the copy operation. \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_init\_copy} -\end{figure} - -\textbf{Algorithm mp\_init\_copy.} -This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it. As -such this algorithm will perform two operations in one step. - -EXAM,bn_mp_init_copy.c - -This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}. Note that -\textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call -and \textbf{a} will be left intact. - -\section{Zeroing an Integer} -Reseting an mp\_int to the default state is a common step in many algorithms. The mp\_zero algorithm will be the algorithm used to -perform this task. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_zero}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. Zero the contents of $a$ \\ -\hline \\ -1. $a.used \leftarrow 0$ \\ -2. $a.sign \leftarrow$ MP\_ZPOS \\ -3. for $n$ from 0 to $a.alloc - 1$ do \\ -\hspace{3mm}3.1 $a_n \leftarrow 0$ \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_zero} -\end{figure} - -\textbf{Algorithm mp\_zero.} -This algorithm simply resets a mp\_int to the default state. - -EXAM,bn_mp_zero.c - -After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the -\textbf{sign} variable is set to \textbf{MP\_ZPOS}. - -\section{Sign Manipulation} -\subsection{Absolute Value} -With the mp\_int representation of an integer, calculating the absolute value is trivial. The mp\_abs algorithm will compute -the absolute value of an mp\_int. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_abs}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. Computes $b = \vert a \vert$ \\ -\hline \\ -1. Copy $a$ to $b$. (\textit{mp\_copy}) \\ -2. If the copy failed return(\textit{MP\_MEM}). \\ -3. $b.sign \leftarrow MP\_ZPOS$ \\ -4. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_abs} -\end{figure} - -\textbf{Algorithm mp\_abs.} -This algorithm computes the absolute of an mp\_int input. First it copies $a$ over $b$. This is an example of an -algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful. This allows, -for instance, the developer to pass the same mp\_int as the source and destination to this function without addition -logic to handle it. - -EXAM,bn_mp_abs.c - -This fairly trivial algorithm first eliminates non--required duplications (line @27,a != b@) and then sets the -\textbf{sign} flag to \textbf{MP\_ZPOS}. - -\subsection{Integer Negation} -With the mp\_int representation of an integer, calculating the negation is also trivial. The mp\_neg algorithm will compute -the negative of an mp\_int input. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_neg}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. Computes $b = -a$ \\ -\hline \\ -1. Copy $a$ to $b$. (\textit{mp\_copy}) \\ -2. If the copy failed return(\textit{MP\_MEM}). \\ -3. If $a.used = 0$ then return(\textit{MP\_OKAY}). \\ -4. If $a.sign = MP\_ZPOS$ then do \\ -\hspace{3mm}4.1 $b.sign = MP\_NEG$. \\ -5. else do \\ -\hspace{3mm}5.1 $b.sign = MP\_ZPOS$. \\ -6. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_neg} -\end{figure} - -\textbf{Algorithm mp\_neg.} -This algorithm computes the negation of an input. First it copies $a$ over $b$. If $a$ has no used digits then -the algorithm returns immediately. Otherwise it flips the sign flag and stores the result in $b$. Note that if -$a$ had no digits then it must be positive by definition. Had step three been omitted then the algorithm would return -zero as negative. - -EXAM,bn_mp_neg.c - -Like mp\_abs() this function avoids non--required duplications (line @21,a != b@) and then sets the sign. We -have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}. If the mp\_int is zero -than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}. - -\section{Small Constants} -\subsection{Setting Small Constants} -Often a mp\_int must be set to a relatively small value such as $1$ or $2$. For these cases the mp\_set algorithm is useful. - -\newpage\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_set}. \\ -\textbf{Input}. An mp\_int $a$ and a digit $b$ \\ -\textbf{Output}. Make $a$ equivalent to $b$ \\ -\hline \\ -1. Zero $a$ (\textit{mp\_zero}). \\ -2. $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\ -3. $a.used \leftarrow \left \lbrace \begin{array}{ll} - 1 & \mbox{if }a_0 > 0 \\ - 0 & \mbox{if }a_0 = 0 - \end{array} \right .$ \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_set} -\end{figure} - -\textbf{Algorithm mp\_set.} -This algorithm sets a mp\_int to a small single digit value. Step number 1 ensures that the integer is reset to the default state. The -single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly. - -EXAM,bn_mp_set.c - -First we zero (line @21,mp_zero@) the mp\_int to make sure that the other members are initialized for a -small positive constant. mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count -is zero. Next we set the digit and reduce it modulo $\beta$ (line @22,MP_MASK@). After this step we have to -check if the resulting digit is zero or not. If it is not then we set the \textbf{used} count to one, otherwise -to zero. - -We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with -$2^k - 1$ will perform the same operation. - -One important limitation of this function is that it will only set one digit. The size of a digit is not fixed, meaning source that uses -this function should take that into account. Only trivially small constants can be set using this function. - -\subsection{Setting Large Constants} -To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal. It accepts a ``long'' -data type as input and will always treat it as a 32-bit integer. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_set\_int}. \\ -\textbf{Input}. An mp\_int $a$ and a ``long'' integer $b$ \\ -\textbf{Output}. Make $a$ equivalent to $b$ \\ -\hline \\ -1. Zero $a$ (\textit{mp\_zero}) \\ -2. for $n$ from 0 to 7 do \\ -\hspace{3mm}2.1 $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\ -\hspace{3mm}2.2 $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\ -\hspace{3mm}2.3 $a_0 \leftarrow a_0 + u$ \\ -\hspace{3mm}2.4 $a.used \leftarrow a.used + 1$ \\ -3. Clamp excess used digits (\textit{mp\_clamp}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_set\_int} -\end{figure} - -\textbf{Algorithm mp\_set\_int.} -The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the -mp\_int. Step 2.1 will multiply the current result by sixteen making room for four more bits in the less significant positions. In step 2.2 the -next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is -incremented to reflect the addition. The \textbf{used} digit counter is incremented since if any of the leading digits were zero the mp\_int would have -zero digits used and the newly added four bits would be ignored. - -Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp. - -EXAM,bn_mp_set_int.c - -This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes. The weird -addition on line @38,a->used@ ensures that the newly added in bits are added to the number of digits. While it may not -seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line @27,mp_mul_2d@ -as well as the call to mp\_clamp() on line @40,mp_clamp@. Both functions will clamp excess leading digits which keeps -the number of used digits low. - -\section{Comparisons} -\subsection{Unsigned Comparisions} -Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers. For example, -to compare $1,234$ to $1,264$ the digits are extracted by their positions. That is we compare $1 \cdot 10^3 + 2 \cdot 10^2 + 3 \cdot 10^1 + 4 \cdot 10^0$ -to $1 \cdot 10^3 + 2 \cdot 10^2 + 6 \cdot 10^1 + 4 \cdot 10^0$ by comparing single digits at a time starting with the highest magnitude -positions. If any leading digit of one integer is greater than a digit in the same position of another integer then obviously it must be greater. - -The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two -mp\_int variables alone. It will ignore the sign of the two inputs. Such a function is useful when an absolute comparison is required or if the -signs are known to agree in advance. - -To facilitate working with the results of the comparison functions three constants are required. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{|r|l|} -\hline \textbf{Constant} & \textbf{Meaning} \\ -\hline \textbf{MP\_GT} & Greater Than \\ -\hline \textbf{MP\_EQ} & Equal To \\ -\hline \textbf{MP\_LT} & Less Than \\ -\hline -\end{tabular} -\end{center} -\caption{Comparison Return Codes} -\end{figure} - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_cmp\_mag}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$. \\ -\textbf{Output}. Unsigned comparison results ($a$ to the left of $b$). \\ -\hline \\ -1. If $a.used > b.used$ then return(\textit{MP\_GT}) \\ -2. If $a.used < b.used$ then return(\textit{MP\_LT}) \\ -3. for n from $a.used - 1$ to 0 do \\ -\hspace{+3mm}3.1 if $a_n > b_n$ then return(\textit{MP\_GT}) \\ -\hspace{+3mm}3.2 if $a_n < b_n$ then return(\textit{MP\_LT}) \\ -4. Return(\textit{MP\_EQ}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_cmp\_mag} -\end{figure} - -\textbf{Algorithm mp\_cmp\_mag.} -By saying ``$a$ to the left of $b$'' it is meant that the comparison is with respect to $a$, that is if $a$ is greater than $b$ it will return -\textbf{MP\_GT} and similar with respect to when $a = b$ and $a < b$. The first two steps compare the number of digits used in both $a$ and $b$. -Obviously if the digit counts differ there would be an imaginary zero digit in the smaller number where the leading digit of the larger number is. -If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit. - -By step three both inputs must have the same number of digits so its safe to start from either $a.used - 1$ or $b.used - 1$ and count down to -the zero'th digit. If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}. - -EXAM,bn_mp_cmp_mag.c - -The two if statements (lines @24,if@ and @28,if@) compare the number of digits in the two inputs. These two are -performed before all of the digits are compared since it is a very cheap test to perform and can potentially save -considerable time. The implementation given is also not valid without those two statements. $b.alloc$ may be -smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits. - - - -\subsection{Signed Comparisons} -Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}). Based on an unsigned magnitude -comparison a trivial signed comparison algorithm can be written. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_cmp}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$ \\ -\textbf{Output}. Signed Comparison Results ($a$ to the left of $b$) \\ -\hline \\ -1. if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\ -2. if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\ -3. if $a.sign = MP\_NEG$ then \\ -\hspace{+3mm}3.1 Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\ -4 Otherwise \\ -\hspace{+3mm}4.1 Return the unsigned comparison of $a$ and $b$ \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_cmp} -\end{figure} - -\textbf{Algorithm mp\_cmp.} -The first two steps compare the signs of the two inputs. If the signs do not agree then it can return right away with the appropriate -comparison code. When the signs are equal the digits of the inputs must be compared to determine the correct result. In step -three the unsigned comparision flips the order of the arguments since they are both negative. For instance, if $-a > -b$ then -$\vert a \vert < \vert b \vert$. Step number four will compare the two when they are both positive. - -EXAM,bn_mp_cmp.c - -The two if statements (lines @22,if@ and @26,if@) perform the initial sign comparison. If the signs are not the equal then which ever -has the positive sign is larger. The inputs are compared (line @30,if@) based on magnitudes. If the signs were both -negative then the unsigned comparison is performed in the opposite direction (line @31,mp_cmp_mag@). Otherwise, the signs are assumed to -be both positive and a forward direction unsigned comparison is performed. - -\section*{Exercises} -\begin{tabular}{cl} -$\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\ - & \\ -$\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits \\ - & of two random digits (of equal magnitude) before a difference is found. \\ - & \\ -$\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based \\ - & on the observations made in the previous problem. \\ - & -\end{tabular} - -\chapter{Basic Arithmetic} -\section{Introduction} -At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been -established. The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms. These -algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms. It is very important -that these algorithms are highly optimized. On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms -which easily places them at $O(n^2)$ or even $O(n^3)$ work levels. - -MARK,SHIFTS -All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right -logical shifts respectively. A logical shift is analogous to sliding the decimal point of radix-10 representations. For example, the real -number $0.9345$ is equivalent to $93.45\%$ which is found by sliding the the decimal two places to the right (\textit{multiplying by $\beta^2 = 10^2$}). -Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two. -For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$. - -One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed -from the number. For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$. However, with a logical shift the -result is $110_2$. - -\section{Addition and Subtraction} -In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus. For example, with 32-bit integers -$a - b\mbox{ (mod }2^{32}\mbox{)}$ is the same as $a + (2^{32} - b) \mbox{ (mod }2^{32}\mbox{)}$ since $2^{32} \equiv 0 \mbox{ (mod }2^{32}\mbox{)}$. -As a result subtraction can be performed with a trivial series of logical operations and an addition. - -However, in multiple precision arithmetic negative numbers are not represented in the same way. Instead a sign flag is used to keep track of the -sign of the integer. As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or -subtraction algorithms with the sign fixed up appropriately. - -The lower level algorithms will add or subtract integers without regard to the sign flag. That is they will add or subtract the magnitude of -the integers respectively. - -\subsection{Low Level Addition} -An unsigned addition of multiple precision integers is performed with the same long-hand algorithm used to add decimal numbers. That is to add the -trailing digits first and propagate the resulting carry upwards. Since this is a lower level algorithm the name will have a ``s\_'' prefix. -Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely. - -\newpage -\begin{figure}[!here] -\begin{center} -\begin{small} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_add}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$ \\ -\textbf{Output}. The unsigned addition $c = \vert a \vert + \vert b \vert$. \\ -\hline \\ -1. if $a.used > b.used$ then \\ -\hspace{+3mm}1.1 $min \leftarrow b.used$ \\ -\hspace{+3mm}1.2 $max \leftarrow a.used$ \\ -\hspace{+3mm}1.3 $x \leftarrow a$ \\ -2. else \\ -\hspace{+3mm}2.1 $min \leftarrow a.used$ \\ -\hspace{+3mm}2.2 $max \leftarrow b.used$ \\ -\hspace{+3mm}2.3 $x \leftarrow b$ \\ -3. If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\ -4. $oldused \leftarrow c.used$ \\ -5. $c.used \leftarrow max + 1$ \\ -6. $u \leftarrow 0$ \\ -7. for $n$ from $0$ to $min - 1$ do \\ -\hspace{+3mm}7.1 $c_n \leftarrow a_n + b_n + u$ \\ -\hspace{+3mm}7.2 $u \leftarrow c_n >> lg(\beta)$ \\ -\hspace{+3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ -8. if $min \ne max$ then do \\ -\hspace{+3mm}8.1 for $n$ from $min$ to $max - 1$ do \\ -\hspace{+6mm}8.1.1 $c_n \leftarrow x_n + u$ \\ -\hspace{+6mm}8.1.2 $u \leftarrow c_n >> lg(\beta)$ \\ -\hspace{+6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ -9. $c_{max} \leftarrow u$ \\ -10. if $olduse > max$ then \\ -\hspace{+3mm}10.1 for $n$ from $max + 1$ to $oldused - 1$ do \\ -\hspace{+6mm}10.1.1 $c_n \leftarrow 0$ \\ -11. Clamp excess digits in $c$. (\textit{mp\_clamp}) \\ -12. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Algorithm s\_mp\_add} -\end{figure} - -\textbf{Algorithm s\_mp\_add.} -This algorithm is loosely based on algorithm 14.7 of HAC \cite[pp. 594]{HAC} but has been extended to allow the inputs to have different magnitudes. -Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}. Even the -MIX pseudo machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes. - -The first thing that has to be accomplished is to sort out which of the two inputs is the largest. The addition logic -will simply add all of the smallest input to the largest input and store that first part of the result in the -destination. Then it will apply a simpler addition loop to excess digits of the larger input. - -The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two -inputs. The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the -same number of digits. After the inputs are sorted the destination $c$ is grown as required to accomodate the sum -of the two inputs. The original \textbf{used} count of $c$ is copied and set to the new used count. - -At this point the first addition loop will go through as many digit positions that both inputs have. The carry -variable $\mu$ is set to zero outside the loop. Inside the loop an ``addition'' step requires three statements to produce -one digit of the summand. First -two digits from $a$ and $b$ are added together along with the carry $\mu$. The carry of this step is extracted and stored -in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$. - -Now all of the digit positions that both inputs have in common have been exhausted. If $min \ne max$ then $x$ is an alias -for one of the inputs that has more digits. A simplified addition loop is then used to essentially copy the remaining digits -and the carry to the destination. - -The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition. - - -EXAM,bn_s_mp_add.c - -We first sort (lines @27,if@ to @35,}@) the inputs based on magnitude and determine the $min$ and $max$ variables. -Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias. Next we -grow the destination (@37,init@ to @42,}@) ensure that it can accomodate the result of the addition. - -Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style. The three aliases that are on -lines @56,tmpa@, @59,tmpb@ and @62,tmpc@ represent the two inputs and destination variables respectively. These aliases are used to ensure the -compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int. - -The initial carry $u$ will be cleared (line @65,u = 0@), note that $u$ is of type mp\_digit which ensures type -compatibility within the implementation. The initial addition (line @66,for@ to @75,}@) adds digits from -both inputs until the smallest input runs out of digits. Similarly the conditional addition loop -(line @81,for@ to @90,}@) adds the remaining digits from the larger of the two inputs. The addition is finished -with the final carry being stored in $tmpc$ (line @94,tmpc++@). Note the ``++'' operator within the same expression. -After line @94,tmpc++@, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$. This is useful -for the next loop (line @97,for@ to @99,}@) which set any old upper digits to zero. - -\subsection{Low Level Subtraction} -The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm. The principle difference is that the -unsigned subtraction algorithm requires the result to be positive. That is when computing $a - b$ the condition $\vert a \vert \ge \vert b\vert$ must -be met for this algorithm to function properly. Keep in mind this low level algorithm is not meant to be used in higher level algorithms directly. -This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms. - -MARK,GAMMA - -For this algorithm a new variable is required to make the description simpler. Recall from section 1.3.1 that a mp\_digit must be able to represent -the range $0 \le x < 2\beta$ for the algorithms to work correctly. However, it is allowable that a mp\_digit represent a larger range of values. For -this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a -mp\_digit (\textit{this implies $2^{\gamma} > \beta$}). - -For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$. In ISO C an ``unsigned long'' -data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$. - -\newpage\begin{figure}[!here] -\begin{center} -\begin{small} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_sub}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\ -\textbf{Output}. The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\ -\hline \\ -1. $min \leftarrow b.used$ \\ -2. $max \leftarrow a.used$ \\ -3. If $c.alloc < max$ then grow $c$ to hold at least $max$ digits. (\textit{mp\_grow}) \\ -4. $oldused \leftarrow c.used$ \\ -5. $c.used \leftarrow max$ \\ -6. $u \leftarrow 0$ \\ -7. for $n$ from $0$ to $min - 1$ do \\ -\hspace{3mm}7.1 $c_n \leftarrow a_n - b_n - u$ \\ -\hspace{3mm}7.2 $u \leftarrow c_n >> (\gamma - 1)$ \\ -\hspace{3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ -8. if $min < max$ then do \\ -\hspace{3mm}8.1 for $n$ from $min$ to $max - 1$ do \\ -\hspace{6mm}8.1.1 $c_n \leftarrow a_n - u$ \\ -\hspace{6mm}8.1.2 $u \leftarrow c_n >> (\gamma - 1)$ \\ -\hspace{6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ -9. if $oldused > max$ then do \\ -\hspace{3mm}9.1 for $n$ from $max$ to $oldused - 1$ do \\ -\hspace{6mm}9.1.1 $c_n \leftarrow 0$ \\ -10. Clamp excess digits of $c$. (\textit{mp\_clamp}). \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Algorithm s\_mp\_sub} -\end{figure} - -\textbf{Algorithm s\_mp\_sub.} -This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive. That is when -passing variables $a$ and $b$ the condition that $\vert a \vert \ge \vert b \vert$ must be met for the algorithm to function correctly. This -algorithm is loosely based on algorithm 14.9 \cite[pp. 595]{HAC} and is similar to algorithm S in \cite[pp. 267]{TAOCPV2} as well. As was the case -of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude. - -The initial sorting of the inputs is trivial in this algorithm since $a$ is guaranteed to have at least the same magnitude of $b$. Steps 1 and 2 -set the $min$ and $max$ variables. Unlike the addition routine there is guaranteed to be no carry which means that the final result can be at -most $max$ digits in length as opposed to $max + 1$. Similar to the addition algorithm the \textbf{used} count of $c$ is copied locally and -set to the maximal count for the operation. - -The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision -subtraction is used instead. Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction -loops. Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry. - -For example, consider subtracting $0101_2$ from $0100_2$ where $\gamma = 4$ and $\beta = 2$. The least significant bit will force a carry upwards to -the third bit which will be set to zero after the borrow. After the very first bit has been subtracted $4 - 1 \equiv 0011_2$ will remain, When the -third bit of $0101_2$ is subtracted from the result it will cause another carry. In this case though the carry will be forced to propagate all the -way to the most significant bit. - -Recall that $\beta < 2^{\gamma}$. This means that if a carry does occur just before the $lg(\beta)$'th bit it will propagate all the way to the most -significant bit. Thus, the high order bits of the mp\_digit that are not part of the actual digit will either be all zero, or all one. All that -is needed is a single zero or one bit for the carry. Therefore a single logical shift right by $\gamma - 1$ positions is sufficient to extract the -carry. This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed. - -If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and copy operation to propagate through the larger input $a$ into $c$. Step -10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed. - -EXAM,bn_s_mp_sub.c - -Like low level addition we ``sort'' the inputs. Except in this case the sorting is hardcoded -(lines @24,min@ and @25,max@). In reality the $min$ and $max$ variables are only aliases and are only -used to make the source code easier to read. Again the pointer alias optimization is used -within this algorithm. The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized -(lines @42,tmpa@, @43,tmpb@ and @44,tmpc@) for $a$, $b$ and $c$ respectively. - -The first subtraction loop (lines @47,u = 0@ through @61,}@) subtract digits from both inputs until the smaller of -the two inputs has been exhausted. As remarked earlier there is an implementation reason for using the ``awkward'' -method of extracting the carry (line @57, >>@). The traditional method for extracting the carry would be to shift -by $lg(\beta)$ positions and logically AND the least significant bit. The AND operation is required because all of -the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction. This carry -extraction requires two relatively cheap operations to extract the carry. The other method is to simply shift the -most significant bit to the least significant bit thus extracting the carry with a single cheap operation. This -optimization only works on twos compliment machines which is a safe assumption to make. - -If $a$ has a larger magnitude than $b$ an additional loop (lines @64,for@ through @73,}@) is required to propagate -the carry through $a$ and copy the result to $c$. - -\subsection{High Level Addition} -Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be -established. This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data -types. - -Recall from section 5.2 that an mp\_int represents an integer with an unsigned mantissa (\textit{the array of digits}) and a \textbf{sign} -flag. A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases. - -\begin{figure}[!here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_add}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$ \\ -\textbf{Output}. The signed addition $c = a + b$. \\ -\hline \\ -1. if $a.sign = b.sign$ then do \\ -\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\ -\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\ -2. else do \\ -\hspace{3mm}2.1 if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\ -\hspace{6mm}2.1.1 $c.sign \leftarrow b.sign$ \\ -\hspace{6mm}2.1.2 $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\ -\hspace{3mm}2.2 else do \\ -\hspace{6mm}2.2.1 $c.sign \leftarrow a.sign$ \\ -\hspace{6mm}2.2.2 $c \leftarrow \vert a \vert - \vert b \vert$ \\ -3. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_add} -\end{figure} - -\textbf{Algorithm mp\_add.} -This algorithm performs the signed addition of two mp\_int variables. There is no reference algorithm to draw upon from -either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations. The algorithm is fairly -straightforward but restricted since subtraction can only produce positive results. - -\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{|c|c|c|c|c|} -\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\ -\hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\ -\hline $+$ & $+$ & No & $c = a + b$ & $a.sign$ \\ -\hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\ -\hline $-$ & $-$ & No & $c = a + b$ & $a.sign$ \\ -\hline &&&&\\ - -\hline $+$ & $-$ & No & $c = b - a$ & $b.sign$ \\ -\hline $-$ & $+$ & No & $c = b - a$ & $b.sign$ \\ - -\hline &&&&\\ - -\hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\ -\hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\ - -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Addition Guide Chart} -\label{fig:AddChart} -\end{figure} - -Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three -specific cases need to be handled. The return code of the unsigned operations at step 1.2, 2.1.2 and 2.2.2 are -forwarded to step three to check for errors. This simplifies the description of the algorithm considerably and best -follows how the implementation actually was achieved. - -Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed. Recall from the descriptions of algorithms -s\_mp\_add and s\_mp\_sub that the mp\_clamp function is used at the end to trim excess digits. The mp\_clamp algorithm will set the \textbf{sign} -to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero. - -For example, consider performing $-a + a$ with algorithm mp\_add. By the description of the algorithm the sign is set to \textbf{MP\_NEG} which would -produce a result of $-0$. However, since the sign is set first then the unsigned addition is performed the subsequent usage of algorithm mp\_clamp -within algorithm s\_mp\_add will force $-0$ to become $0$. - -EXAM,bn_mp_add.c - -The source code follows the algorithm fairly closely. The most notable new source code addition is the usage of the $res$ integer variable which -is used to pass result of the unsigned operations forward. Unlike in the algorithm, the variable $res$ is merely returned as is without -explicitly checking it and returning the constant \textbf{MP\_OKAY}. The observation is this algorithm will succeed or fail only if the lower -level functions do so. Returning their return code is sufficient. - -\subsection{High Level Subtraction} -The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm. - -\newpage\begin{figure}[!here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_sub}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$ \\ -\textbf{Output}. The signed subtraction $c = a - b$. \\ -\hline \\ -1. if $a.sign \ne b.sign$ then do \\ -\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\ -\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\ -2. else do \\ -\hspace{3mm}2.1 if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\ -\hspace{6mm}2.1.1 $c.sign \leftarrow a.sign$ \\ -\hspace{6mm}2.1.2 $c \leftarrow \vert a \vert - \vert b \vert$ (\textit{s\_mp\_sub}) \\ -\hspace{3mm}2.2 else do \\ -\hspace{6mm}2.2.1 $c.sign \leftarrow \left \lbrace \begin{array}{ll} - MP\_ZPOS & \mbox{if }a.sign = MP\_NEG \\ - MP\_NEG & \mbox{otherwise} \\ - \end{array} \right .$ \\ -\hspace{6mm}2.2.2 $c \leftarrow \vert b \vert - \vert a \vert$ \\ -3. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_sub} -\end{figure} - -\textbf{Algorithm mp\_sub.} -This algorithm performs the signed subtraction of two inputs. Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or -\cite{HAC}. Also this algorithm is restricted by algorithm s\_mp\_sub. Chart \ref{fig:SubChart} lists the eight possible inputs and -the operations required. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{|c|c|c|c|c|} -\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\ -\hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\ -\hline $+$ & $-$ & No & $c = a + b$ & $a.sign$ \\ -\hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\ -\hline $-$ & $+$ & No & $c = a + b$ & $a.sign$ \\ -\hline &&&& \\ -\hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\ -\hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\ -\hline &&&& \\ -\hline $+$ & $+$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\ -\hline $-$ & $-$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Subtraction Guide Chart} -\label{fig:SubChart} -\end{figure} - -Similar to the case of algorithm mp\_add the \textbf{sign} is set first before the unsigned addition or subtraction. That is to prevent the -algorithm from producing $-a - -a = -0$ as a result. - -EXAM,bn_mp_sub.c - -Much like the implementation of algorithm mp\_add the variable $res$ is used to catch the return code of the unsigned addition or subtraction operations -and forward it to the end of the function. On line @38, != MP_LT@ the ``not equal to'' \textbf{MP\_LT} expression is used to emulate a -``greater than or equal to'' comparison. - -\section{Bit and Digit Shifting} -MARK,POLY -It is quite common to think of a multiple precision integer as a polynomial in $x$, that is $y = f(\beta)$ where $f(x) = \sum_{i=0}^{n-1} a_i x^i$. -This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring. - -In order to facilitate operations on polynomials in $x$ as above a series of simple ``digit'' algorithms have to be established. That is to shift -the digits left or right as well to shift individual bits of the digits left and right. It is important to note that not all ``shift'' operations -are on radix-$\beta$ digits. - -\subsection{Multiplication by Two} - -In a binary system where the radix is a power of two multiplication by two not only arises often in other algorithms it is a fairly efficient -operation to perform. A single precision logical shift left is sufficient to multiply a single digit by two. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_mul\_2}. \\ -\textbf{Input}. One mp\_int $a$ \\ -\textbf{Output}. $b = 2a$. \\ -\hline \\ -1. If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits. (\textit{mp\_grow}) \\ -2. $oldused \leftarrow b.used$ \\ -3. $b.used \leftarrow a.used$ \\ -4. $r \leftarrow 0$ \\ -5. for $n$ from 0 to $a.used - 1$ do \\ -\hspace{3mm}5.1 $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\ -\hspace{3mm}5.2 $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}5.3 $r \leftarrow rr$ \\ -6. If $r \ne 0$ then do \\ -\hspace{3mm}6.1 $b_{n + 1} \leftarrow r$ \\ -\hspace{3mm}6.2 $b.used \leftarrow b.used + 1$ \\ -7. If $b.used < oldused - 1$ then do \\ -\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\ -\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\ -8. $b.sign \leftarrow a.sign$ \\ -9. Return(\textit{MP\_OKAY}).\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_mul\_2} -\end{figure} - -\textbf{Algorithm mp\_mul\_2.} -This algorithm will quickly multiply a mp\_int by two provided $\beta$ is a power of two. Neither \cite{TAOCPV2} nor \cite{HAC} describe such -an algorithm despite the fact it arises often in other algorithms. The algorithm is setup much like the lower level algorithm s\_mp\_add since -it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$. - -Step 1 and 2 grow the input as required to accomodate the maximum number of \textbf{used} digits in the result. The initial \textbf{used} count -is set to $a.used$ at step 4. Only if there is a final carry will the \textbf{used} count require adjustment. - -Step 6 is an optimization implementation of the addition loop for this specific case. That is since the two values being added together -are the same there is no need to perform two reads from the digits of $a$. Step 6.1 performs a single precision shift on the current digit $a_n$ to -obtain what will be the carry for the next iteration. Step 6.2 calculates the $n$'th digit of the result as single precision shift of $a_n$ plus -the previous carry. Recall from ~SHIFTS~ that $a_n << 1$ is equivalent to $a_n \cdot 2$. An iteration of the addition loop is finished with -forwarding the carry to the next iteration. - -Step 7 takes care of any final carry by setting the $a.used$'th digit of the result to the carry and augmenting the \textbf{used} count of $b$. -Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$. - -EXAM,bn_mp_mul_2.c - -This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input. The only noteworthy difference -is the use of the logical shift operator on line @52,<<@ to perform a single precision doubling. - -\subsection{Division by Two} -A division by two can just as easily be accomplished with a logical shift right as multiplication by two can be with a logical shift left. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_div\_2}. \\ -\textbf{Input}. One mp\_int $a$ \\ -\textbf{Output}. $b = a/2$. \\ -\hline \\ -1. If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits. (\textit{mp\_grow}) \\ -2. If the reallocation failed return(\textit{MP\_MEM}). \\ -3. $oldused \leftarrow b.used$ \\ -4. $b.used \leftarrow a.used$ \\ -5. $r \leftarrow 0$ \\ -6. for $n$ from $b.used - 1$ to $0$ do \\ -\hspace{3mm}6.1 $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\ -\hspace{3mm}6.2 $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}6.3 $r \leftarrow rr$ \\ -7. If $b.used < oldused - 1$ then do \\ -\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\ -\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\ -8. $b.sign \leftarrow a.sign$ \\ -9. Clamp excess digits of $b$. (\textit{mp\_clamp}) \\ -10. Return(\textit{MP\_OKAY}).\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_div\_2} -\end{figure} - -\textbf{Algorithm mp\_div\_2.} -This algorithm will divide an mp\_int by two using logical shifts to the right. Like mp\_mul\_2 it uses a modified low level addition -core as the basis of the algorithm. Unlike mp\_mul\_2 the shift operations work from the leading digit to the trailing digit. The algorithm -could be written to work from the trailing digit to the leading digit however, it would have to stop one short of $a.used - 1$ digits to prevent -reading past the end of the array of digits. - -Essentially the loop at step 6 is similar to that of mp\_mul\_2 except the logical shifts go in the opposite direction and the carry is at the -least significant bit not the most significant bit. - -EXAM,bn_mp_div_2.c - -\section{Polynomial Basis Operations} -Recall from ~POLY~ that any integer can be represented as a polynomial in $x$ as $y = f(\beta)$. Such a representation is also known as -the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single -place. The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer -division and Karatsuba multiplication. - -Converting from an array of digits to polynomial basis is very simple. Consider the integer $y \equiv (a_2, a_1, a_0)_{\beta}$ and recall that -$y = \sum_{i=0}^{2} a_i \beta^i$. Simply replace $\beta$ with $x$ and the expression is in polynomial basis. For example, $f(x) = 8x + 9$ is the -polynomial basis representation for $89$ using radix ten. That is, $f(10) = 8(10) + 9 = 89$. - -\subsection{Multiplication by $x$} - -Given a polynomial in $x$ such as $f(x) = a_n x^n + a_{n-1} x^{n-1} + ... + a_0$ multiplying by $x$ amounts to shifting the coefficients up one -degree. In this case $f(x) \cdot x = a_n x^{n+1} + a_{n-1} x^n + ... + a_0 x$. From a scalar basis point of view multiplying by $x$ is equivalent to -multiplying by the integer $\beta$. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_lshd}. \\ -\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ -\textbf{Output}. $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\ -\hline \\ -1. If $b \le 0$ then return(\textit{MP\_OKAY}). \\ -2. If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits. (\textit{mp\_grow}). \\ -3. If the reallocation failed return(\textit{MP\_MEM}). \\ -4. $a.used \leftarrow a.used + b$ \\ -5. $i \leftarrow a.used - 1$ \\ -6. $j \leftarrow a.used - 1 - b$ \\ -7. for $n$ from $a.used - 1$ to $b$ do \\ -\hspace{3mm}7.1 $a_{i} \leftarrow a_{j}$ \\ -\hspace{3mm}7.2 $i \leftarrow i - 1$ \\ -\hspace{3mm}7.3 $j \leftarrow j - 1$ \\ -8. for $n$ from 0 to $b - 1$ do \\ -\hspace{3mm}8.1 $a_n \leftarrow 0$ \\ -9. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_lshd} -\end{figure} - -\textbf{Algorithm mp\_lshd.} -This algorithm multiplies an mp\_int by the $b$'th power of $x$. This is equivalent to multiplying by $\beta^b$. The algorithm differs -from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location. The -motivation behind this change is due to the way this function is typically used. Algorithms such as mp\_add store the result in an optionally -different third mp\_int because the original inputs are often still required. Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is -typically used on values where the original value is no longer required. The algorithm will return success immediately if -$b \le 0$ since the rest of algorithm is only valid when $b > 0$. - -First the destination $a$ is grown as required to accomodate the result. The counters $i$ and $j$ are used to form a \textit{sliding window} over -the digits of $a$ of length $b$. The head of the sliding window is at $i$ (\textit{the leading digit}) and the tail at $j$ (\textit{the trailing digit}). -The loop on step 7 copies the digit from the tail to the head. In each iteration the window is moved down one digit. The last loop on -step 8 sets the lower $b$ digits to zero. - -\newpage -FIGU,sliding_window,Sliding Window Movement - -EXAM,bn_mp_lshd.c - -The if statement (line @24,if@) ensures that the $b$ variable is greater than zero since we do not interpret negative -shift counts properly. The \textbf{used} count is incremented by $b$ before the copy loop begins. This elminates -the need for an additional variable in the for loop. The variable $top$ (line @42,top@) is an alias -for the leading digit while $bottom$ (line @45,bottom@) is an alias for the trailing edge. The aliases form a -window of exactly $b$ digits over the input. - -\subsection{Division by $x$} - -Division by powers of $x$ is easily achieved by shifting the digits right and removing any that will end up to the right of the zero'th digit. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_rshd}. \\ -\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ -\textbf{Output}. $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\ -\hline \\ -1. If $b \le 0$ then return. \\ -2. If $a.used \le b$ then do \\ -\hspace{3mm}2.1 Zero $a$. (\textit{mp\_zero}). \\ -\hspace{3mm}2.2 Return. \\ -3. $i \leftarrow 0$ \\ -4. $j \leftarrow b$ \\ -5. for $n$ from 0 to $a.used - b - 1$ do \\ -\hspace{3mm}5.1 $a_i \leftarrow a_j$ \\ -\hspace{3mm}5.2 $i \leftarrow i + 1$ \\ -\hspace{3mm}5.3 $j \leftarrow j + 1$ \\ -6. for $n$ from $a.used - b$ to $a.used - 1$ do \\ -\hspace{3mm}6.1 $a_n \leftarrow 0$ \\ -7. $a.used \leftarrow a.used - b$ \\ -8. Return. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_rshd} -\end{figure} - -\textbf{Algorithm mp\_rshd.} -This algorithm divides the input in place by the $b$'th power of $x$. It is analogous to dividing by a $\beta^b$ but much quicker since -it does not require single precision division. This algorithm does not actually return an error code as it cannot fail. - -If the input $b$ is less than one the algorithm quickly returns without performing any work. If the \textbf{used} count is less than or equal -to the shift count $b$ then it will simply zero the input and return. - -After the trivial cases of inputs have been handled the sliding window is setup. Much like the case of algorithm mp\_lshd a sliding window that -is $b$ digits wide is used to copy the digits. Unlike mp\_lshd the window slides in the opposite direction from the trailing to the leading digit. -Also the digits are copied from the leading to the trailing edge. - -Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented. - -EXAM,bn_mp_rshd.c - -The only noteworthy element of this routine is the lack of a return type since it cannot fail. Like mp\_lshd() we -form a sliding window except we copy in the other direction. After the window (line @59,for (;@) we then zero -the upper digits of the input to make sure the result is correct. - -\section{Powers of Two} - -Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required. For -example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful. Instead of performing single -shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed. - -\subsection{Multiplication by Power of Two} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_mul\_2d}. \\ -\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ -\textbf{Output}. $c \leftarrow a \cdot 2^b$. \\ -\hline \\ -1. $c \leftarrow a$. (\textit{mp\_copy}) \\ -2. If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\ -3. If the reallocation failed return(\textit{MP\_MEM}). \\ -4. If $b \ge lg(\beta)$ then \\ -\hspace{3mm}4.1 $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\ -\hspace{3mm}4.2 If step 4.1 failed return(\textit{MP\_MEM}). \\ -5. $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ -6. If $d \ne 0$ then do \\ -\hspace{3mm}6.1 $mask \leftarrow 2^d$ \\ -\hspace{3mm}6.2 $r \leftarrow 0$ \\ -\hspace{3mm}6.3 for $n$ from $0$ to $c.used - 1$ do \\ -\hspace{6mm}6.3.1 $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\ -\hspace{6mm}6.3.2 $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{6mm}6.3.3 $r \leftarrow rr$ \\ -\hspace{3mm}6.4 If $r > 0$ then do \\ -\hspace{6mm}6.4.1 $c_{c.used} \leftarrow r$ \\ -\hspace{6mm}6.4.2 $c.used \leftarrow c.used + 1$ \\ -7. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_mul\_2d} -\end{figure} - -\textbf{Algorithm mp\_mul\_2d.} -This algorithm multiplies $a$ by $2^b$ and stores the result in $c$. The algorithm uses algorithm mp\_lshd and a derivative of algorithm mp\_mul\_2 to -quickly compute the product. - -First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than -$\beta$. For example, if $b = 37$ and $\beta = 2^{28}$ then this step will multiply by $x$ leaving a multiplication by $2^{37 - 28} = 2^{9}$ -left. - -After the digits have been shifted appropriately at most $lg(\beta) - 1$ shifts are left to perform. Step 5 calculates the number of remaining shifts -required. If it is non-zero a modified shift loop is used to calculate the remaining product. -Essentially the loop is a generic version of algorithm mp\_mul\_2 designed to handle any shift count in the range $1 \le x < lg(\beta)$. The $mask$ -variable is used to extract the upper $d$ bits to form the carry for the next iteration. - -This algorithm is loosely measured as a $O(2n)$ algorithm which means that if the input is $n$-digits that it takes $2n$ ``time'' to -complete. It is possible to optimize this algorithm down to a $O(n)$ algorithm at a cost of making the algorithm slightly harder to follow. - -EXAM,bn_mp_mul_2d.c - -The shifting is performed in--place which means the first step (line @24,a != c@) is to copy the input to the -destination. We avoid calling mp\_copy() by making sure the mp\_ints are different. The destination then -has to be grown (line @31,grow@) to accomodate the result. - -If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples -of $lg(\beta)$. Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left. Inside the actual shift -loop (lines @45,if@ to @76,}@) we make use of pre--computed values $shift$ and $mask$. These are used to -extract the carry bit(s) to pass into the next iteration of the loop. The $r$ and $rr$ variables form a -chain between consecutive iterations to propagate the carry. - -\subsection{Division by Power of Two} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_div\_2d}. \\ -\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ -\textbf{Output}. $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\ -\hline \\ -1. If $b \le 0$ then do \\ -\hspace{3mm}1.1 $c \leftarrow a$ (\textit{mp\_copy}) \\ -\hspace{3mm}1.2 $d \leftarrow 0$ (\textit{mp\_zero}) \\ -\hspace{3mm}1.3 Return(\textit{MP\_OKAY}). \\ -2. $c \leftarrow a$ \\ -3. $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\ -4. If $b \ge lg(\beta)$ then do \\ -\hspace{3mm}4.1 $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\ -5. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ -6. If $k \ne 0$ then do \\ -\hspace{3mm}6.1 $mask \leftarrow 2^k$ \\ -\hspace{3mm}6.2 $r \leftarrow 0$ \\ -\hspace{3mm}6.3 for $n$ from $c.used - 1$ to $0$ do \\ -\hspace{6mm}6.3.1 $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\ -\hspace{6mm}6.3.2 $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\ -\hspace{6mm}6.3.3 $r \leftarrow rr$ \\ -7. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\ -8. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_div\_2d} -\end{figure} - -\textbf{Algorithm mp\_div\_2d.} -This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder. The algorithm is designed much like algorithm -mp\_mul\_2d by first using whole digit shifts then single precision shifts. This algorithm will also produce the remainder of the division -by using algorithm mp\_mod\_2d. - -EXAM,bn_mp_div_2d.c - -The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies. The remainder $d$ may be optionally -ignored by passing \textbf{NULL} as the pointer to the mp\_int variable. The temporary mp\_int variable $t$ is used to hold the -result of the remainder operation until the end. This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before -the quotient is obtained. - -The remainder of the source code is essentially the same as the source code for mp\_mul\_2d. The only significant difference is -the direction of the shifts. - -\subsection{Remainder of Division by Power of Two} - -The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$. This -algorithm benefits from the fact that in twos complement arithmetic $a \mbox{ (mod }2^b\mbox{)}$ is the same as $a$ AND $2^b - 1$. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_mod\_2d}. \\ -\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ -\textbf{Output}. $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\ -\hline \\ -1. If $b \le 0$ then do \\ -\hspace{3mm}1.1 $c \leftarrow 0$ (\textit{mp\_zero}) \\ -\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ -2. If $b > a.used \cdot lg(\beta)$ then do \\ -\hspace{3mm}2.1 $c \leftarrow a$ (\textit{mp\_copy}) \\ -\hspace{3mm}2.2 Return the result of step 2.1. \\ -3. $c \leftarrow a$ \\ -4. If step 3 failed return(\textit{MP\_MEM}). \\ -5. for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\ -\hspace{3mm}5.1 $c_n \leftarrow 0$ \\ -6. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ -7. $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\ -8. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\ -9. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_mod\_2d} -\end{figure} - -\textbf{Algorithm mp\_mod\_2d.} -This algorithm will quickly calculate the value of $a \mbox{ (mod }2^b\mbox{)}$. First if $b$ is less than or equal to zero the -result is set to zero. If $b$ is greater than the number of bits in $a$ then it simply copies $a$ to $c$ and returns. Otherwise, $a$ -is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count. - -EXAM,bn_mp_mod_2d.c - -We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases. Next if $2^b$ is larger -than the input we just mp\_copy() the input and return right away. After this point we know we must actually -perform some work to produce the remainder. - -Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce -the number. First we zero any digits above the last digit in $2^b$ (line @41,for@). Next we reduce the -leading digit of both (line @45,&=@) and then mp\_clamp(). - -\section*{Exercises} -\begin{tabular}{cl} -$\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\ - & in $O(n)$ time. \\ - &\\ -$\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming \\ - & weight values such as $3$, $5$ and $9$. Extend it to handle all values \\ - & upto $64$ with a hamming weight less than three. \\ - &\\ -$\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\ - & $2^k - 1$ as well. \\ - &\\ -$\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\ - & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\ - & any $n$-bit input. Note that the time of addition is ignored in the \\ - & calculation. \\ - & \\ -$\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\ - & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$. Again ignore \\ - & the cost of addition. \\ - & \\ -$\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\ - & for $n = 64 \ldots 1024$ in steps of $64$. \\ - & \\ -$\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\ - & calculating the result of a signed comparison. \\ - & -\end{tabular} - -\chapter{Multiplication and Squaring} -\section{The Multipliers} -For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of -algorithms of any multiple precision integer package. The set of multiplier algorithms include integer multiplication, squaring and modular reduction -where in each of the algorithms single precision multiplication is the dominant operation performed. This chapter will discuss integer multiplication -and squaring, leaving modular reductions for the subsequent chapter. - -The importance of the multiplier algorithms is for the most part driven by the fact that certain popular public key algorithms are based on modular -exponentiation, that is computing $d \equiv a^b \mbox{ (mod }c\mbox{)}$ for some arbitrary choice of $a$, $b$, $c$ and $d$. During a modular -exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions, -35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision -multiplications. - -For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied -against every digit of the other multiplicand. Traditional long-hand multiplication is based on this process; while the techniques can differ the -overall algorithm used is essentially the same. Only ``recently'' have faster algorithms been studied. First Karatsuba multiplication was discovered in -1962. This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach. -This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions. - -\section{Multiplication} -\subsection{The Baseline Multiplication} -\label{sec:basemult} -\index{baseline multiplication} -Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication -algorithm that school children are taught. The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision -multiplications are required. More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required. To -simplify most discussions, it will be assumed that the inputs have comparable number of digits. - -The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be -used. This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible. One important -facet of this algorithm, is that it has been modified to only produce a certain amount of output digits as resolution. The importance of this -modification will become evident during the discussion of Barrett modular reduction. Recall that for a $n$ and $m$ digit input the product -will be at most $n + m$ digits. Therefore, this algorithm can be reduced to a full multiplier by having it produce $n + m$ digits of the product. - -Recall from ~GAMMA~ the definition of $\gamma$ as the number of bits in the type \textbf{mp\_digit}. We shall now extend the variable set to -include $\alpha$ which shall represent the number of bits in the type \textbf{mp\_word}. This implies that $2^{\alpha} > 2 \cdot \beta^2$. The -constant $\delta = 2^{\alpha - 2lg(\beta)}$ will represent the maximal weight of any column in a product (\textit{see ~COMBA~ for more information}). - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_mul\_digs}. \\ -\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\ -\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\ -\hline \\ -1. If min$(a.used, b.used) < \delta$ then do \\ -\hspace{3mm}1.1 Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}). \\ -\hspace{3mm}1.2 Return the result of step 1.1 \\ -\\ -Allocate and initialize a temporary mp\_int. \\ -2. Init $t$ to be of size $digs$ \\ -3. If step 2 failed return(\textit{MP\_MEM}). \\ -4. $t.used \leftarrow digs$ \\ -\\ -Compute the product. \\ -5. for $ix$ from $0$ to $a.used - 1$ do \\ -\hspace{3mm}5.1 $u \leftarrow 0$ \\ -\hspace{3mm}5.2 $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\ -\hspace{3mm}5.3 If $pb < 1$ then goto step 6. \\ -\hspace{3mm}5.4 for $iy$ from $0$ to $pb - 1$ do \\ -\hspace{6mm}5.4.1 $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\ -\hspace{6mm}5.4.2 $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{6mm}5.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -\hspace{3mm}5.5 if $ix + pb < digs$ then do \\ -\hspace{6mm}5.5.1 $t_{ix + pb} \leftarrow u$ \\ -6. Clamp excess digits of $t$. \\ -7. Swap $c$ with $t$ \\ -8. Clear $t$ \\ -9. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm s\_mp\_mul\_digs} -\end{figure} - -\textbf{Algorithm s\_mp\_mul\_digs.} -This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits. While it may seem -a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent -algorithm. The algorithm is loosely based on algorithm 14.12 from \cite[pp. 595]{HAC} and is similar to Algorithm M of Knuth \cite[pp. 268]{TAOCPV2}. -Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the -inputs. - -The first thing this algorithm checks for is whether a Comba multiplier can be used instead. If the minimum digit count of either -input is less than $\delta$, then the Comba method may be used instead. After the Comba method is ruled out, the baseline algorithm begins. A -temporary mp\_int variable $t$ is used to hold the intermediate result of the product. This allows the algorithm to be used to -compute products when either $a = c$ or $b = c$ without overwriting the inputs. - -All of step 5 is the infamous $O(n^2)$ multiplication loop slightly modified to only produce upto $digs$ digits of output. The $pb$ variable -is given the count of digits to read from $b$ inside the nested loop. If $pb \le 1$ then no more output digits can be produced and the algorithm -will exit the loop. The best way to think of the loops are as a series of $pb \times 1$ multiplications. That is, in each pass of the -innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$. - -For example, consider multiplying $576$ by $241$. That is equivalent to computing $10^0(1)(576) + 10^1(4)(576) + 10^2(2)(576)$ which is best -visualized in the following table. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{|c|c|c|c|c|c|l|} -\hline && & 5 & 7 & 6 & \\ -\hline $\times$&& & 2 & 4 & 1 & \\ -\hline &&&&&&\\ - && & 5 & 7 & 6 & $10^0(1)(576)$ \\ - &2 & 3 & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\ - 1 & 3 & 8 & 8 & 1 & 6 & $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\ -\hline -\end{tabular} -\end{center} -\caption{Long-Hand Multiplication Diagram} -\end{figure} - -Each row of the product is added to the result after being shifted to the left (\textit{multiplied by a power of the radix}) by the appropriate -count. That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult. - -Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable. The multiplication on that step -is assumed to be a double wide output single precision multiplication. That is, two single precision variables are multiplied to produce a -double precision result. The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step -5.4.1 is propagated through the nested loop. If the carry was not propagated immediately it would overflow the single precision digit -$t_{ix+iy}$ and the result would be lost. - -At step 5.5 the nested loop is finished and any carry that was left over should be forwarded. The carry does not have to be added to the $ix+pb$'th -digit since that digit is assumed to be zero at this point. However, if $ix + pb \ge digs$ the carry is not set as it would make the result -exceed the precision requested. - -EXAM,bn_s_mp_mul_digs.c - -First we determine (line @30,if@) if the Comba method can be used first since it's faster. The conditions for -sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than -\textbf{MP\_WARRAY}. This new constant is used to control the stack usage in the Comba routines. By default it is -set to $\delta$ but can be reduced when memory is at a premium. - -If we cannot use the Comba method we proceed to setup the baseline routine. We allocate the the destination mp\_int -$t$ (line @36,init@) to the exact size of the output to avoid further re--allocations. At this point we now -begin the $O(n^2)$ loop. - -This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of -digits as output. In each iteration of the outer loop the $pb$ variable is set (line @48,MIN@) to the maximum -number of inner loop iterations. - -Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the -carry from the previous iteration. A particularly important observation is that most modern optimizing -C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that -is required for the product. In x86 terms for example, this means using the MUL instruction. - -Each digit of the product is stored in turn (line @68,tmpt@) and the carry propagated (line @71,>>@) to the -next iteration. - -\subsection{Faster Multiplication by the ``Comba'' Method} -MARK,COMBA - -One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be -computed and propagated upwards. This makes the nested loop very sequential and hard to unroll and implement -in parallel. The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G. -Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations. As an -interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written -five years before. - -At the heart of the Comba technique is once again the long-hand algorithm. Except in this case a slight -twist is placed on how the columns of the result are produced. In the standard long-hand algorithm rows of products -are produced then added together to form the final result. In the baseline algorithm the columns are added together -after each iteration to get the result instantaneously. - -In the Comba algorithm the columns of the result are produced entirely independently of each other. That is at -the $O(n^2)$ level a simple multiplication and addition step is performed. The carries of the columns are propagated -after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute -the product vector $\vec x$ as follows. - -\begin{equation} -\vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace -\end{equation} - -Where $\vec x_n$ is the $n'th$ column of the output vector. Consider the following example which computes the vector $\vec x$ for the multiplication -of $576$ and $241$. - -\newpage\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{|c|c|c|c|c|c|} - \hline & & 5 & 7 & 6 & First Input\\ - \hline $\times$ & & 2 & 4 & 1 & Second Input\\ -\hline & & $1 \cdot 5 = 5$ & $1 \cdot 7 = 7$ & $1 \cdot 6 = 6$ & First pass \\ - & $4 \cdot 5 = 20$ & $4 \cdot 7+5=33$ & $4 \cdot 6+7=31$ & 6 & Second pass \\ - $2 \cdot 5 = 10$ & $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31 & 6 & Third pass \\ -\hline 10 & 34 & 45 & 31 & 6 & Final Result \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Comba Multiplication Diagram} -\end{figure} - -At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler. -Now the columns must be fixed by propagating the carry upwards. The resultant vector will have one extra dimension over the input vector which is -congruent to adding a leading zero digit. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Comba Fixup}. \\ -\textbf{Input}. Vector $\vec x$ of dimension $k$ \\ -\textbf{Output}. Vector $\vec x$ such that the carries have been propagated. \\ -\hline \\ -1. for $n$ from $0$ to $k - 1$ do \\ -\hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\ -\hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\ -2. Return($\vec x$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Comba Fixup} -\end{figure} - -With that algorithm and $k = 5$ and $\beta = 10$ the following vector is produced $\vec x= \left < 1, 3, 8, 8, 1, 6 \right >$. In this case -$241 \cdot 576$ is in fact $138816$ and the procedure succeeded. If the algorithm is correct and as will be demonstrated shortly more -efficient than the baseline algorithm why not simply always use this algorithm? - -\subsubsection{Column Weight.} -At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output -independently. A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix -the carries. For example, in the multiplication of two three-digit numbers the third column of output will be the sum of -three single precision multiplications. If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then -an overflow can occur and the carry information will be lost. For any $m$ and $n$ digit inputs the maximum weight of any column is -min$(m, n)$ which is fairly obvious. - -The maximum number of terms in any column of a product is known as the ``column weight'' and strictly governs when the algorithm can be used. Recall -from earlier that a double precision type has $\alpha$ bits of resolution and a single precision digit has $lg(\beta)$ bits of precision. Given these -two quantities we must not violate the following - -\begin{equation} -k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha} -\end{equation} - -Which reduces to - -\begin{equation} -k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha} -\end{equation} - -Let $\rho = lg(\beta)$ represent the number of bits in a single precision digit. By further re-arrangement of the equation the final solution is -found. - -\begin{equation} -k < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}} -\end{equation} - -The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$. In this configuration -the smaller input may not have more than $256$ digits if the Comba method is to be used. This is quite satisfactory for most applications since -$256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, is much larger than most public key cryptographic algorithms require. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\ -\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\ -\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\ -\hline \\ -Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\ -1. If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\ -2. If step 1 failed return(\textit{MP\_MEM}).\\ -\\ -3. $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\ -\\ -4. $\_ \hat W \leftarrow 0$ \\ -5. for $ix$ from 0 to $pa - 1$ do \\ -\hspace{3mm}5.1 $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\ -\hspace{3mm}5.2 $tx \leftarrow ix - ty$ \\ -\hspace{3mm}5.3 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\ -\hspace{3mm}5.4 for $iz$ from 0 to $iy - 1$ do \\ -\hspace{6mm}5.4.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\ -\hspace{3mm}5.5 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\ -\hspace{3mm}5.6 $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\ -\\ -6. $oldused \leftarrow c.used$ \\ -7. $c.used \leftarrow digs$ \\ -8. for $ix$ from $0$ to $pa$ do \\ -\hspace{3mm}8.1 $c_{ix} \leftarrow W_{ix}$ \\ -9. for $ix$ from $pa + 1$ to $oldused - 1$ do \\ -\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\ -\\ -10. Clamp $c$. \\ -11. Return MP\_OKAY. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm fast\_s\_mp\_mul\_digs} -\label{fig:COMBAMULT} -\end{figure} - -\textbf{Algorithm fast\_s\_mp\_mul\_digs.} -This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision. - -The outer loop of this algorithm is more complicated than that of the baseline multiplier. This is because on the inside of the -loop we want to produce one column per pass. This allows the accumulator $\_ \hat W$ to be placed in CPU registers and -reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration. - -The $ty$ variable is set to the minimum count of $ix$ or the number of digits in $b$. That way if $a$ has more digits than -$b$ this will be limited to $b.used - 1$. The $tx$ variable is set to the to the distance past $b.used$ the variable -$ix$ is. This is used for the immediately subsequent statement where we find $iy$. - -The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out. Computing one column at a time -means we have to scan one integer upwards and the other downwards. $a$ starts at $tx$ and $b$ starts at $ty$. In each -pass we are producing the $ix$'th output column and we note that $tx + ty = ix$. As we move $tx$ upwards we have to -move $ty$ downards so the equality remains valid. The $iy$ variable is the number of iterations until -$tx \ge a.used$ or $ty < 0$ occurs. - -After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator -into the next round by dividing $\_ \hat W$ by $\beta$. - -To measure the benefits of the Comba method over the baseline method consider the number of operations that are required. If the -cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require -$O \left ((p + q)n^2 \right )$ time to multiply two $n$-digit numbers. The Comba method requires only $O(pn^2 + qn)$ time, however in practice, -the speed increase is actually much more. With $O(n)$ space the algorithm can be reduced to $O(pn + qn)$ time by implementing the $n$ multiply -and addition operations in the nested loop in parallel. - -EXAM,bn_fast_s_mp_mul_digs.c - -As per the pseudo--code we first calculate $pa$ (line @47,MIN@) as the number of digits to output. Next we begin the outer loop -to produce the individual columns of the product. We use the two aliases $tmpx$ and $tmpy$ (lines @61,tmpx@, @62,tmpy@) to point -inside the two multiplicands quickly. - -The inner loop (lines @70,for@ to @72,}@) of this implementation is where the tradeoff come into play. Originally this comba -implementation was ``row--major'' which means it adds to each of the columns in each pass. After the outer loop it would then fix -the carries. This was very fast except it had an annoying drawback. You had to read a mp\_word and two mp\_digits and write -one mp\_word per iteration. On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth -is very high and it can keep the ALU fed with data. It did, however, matter on older and embedded cpus where cache is often -slower and also often doesn't exist. This new algorithm only performs two reads per iteration under the assumption that the -compiler has aliased $\_ \hat W$ to a CPU register. - -After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines @75,W[ix]@, @78,>>@) to forward it as -a carry for the next pass. After the outer loop we use the final carry (line @82,W[ix]@) as the last digit of the product. - -\subsection{Polynomial Basis Multiplication} -To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication. In the following algorithms -the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and -$g(x) = \sum_{i=0}^{n} b_i x^i$ respectively, is required. In this system both $f(x)$ and $g(x)$ have $n + 1$ terms and are of the $n$'th degree. - -The product $a \cdot b \equiv f(x)g(x)$ is the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$. The coefficients $w_i$ will -directly yield the desired product when $\beta$ is substituted for $x$. The direct solution to solve for the $2n + 1$ coefficients -requires $O(n^2)$ time and would in practice be slower than the Comba technique. - -However, numerical analysis theory indicates that only $2n + 1$ distinct points in $W(x)$ are required to determine the values of the $2n + 1$ unknown -coefficients. This means by finding $\zeta_y = W(y)$ for $2n + 1$ small values of $y$ the coefficients of $W(x)$ can be found with -Gaussian elimination. This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in -effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$. - -The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible. However, since -$W(x) = f(x)g(x)$ the equivalent $\zeta_y = f(y) g(y)$ can be used in its place. The benefit of this technique stems from the -fact that $f(y)$ and $g(y)$ are much smaller than either $a$ or $b$ respectively. As a result finding the $2n + 1$ relations required -by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs. - -When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$. The $\zeta_0$ term -is simply the product $W(0) = w_0 = a_0 \cdot b_0$. The $\zeta_1$ term is the product -$W(1) = \left (\sum_{i = 0}^{n} a_i \right ) \left (\sum_{i = 0}^{n} b_i \right )$. The third point $\zeta_{\infty}$ is less obvious but rather -simple to explain. The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication. -The point at $\infty$ is used symbolically to represent the most significant column, that is $W(\infty) = w_{2n} = a_nb_n$. Note that the -points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly. - -If more points are required they should be of small values and powers of two such as $2^q$ and the related \textit{mirror points} -$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ for small values of $q$. The term ``mirror point'' stems from the fact that -$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$. For -example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror. - -\begin{eqnarray} -\zeta_{2} = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\ -16 \cdot \zeta_{1 \over 2} = 4f({1\over 2}) \cdot 4g({1 \over 2}) = (a_2 + 2a_1 + 4a_0)(b_2 + 2b_1 + 4b_0) -\end{eqnarray} - -Using such points will allow the values of $f(y)$ and $g(y)$ to be independently calculated using only left shifts. For example, when $n = 2$ the -polynomial $f(2^q)$ is equal to $2^q((2^qa_2) + a_1) + a_0$. This technique of polynomial representation is known as Horner's method. - -As a general rule of the algorithm when the inputs are split into $n$ parts each there are $2n - 1$ multiplications. Each multiplication is of -multiplicands that have $n$ times fewer digits than the inputs. The asymptotic running time of this algorithm is -$O \left ( k^{lg_n(2n - 1)} \right )$ for $k$ digit inputs (\textit{assuming they have the same number of digits}). Figure~\ref{fig:exponent} -summarizes the exponents for various values of $n$. - -\begin{figure} -\begin{center} -\begin{tabular}{|c|c|c|} -\hline \textbf{Split into $n$ Parts} & \textbf{Exponent} & \textbf{Notes}\\ -\hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\ -\hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\ -\hline $4$ & $1.403677461$ &\\ -\hline $5$ & $1.365212389$ &\\ -\hline $10$ & $1.278753601$ &\\ -\hline $100$ & $1.149426538$ &\\ -\hline $1000$ & $1.100270931$ &\\ -\hline $10000$ & $1.075252070$ &\\ -\hline -\end{tabular} -\end{center} -\caption{Asymptotic Running Time of Polynomial Basis Multiplication} -\label{fig:exponent} -\end{figure} - -At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$. However, the overhead -of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large -numbers. - -\subsubsection{Cutoff Point} -The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach. However, -the algorithms incur an overhead (\textit{at the $O(n)$ work level}) since they require a system of equations to be solved. This makes the -polynomial basis approach more costly to use with small inputs. - -Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}). There exists a -point $y$ such that when $m < y$ the polynomial basis algorithms are more costly than Comba, when $m = y$ they are roughly the same cost and -when $m > y$ the Comba methods are slower than the polynomial basis algorithms. - -The exact location of $y$ depends on several key architectural elements of the computer platform in question. - -\begin{enumerate} -\item The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc. For example -on the AMD Athlon the ratio is roughly $17 : 1$ while on the Intel P4 it is $29 : 1$. The higher the ratio in favour of multiplication the lower -the cutoff point $y$ will be. - -\item The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is. Generally speaking as the number of splits -grows the complexity grows substantially. Ideally solving the system will only involve addition, subtraction and shifting of integers. This -directly reflects on the ratio previous mentioned. - -\item To a lesser extent memory bandwidth and function call overheads. Provided the values are in the processor cache this is less of an -influence over the cutoff point. - -\end{enumerate} - -A clean cutoff point separation occurs when a point $y$ is found such that all of the cutoff point conditions are met. For example, if the point -is too low then there will be values of $m$ such that $m > y$ and the Comba method is still faster. Finding the cutoff points is fairly simple when -a high resolution timer is available. - -\subsection{Karatsuba Multiplication} -Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for -general purpose multiplication. Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with -light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent. - -\begin{equation} -f(x) \cdot g(x) = acx^2 + ((a + b)(c + d) - (ac + bd))x + bd -\end{equation} - -Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product. Applying -this algorithm recursively, the work factor becomes $O(n^{lg(3)})$ which is substantially better than the work factor $O(n^2)$ of the Comba technique. It turns -out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points -$\zeta_0$, $\zeta_{\infty}$ and $\zeta_{1}$. Consider the resultant system of equations. - -\begin{center} -\begin{tabular}{rcrcrcrc} -$\zeta_{0}$ & $=$ & & & & & $w_0$ \\ -$\zeta_{1}$ & $=$ & $w_2$ & $+$ & $w_1$ & $+$ & $w_0$ \\ -$\zeta_{\infty}$ & $=$ & $w_2$ & & & & \\ -\end{tabular} -\end{center} - -By adding the first and last equation to the equation in the middle the term $w_1$ can be isolated and all three coefficients solved for. The simplicity -of this system of equations has made Karatsuba fairly popular. In fact the cutoff point is often fairly low\footnote{With LibTomMath 0.18 it is 70 and 109 digits for the Intel P4 and AMD Athlon respectively.} -making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_karatsuba\_mul}. \\ -\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ -\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\ -\hline \\ -1. Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\ -2. If step 2 failed then return(\textit{MP\_MEM}). \\ -\\ -Split the input. e.g. $a = x1 \cdot \beta^B + x0$ \\ -3. $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\ -4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\ -5. $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\ -6. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\ -7. $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\ -\\ -Calculate the three products. \\ -8. $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\ -9. $x1y1 \leftarrow x1 \cdot y1$ \\ -10. $t1 \leftarrow x1 + x0$ (\textit{mp\_add}) \\ -11. $x0 \leftarrow y1 + y0$ \\ -12. $t1 \leftarrow t1 \cdot x0$ \\ -\\ -Calculate the middle term. \\ -13. $x0 \leftarrow x0y0 + x1y1$ \\ -14. $t1 \leftarrow t1 - x0$ (\textit{s\_mp\_sub}) \\ -\\ -Calculate the final product. \\ -15. $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\ -16. $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\ -17. $t1 \leftarrow x0y0 + t1$ \\ -18. $c \leftarrow t1 + x1y1$ \\ -19. Clear all of the temporary variables. \\ -20. Return(\textit{MP\_OKAY}).\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_karatsuba\_mul} -\end{figure} - -\textbf{Algorithm mp\_karatsuba\_mul.} -This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm. It is loosely based on the description -from Knuth \cite[pp. 294-295]{TAOCPV2}. - -\index{radix point} -In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen. The radix point chosen must -be used for both of the inputs meaning that it must be smaller than the smallest input. Step 3 chooses the radix point $B$ as half of the -smallest input \textbf{used} count. After the radix point is chosen the inputs are split into lower and upper halves. Step 4 and 5 -compute the lower halves. Step 6 and 7 computer the upper halves. - -After the halves have been computed the three intermediate half-size products must be computed. Step 8 and 9 compute the trivial products -$x0 \cdot y0$ and $x1 \cdot y1$. The mp\_int $x0$ is used as a temporary variable after $x1 + x0$ has been computed. By using $x0$ instead -of an additional temporary variable, the algorithm can avoid an addition memory allocation operation. - -The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations. - -EXAM,bn_mp_karatsuba_mul.c - -The new coding element in this routine, not seen in previous routines, is the usage of goto statements. The conventional -wisdom is that goto statements should be avoided. This is generally true, however when every single function call can fail, it makes sense -to handle error recovery with a single piece of code. Lines @61,if@ to @75,if@ handle initializing all of the temporary variables -required. Note how each of the if statements goes to a different label in case of failure. This allows the routine to correctly free only -the temporaries that have been successfully allocated so far. - -The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large. This saves the -additional reallocation that would have been necessary. Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective -number of digits for the next section of code. - -The first algebraic portion of the algorithm is to split the two inputs into their halves. However, instead of using mp\_mod\_2d and mp\_rshd -to extract the halves, the respective code has been placed inline within the body of the function. To initialize the halves, the \textbf{used} and -\textbf{sign} members are copied first. The first for loop on line @98,for@ copies the lower halves. Since they are both the same magnitude it -is simpler to calculate both lower halves in a single loop. The for loop on lines @104,for@ and @109,for@ calculate the upper halves $x1$ and -$y1$ respectively. - -By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs. - -When line @152,err@ is reached, the algorithm has completed succesfully. The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that -the same code that handles errors can be used to clear the temporary variables and return. - -\subsection{Toom-Cook $3$-Way Multiplication} -Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points are -chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce. Here, the points $\zeta_{0}$, -$16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients -of the $W(x)$. - -With the five relations that Toom-Cook specifies, the following system of equations is formed. - -\begin{center} -\begin{tabular}{rcrcrcrcrcr} -$\zeta_0$ & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$ \\ -$16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$ \\ -$\zeta_1$ & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$ \\ -$\zeta_2$ & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$ \\ -$\zeta_{\infty}$ & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$ \\ -\end{tabular} -\end{center} - -A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power -of two, two divisions by three and one multiplication by three. All of these $19$ sub-operations require less than quadratic time, meaning that -the algorithm can be faster than a baseline multiplication. However, the greater complexity of this algorithm places the cutoff point -(\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_toom\_mul}. \\ -\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ -\textbf{Output}. $c \leftarrow a \cdot b $ \\ -\hline \\ -Split $a$ and $b$ into three pieces. E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\ -1. $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\ -2. $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -3. $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -4. $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -5. $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -6. $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -7. $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -\\ -Find the five equations for $w_0, w_1, ..., w_4$. \\ -8. $w_0 \leftarrow a_0 \cdot b_0$ \\ -9. $w_4 \leftarrow a_2 \cdot b_2$ \\ -10. $tmp_1 \leftarrow 2 \cdot a_0$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_2$ \\ -11. $tmp_2 \leftarrow 2 \cdot b_0$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_2$ \\ -12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\ -13. $tmp_1 \leftarrow 2 \cdot a_2$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_0$ \\ -14. $tmp_2 \leftarrow 2 \cdot b_2$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_0$ \\ -15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\ -16. $tmp_1 \leftarrow a_0 + a_1$, $tmp_1 \leftarrow tmp_1 + a_2$, $tmp_2 \leftarrow b_0 + b_1$, $tmp_2 \leftarrow tmp_2 + b_2$ \\ -17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\ -\\ -Continued on the next page.\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_toom\_mul} -\end{figure} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_toom\_mul} (continued). \\ -\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ -\textbf{Output}. $c \leftarrow a \cdot b $ \\ -\hline \\ -Now solve the system of equations. \\ -18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\ -19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\ -20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\ -21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\ -22. $tmp_1 \leftarrow 8 \cdot w_0$, $w_1 \leftarrow w_1 - tmp_1$, $tmp_1 \leftarrow 8 \cdot w_4$, $w_3 \leftarrow w_3 - tmp_1$ \\ -23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\ -24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\ -25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\ -\\ -Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\ -26. for $n$ from $1$ to $4$ do \\ -\hspace{3mm}26.1 $w_n \leftarrow w_n \cdot \beta^{nk}$ \\ -27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\ -28. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_toom\_mul (continued)} -\end{figure} - -\textbf{Algorithm mp\_toom\_mul.} -This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach. Compared to the Karatsuba multiplication, this -algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead. In this -description, several statements have been compounded to save space. The intention is that the statements are executed from left to right across -any given step. - -The two inputs $a$ and $b$ are first split into three $k$-digit integers $a_0, a_1, a_2$ and $b_0, b_1, b_2$ respectively. From these smaller -integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required. - -The first two relations $w_0$ and $w_4$ are the points $\zeta_{0}$ and $\zeta_{\infty}$ respectively. The relation $w_1, w_2$ and $w_3$ correspond -to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively. These are found using logical shifts to independently find -$f(y)$ and $g(y)$ which significantly speeds up the algorithm. - -After the five relations $w_0, w_1, \ldots, w_4$ have been computed, the system they represent must be solved in order for the unknown coefficients -$w_1, w_2$ and $w_3$ to be isolated. The steps 18 through 25 perform the system reduction required as previously described. Each step of -the reduction represents the comparable matrix operation that would be performed had this been performed by pencil. For example, step 18 indicates -that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$. - -Once the coeffients have been isolated, the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$ is known. By substituting $\beta^{k}$ for $x$, the integer -result $a \cdot b$ is produced. - -EXAM,bn_mp_toom_mul.c - -The first obvious thing to note is that this algorithm is complicated. The complexity is worth it if you are multiplying very -large numbers. For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with -Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$). For most ``crypto'' sized numbers this -algorithm is not practical as Karatsuba has a much lower cutoff point. - -First we split $a$ and $b$ into three roughly equal portions. This has been accomplished (lines @40,mod@ to @69,rshd@) with -combinations of mp\_rshd() and mp\_mod\_2d() function calls. At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly -for $b$. - -Next we compute the five points $w0, w1, w2, w3$ and $w4$. Recall that $w0$ and $w4$ can be computed directly from the portions so -we get those out of the way first (lines @72,mul@ and @77,mul@). Next we compute $w1, w2$ and $w3$ using Horners method. - -After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively -straight forward. - -\subsection{Signed Multiplication} -Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required. So far all -of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_mul}. \\ -\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ -\textbf{Output}. $c \leftarrow a \cdot b$ \\ -\hline \\ -1. If $a.sign = b.sign$ then \\ -\hspace{3mm}1.1 $sign = MP\_ZPOS$ \\ -2. else \\ -\hspace{3mm}2.1 $sign = MP\_ZNEG$ \\ -3. If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then \\ -\hspace{3mm}3.1 $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\ -4. else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\ -\hspace{3mm}4.1 $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\ -5. else \\ -\hspace{3mm}5.1 $digs \leftarrow a.used + b.used + 1$ \\ -\hspace{3mm}5.2 If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\ -\hspace{6mm}5.2.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs. \\ -\hspace{3mm}5.3 else \\ -\hspace{6mm}5.3.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs. \\ -6. $c.sign \leftarrow sign$ \\ -7. Return the result of the unsigned multiplication performed. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_mul} -\end{figure} - -\textbf{Algorithm mp\_mul.} -This algorithm performs the signed multiplication of two inputs. It will make use of any of the three unsigned multiplication algorithms -available when the input is of appropriate size. The \textbf{sign} of the result is not set until the end of the algorithm since algorithm -s\_mp\_mul\_digs will clear it. - -EXAM,bn_mp_mul.c - -The implementation is rather simplistic and is not particularly noteworthy. Line @22,?@ computes the sign of the result using the ``?'' -operator from the C programming language. Line @37,<<@ computes $\delta$ using the fact that $1 << k$ is equal to $2^k$. - -\section{Squaring} -\label{sec:basesquare} - -Squaring is a special case of multiplication where both multiplicands are equal. At first it may seem like there is no significant optimization -available but in fact there is. Consider the multiplication of $576$ against $241$. In total there will be nine single precision multiplications -performed which are $1\cdot 6$, $1 \cdot 7$, $1 \cdot 5$, $4 \cdot 6$, $4 \cdot 7$, $4 \cdot 5$, $2 \cdot 6$, $2 \cdot 7$ and $2 \cdot 5$. Now consider -the multiplication of $123$ against $123$. The nine products are $3 \cdot 3$, $3 \cdot 2$, $3 \cdot 1$, $2 \cdot 3$, $2 \cdot 2$, $2 \cdot 1$, -$1 \cdot 3$, $1 \cdot 2$ and $1 \cdot 1$. On closer inspection some of the products are equivalent. For example, $3 \cdot 2 = 2 \cdot 3$ -and $3 \cdot 1 = 1 \cdot 3$. - -For any $n$-digit input, there are ${{\left (n^2 + n \right)}\over 2}$ possible unique single precision multiplications required compared to the $n^2$ -required for multiplication. The following diagram gives an example of the operations required. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{ccccc|c} -&&1&2&3&\\ -$\times$ &&1&2&3&\\ -\hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\ - & $2 \cdot 1$ & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\ - $1 \cdot 1$ & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\ -\end{tabular} -\end{center} -\caption{Squaring Optimization Diagram} -\end{figure} - -MARK,SQUARE -Starting from zero and numbering the columns from right to left a very simple pattern becomes obvious. For the purposes of this discussion let $x$ -represent the number being squared. The first observation is that in row $k$ the $2k$'th column of the product has a $\left (x_k \right)^2$ term in it. - -The second observation is that every column $j$ in row $k$ where $j \ne 2k$ is part of a double product. Every non-square term of a column will -appear twice hence the name ``double product''. Every odd column is made up entirely of double products. In fact every column is made up of double -products and at most one square (\textit{see the exercise section}). - -The third and final observation is that for row $k$ the first unique non-square term, that is, one that hasn't already appeared in an earlier row, -occurs at column $2k + 1$. For example, on row $1$ of the previous squaring, column one is part of the double product with column one from row zero. -Column two of row one is a square and column three is the first unique column. - -\subsection{The Baseline Squaring Algorithm} -The baseline squaring algorithm is meant to be a catch-all squaring algorithm. It will handle any of the input sizes that the faster routines -will not handle. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_sqr}. \\ -\textbf{Input}. mp\_int $a$ \\ -\textbf{Output}. $b \leftarrow a^2$ \\ -\hline \\ -1. Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits. (\textit{mp\_init\_size}) \\ -2. If step 1 failed return(\textit{MP\_MEM}) \\ -3. $t.used \leftarrow 2 \cdot a.used + 1$ \\ -4. For $ix$ from 0 to $a.used - 1$ do \\ -\hspace{3mm}Calculate the square. \\ -\hspace{3mm}4.1 $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\ -\hspace{3mm}4.2 $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}Calculate the double products after the square. \\ -\hspace{3mm}4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -\hspace{3mm}4.4 For $iy$ from $ix + 1$ to $a.used - 1$ do \\ -\hspace{6mm}4.4.1 $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\ -\hspace{6mm}4.4.2 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{6mm}4.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -\hspace{3mm}Set the last carry. \\ -\hspace{3mm}4.5 While $u > 0$ do \\ -\hspace{6mm}4.5.1 $iy \leftarrow iy + 1$ \\ -\hspace{6mm}4.5.2 $\hat r \leftarrow t_{ix + iy} + u$ \\ -\hspace{6mm}4.5.3 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{6mm}4.5.4 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -5. Clamp excess digits of $t$. (\textit{mp\_clamp}) \\ -6. Exchange $b$ and $t$. \\ -7. Clear $t$ (\textit{mp\_clear}) \\ -8. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm s\_mp\_sqr} -\end{figure} - -\textbf{Algorithm s\_mp\_sqr.} -This algorithm computes the square of an input using the three observations on squaring. It is based fairly faithfully on algorithm 14.16 of HAC -\cite[pp.596-597]{HAC}. Similar to algorithm s\_mp\_mul\_digs, a temporary mp\_int is allocated to hold the result of the squaring. This allows the -destination mp\_int to be the same as the source mp\_int. - -The outer loop of this algorithm begins on step 4. It is best to think of the outer loop as walking down the rows of the partial results, while -the inner loop computes the columns of the partial result. Step 4.1 and 4.2 compute the square term for each row, and step 4.3 and 4.4 propagate -the carry and compute the double products. - -The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this -very algorithm. The product $a_{ix}a_{iy}$ will lie in the range $0 \le x \le \beta^2 - 2\beta + 1$ which is obviously less than $\beta^2$ meaning that -when it is multiplied by two, it can be properly represented by a mp\_word. - -Similar to algorithm s\_mp\_mul\_digs, after every pass of the inner loop, the destination is correctly set to the sum of all of the partial -results calculated so far. This involves expensive carry propagation which will be eliminated in the next algorithm. - -EXAM,bn_s_mp_sqr.c - -Inside the outer loop (line @32,for@) the square term is calculated on line @35,r =@. The carry (line @42,>>@) has been -extracted from the mp\_word accumulator using a right shift. Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized -(lines @45,tmpx@ and @48,tmpt@) to simplify the inner loop. The doubling is performed using two -additions (line @57,r + r@) since it is usually faster than shifting, if not at least as fast. - -The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication. As such the inner loops -get progressively shorter as the algorithm proceeds. This is what leads to the savings compared to using a multiplication to -square a number. - -\subsection{Faster Squaring by the ``Comba'' Method} -A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop. Squaring has an additional -drawback that it must double the product inside the inner loop as well. As for multiplication, the Comba technique can be used to eliminate these -performance hazards. - -The first obvious solution is to make an array of mp\_words which will hold all of the columns. This will indeed eliminate all of the carry -propagation operations from the inner loop. However, the inner product must still be doubled $O(n^2)$ times. The solution stems from the simple fact -that $2a + 2b + 2c = 2(a + b + c)$. That is the sum of all of the double products is equal to double the sum of all the products. For example, -$ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$. - -However, we cannot simply double all of the columns, since the squares appear only once per row. The most practical solution is to have two -mp\_word arrays. One array will hold the squares and the other array will hold the double products. With both arrays the doubling and -carry propagation can be moved to a $O(n)$ work level outside the $O(n^2)$ level. In this case, we have an even simpler solution in mind. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\ -\textbf{Input}. mp\_int $a$ \\ -\textbf{Output}. $b \leftarrow a^2$ \\ -\hline \\ -Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\ -1. If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits. (\textit{mp\_grow}). \\ -2. If step 1 failed return(\textit{MP\_MEM}). \\ -\\ -3. $pa \leftarrow 2 \cdot a.used$ \\ -4. $\hat W1 \leftarrow 0$ \\ -5. for $ix$ from $0$ to $pa - 1$ do \\ -\hspace{3mm}5.1 $\_ \hat W \leftarrow 0$ \\ -\hspace{3mm}5.2 $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\ -\hspace{3mm}5.3 $tx \leftarrow ix - ty$ \\ -\hspace{3mm}5.4 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\ -\hspace{3mm}5.5 $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\ -\hspace{3mm}5.6 for $iz$ from $0$ to $iz - 1$ do \\ -\hspace{6mm}5.6.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\ -\hspace{3mm}5.7 $\_ \hat W \leftarrow 2 \cdot \_ \hat W + \hat W1$ \\ -\hspace{3mm}5.8 if $ix$ is even then \\ -\hspace{6mm}5.8.1 $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\ -\hspace{3mm}5.9 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\ -\hspace{3mm}5.10 $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\ -\\ -6. $oldused \leftarrow b.used$ \\ -7. $b.used \leftarrow 2 \cdot a.used$ \\ -8. for $ix$ from $0$ to $pa - 1$ do \\ -\hspace{3mm}8.1 $b_{ix} \leftarrow W_{ix}$ \\ -9. for $ix$ from $pa$ to $oldused - 1$ do \\ -\hspace{3mm}9.1 $b_{ix} \leftarrow 0$ \\ -10. Clamp excess digits from $b$. (\textit{mp\_clamp}) \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm fast\_s\_mp\_sqr} -\end{figure} - -\textbf{Algorithm fast\_s\_mp\_sqr.} -This algorithm computes the square of an input using the Comba technique. It is designed to be a replacement for algorithm -s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$. -This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of. - -First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively. This is because the inner loop -products are to be doubled. If we had added the previous carry in we would be doubling too much. Next we perform an -addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits. For example, $a_3 \cdot a_5$ is equal -$a_5 \cdot a_3$. Whereas in the multiplication case we would have $5 < a.used$ and $3 \ge 0$ is maintained since we double the sum -of the products just outside the inner loop we have to avoid doing this. This is also a good thing since we perform -fewer multiplications and the routine ends up being faster. - -Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8). We add in the square -only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position. - -EXAM,bn_fast_s_mp_sqr.c - -This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for -the special case of squaring. - -\subsection{Polynomial Basis Squaring} -The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring. The minor exception -is that $\zeta_y = f(y)g(y)$ is actually equivalent to $\zeta_y = f(y)^2$ since $f(y) = g(y)$. Instead of performing $2n + 1$ -multiplications to find the $\zeta$ relations, squaring operations are performed instead. - -\subsection{Karatsuba Squaring} -Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square. -Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial. The Karatsuba equation can be modified to square a -number with the following equation. - -\begin{equation} -h(x) = a^2x^2 + \left ((a + b)^2 - (a^2 + b^2) \right )x + b^2 -\end{equation} - -Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a + b)^2$. As in -Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of -$O \left ( n^{lg(3)} \right )$. - -If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm -instead? The answer to this arises from the cutoff point for squaring. As in multiplication there exists a cutoff point, at which the -time required for a Comba based squaring and a Karatsuba based squaring meet. Due to the overhead inherent in the Karatsuba method, the cutoff -point is fairly high. For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits. - -Consider squaring a 200 digit number with this technique. It will be split into two 100 digit halves which are subsequently squared. -The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm. If Karatsuba multiplication -were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\ -\textbf{Input}. mp\_int $a$ \\ -\textbf{Output}. $b \leftarrow a^2$ \\ -\hline \\ -1. Initialize the following temporary mp\_ints: $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\ -2. If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\ -\\ -Split the input. e.g. $a = x1\beta^B + x0$ \\ -3. $B \leftarrow \lfloor a.used / 2 \rfloor$ \\ -4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\ -5. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\ -\\ -Calculate the three squares. \\ -6. $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\ -7. $x1x1 \leftarrow x1^2$ \\ -8. $t1 \leftarrow x1 + x0$ (\textit{s\_mp\_add}) \\ -9. $t1 \leftarrow t1^2$ \\ -\\ -Compute the middle term. \\ -10. $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\ -11. $t1 \leftarrow t1 - t2$ \\ -\\ -Compute final product. \\ -12. $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\ -13. $x1x1 \leftarrow x1x1\beta^{2B}$ \\ -14. $t1 \leftarrow t1 + x0x0$ \\ -15. $b \leftarrow t1 + x1x1$ \\ -16. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_karatsuba\_sqr} -\end{figure} - -\textbf{Algorithm mp\_karatsuba\_sqr.} -This algorithm computes the square of an input $a$ using the Karatsuba technique. This algorithm is very similar to the Karatsuba based -multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings. - -The radix point for squaring is simply placed exactly in the middle of the digits when the input has an odd number of digits, otherwise it is -placed just below the middle. Step 3, 4 and 5 compute the two halves required using $B$ -as the radix point. The first two squares in steps 6 and 7 are rather straightforward while the last square is of a more compact form. - -By expanding $\left (x1 + x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $(x0 - x1)^2 - (x1^2 + x0^2) = 2 \cdot x0 \cdot x1$. -Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then -this method is faster. Assuming no further recursions occur, the difference can be estimated with the following inequality. - -Let $p$ represent the cost of a single precision addition and $q$ the cost of a single precision multiplication both in terms of time\footnote{Or -machine clock cycles.}. - -\begin{equation} -5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2 -\end{equation} - -For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$. This implies that the following inequality should hold. -\begin{center} -\begin{tabular}{rcl} -${5n \over 3} + 3n^2 + 3n$ & $<$ & ${n \over 3} + 6n^2$ \\ -${5 \over 3} + 3n + 3$ & $<$ & ${1 \over 3} + 6n$ \\ -${13 \over 9}$ & $<$ & $n$ \\ -\end{tabular} -\end{center} - -This results in a cutoff point around $n = 2$. As a consequence it is actually faster to compute the middle term the ``long way'' on processors -where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication. On -the Intel P4 processor this ratio is 1:29 making this method even more beneficial. The only common exception is the ARMv4 processor which has a -ratio of 1:7. } than simpler operations such as addition. - -EXAM,bn_mp_karatsuba_sqr.c - -This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul. It uses the same inline style to copy and -shift the input into the two halves. The loop from line @54,{@ to line @70,}@ has been modified since only one input exists. The \textbf{used} -count of both $x0$ and $x1$ is fixed up and $x0$ is clamped before the calculations begin. At this point $x1$ and $x0$ are valid equivalents -to the respective halves as if mp\_rshd and mp\_mod\_2d had been used. - -By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered. On the Athlon the cutoff point -is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}). On slower processors such as the Intel P4 -it is actually below the Comba limit (\textit{at 110 digits}). - -This routine uses the same error trap coding style as mp\_karatsuba\_sqr. As the temporary variables are initialized errors are -redirected to the error trap higher up. If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and -mp\_clears are executed normally. - -\subsection{Toom-Cook Squaring} -The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used -instead of multiplication to find the five relations. The reader is encouraged to read the description of the latter algorithm and try to -derive their own Toom-Cook squaring algorithm. - -\subsection{High Level Squaring} -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_sqr}. \\ -\textbf{Input}. mp\_int $a$ \\ -\textbf{Output}. $b \leftarrow a^2$ \\ -\hline \\ -1. If $a.used \ge TOOM\_SQR\_CUTOFF$ then \\ -\hspace{3mm}1.1 $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\ -2. else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\ -\hspace{3mm}2.1 $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\ -3. else \\ -\hspace{3mm}3.1 $digs \leftarrow a.used + b.used + 1$ \\ -\hspace{3mm}3.2 If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\ -\hspace{6mm}3.2.1 $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr. \\ -\hspace{3mm}3.3 else \\ -\hspace{6mm}3.3.1 $b \leftarrow a^2$ using algorithm s\_mp\_sqr. \\ -4. $b.sign \leftarrow MP\_ZPOS$ \\ -5. Return the result of the unsigned squaring performed. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_sqr} -\end{figure} - -\textbf{Algorithm mp\_sqr.} -This algorithm computes the square of the input using one of four different algorithms. If the input is very large and has at least -\textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used. If -neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used. - -EXAM,bn_mp_sqr.c - -\section*{Exercises} -\begin{tabular}{cl} -$\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\ - & that have different number of digits in Karatsuba multiplication. \\ - & \\ -$\left [ 2 \right ] $ & In ~SQUARE~ the fact that every column of a squaring is made up \\ - & of double products and at most one square is stated. Prove this statement. \\ - & \\ -$\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\ - & \\ -$\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\ - & \\ -$\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\ - & required for equation $6.7$ to be true. \\ - & \\ -$\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\ - & compute subsets of the columns in each thread. Determine a cutoff point where \\ - & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\ - &\\ -$\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook. You must \\ - & increase the throughput of mp\_exptmod() for random odd moduli in the range \\ - & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\ - & \\ -\end{tabular} - -\chapter{Modular Reduction} -MARK,REDUCTION -\section{Basics of Modular Reduction} -\index{modular residue} -Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms, -such as factoring. Modular reduction algorithms are the third class of algorithms of the ``multipliers'' set. A number $a$ is said to be \textit{reduced} -modulo another number $b$ by finding the remainder of the division $a/b$. Full integer division with remainder is a topic to be covered -in~\ref{sec:division}. - -Modular reduction is equivalent to solving for $r$ in the following equation. $a = bq + r$ where $q = \lfloor a/b \rfloor$. The result -$r$ is said to be ``congruent to $a$ modulo $b$'' which is also written as $r \equiv a \mbox{ (mod }b\mbox{)}$. In other vernacular $r$ is known as the -``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and -other forms of residues. - -Modular reductions are normally used to create either finite groups, rings or fields. The most common usage for performance driven modular reductions -is in modular exponentiation algorithms. That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible. This operation is used in the -RSA and Diffie-Hellman public key algorithms, for example. Modular multiplication and squaring also appears as a fundamental operation in -elliptic curve cryptographic algorithms. As will be discussed in the subsequent chapter there exist fast algorithms for computing modular -exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications. These algorithms will produce partial results in the -range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms. They have also been used to create redundancy check -algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems. - -\section{The Barrett Reduction} -The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate -division. Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to - -\begin{equation} -c = a - b \cdot \lfloor a/b \rfloor -\end{equation} - -Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper -targeted the DSP56K processor.} intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal. However, -DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types. -It would take another common optimization to optimize the algorithm. - -\subsection{Fixed Point Arithmetic} -The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers. Fixed -point arithmetic would become very popular as it greatly optimize the ``3d-shooter'' genre of games in the mid 1990s when floating point units were -fairly slow if not unavailable. The idea behind fixed point arithmetic is to take a normal $k$-bit integer data type and break it into $p$-bit -integer and a $q$-bit fraction part (\textit{where $p+q = k$}). - -In this system a $k$-bit integer $n$ would actually represent $n/2^q$. For example, with $q = 4$ the integer $n = 37$ would actually represent the -value $2.3125$. To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by -moving the implied decimal point back to where it should be. For example, with $q = 4$ to multiply the integers $9$ and $5$ they must be converted -to fixed point first by multiplying by $2^q$. Let $a = 9(2^q)$ represent the fixed point representation of $9$ and $b = 5(2^q)$ represent the -fixed point representation of $5$. The product $ab$ is equal to $45(2^{2q})$ which when normalized by dividing by $2^q$ produces $45(2^q)$. - -This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication -of two fixed point numbers. Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal. If $2^q$ is -equivalent to one than $2^q/b$ is equivalent to the fixed point approximation of $1/b$ using real arithmetic. Using this fact dividing an integer -$a$ by another integer $b$ can be achieved with the following expression. - -\begin{equation} -\lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor -\end{equation} - -The precision of the division is proportional to the value of $q$. If the divisor $b$ is used frequently as is the case with -modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift. Both operations -are considerably faster than division on most processors. - -Consider dividing $19$ by $5$. The correct result is $\lfloor 19/5 \rfloor = 3$. With $q = 3$ the reciprocal is $\lfloor 2^q/5 \rfloor = 1$ which -leads to a product of $19$ which when divided by $2^q$ produces $2$. However, with $q = 4$ the reciprocal is $\lfloor 2^q/5 \rfloor = 3$ and -the result of the emulated division is $\lfloor 3 \cdot 19 / 2^q \rfloor = 3$ which is correct. The value of $2^q$ must be close to or ideally -larger than the dividend. In effect if $a$ is the dividend then $q$ should allow $0 \le \lfloor a/2^q \rfloor \le 1$ in order for this approach -to work correctly. Plugging this form of divison into the original equation the following modular residue equation arises. - -\begin{equation} -c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor -\end{equation} - -Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol. Using the $\mu$ -variable also helps re-inforce the idea that it is meant to be computed once and re-used. - -\begin{equation} -c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor -\end{equation} - -Provided that $2^q \ge a$ this algorithm will produce a quotient that is either exactly correct or off by a value of one. In the context of Barrett -reduction the value of $a$ is bound by $0 \le a \le (b - 1)^2$ meaning that $2^q \ge b^2$ is sufficient to ensure the reciprocal will have enough -precision. - -Let $n$ represent the number of digits in $b$. This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and -another $n^2$ single precision multiplications to find the residue. In total $3n^2$ single precision multiplications are required to -reduce the number. - -For example, if $b = 1179677$ and $q = 41$ ($2^q > b^2$), then the reciprocal $\mu$ is equal to $\lfloor 2^q / b \rfloor = 1864089$. Consider reducing -$a = 180388626447$ modulo $b$ using the above reduction equation. The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$. -By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found. - -\subsection{Choosing a Radix Point} -Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications. If that were the best -that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$. -See~\ref{sec:division} for further details.} might as well be used in its place. The key to optimizing the reduction is to reduce the precision of -the initial multiplication that finds the quotient. - -Let $a$ represent the number of which the residue is sought. Let $b$ represent the modulus used to find the residue. Let $m$ represent -the number of digits in $b$. For the purposes of this discussion we will assume that the number of digits in $a$ is $2m$, which is generally true if -two $m$-digit numbers have been multiplied. Dividing $a$ by $b$ is the same as dividing a $2m$ digit integer by a $m$ digit integer. Digits below the -$m - 1$'th digit of $a$ will contribute at most a value of $1$ to the quotient because $\beta^k < b$ for any $0 \le k \le m - 1$. Another way to -express this is by re-writing $a$ as two parts. If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then -${a \over b} \equiv {{a' + a''} \over b}$ which is equivalent to ${a' \over b} + {a'' \over b}$. Since $a'$ is bound to be less than $b$ the quotient -is bound by $0 \le {a' \over b} < 1$. - -Since the digits of $a'$ do not contribute much to the quotient the observation is that they might as well be zero. However, if the digits -``might as well be zero'' they might as well not be there in the first place. Let $q_0 = \lfloor a/\beta^{m-1} \rfloor$ represent the input -with the irrelevant digits trimmed. Now the modular reduction is trimmed to the almost equivalent equation - -\begin{equation} -c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor -\end{equation} - -Note that the original divisor $2^q$ has been replaced with $\beta^{m+1}$ where in this case $q$ is a multiple of $lg(\beta)$. Also note that the -exponent on the divisor when added to the amount $q_0$ was shifted by equals $2m$. If the optimization had not been performed the divisor -would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient -$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ can be off from the true quotient by at most two. The original fixed point quotient can be off -by as much as one (\textit{provided the radix point is chosen suitably}) and now that the lower irrelevent digits have been trimmed the quotient -can be off by an additional value of one for a total of at most two. This implies that -$0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. By first subtracting $b$ times the quotient and then conditionally subtracting -$b$ once or twice the residue is found. - -The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single -precision multiplications, ignoring the subtractions required. In total $2m^2 + m$ single precision multiplications are required to find the residue. -This is considerably faster than the original attempt. - -For example, let $\beta = 10$ represent the radix of the digits. Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$ -represent the value of which the residue is desired. In this case $q = 8$ since $10^7 < 9999^2$ meaning that $\mu = \lfloor \beta^{q}/b \rfloor = 10001$. -With the new observation the multiplicand for the quotient is equal to $q_0 = \lfloor a / \beta^{m - 1} \rfloor = 99929$. The quotient is then -$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor = 9993$. Subtracting $9993b$ from $a$ and the correct residue $a \equiv 9871 \mbox{ (mod }b\mbox{)}$ -is found. - -\subsection{Trimming the Quotient} -So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications. As -it stands now the algorithm is already fairly fast compared to a full integer division algorithm. However, there is still room for -optimization. - -After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower -half of the product. It would be nice to be able to remove those digits from the product to effectively cut down the number of single precision -multiplications. If the number of digits in the modulus $m$ is far less than $\beta$ a full product is not required for the algorithm to work properly. -In fact the lower $m - 2$ digits will not affect the upper half of the product at all and do not need to be computed. - -The value of $\mu$ is a $m$-digit number and $q_0$ is a $m + 1$ digit number. Using a full multiplier $(m + 1)(m) = m^2 + m$ single precision -multiplications would be required. Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number -of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications. - -\subsection{Trimming the Residue} -After the quotient has been calculated it is used to reduce the input. As previously noted the algorithm is not exact and it can be off by a small -multiple of the modulus, that is $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. If $b$ is $m$ digits than the -result of reduction equation is a value of at most $m + 1$ digits (\textit{provided $3 < \beta$}) implying that the upper $m - 1$ digits are -implicitly zero. - -The next optimization arises from this very fact. Instead of computing $b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ using a full -$O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed. Similarly the value of $a$ can -be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well. A multiplication that produces -only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications. - -With both optimizations in place the algorithm is the algorithm Barrett proposed. It requires $m^2 + 2m - 1$ single precision multiplications which -is considerably faster than the straightforward $3m^2$ method. - -\subsection{The Barrett Algorithm} -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_reduce}. \\ -\textbf{Input}. mp\_int $a$, mp\_int $b$ and $\mu = \lfloor \beta^{2m}/b \rfloor, m = \lceil lg_{\beta}(b) \rceil, (0 \le a < b^2, b > 1)$ \\ -\textbf{Output}. $a \mbox{ (mod }b\mbox{)}$ \\ -\hline \\ -Let $m$ represent the number of digits in $b$. \\ -1. Make a copy of $a$ and store it in $q$. (\textit{mp\_init\_copy}) \\ -2. $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\ -\\ -Produce the quotient. \\ -3. $q \leftarrow q \cdot \mu$ (\textit{note: only produce digits at or above $m-1$}) \\ -4. $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\ -\\ -Subtract the multiple of modulus from the input. \\ -5. $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\ -6. $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\ -7. $a \leftarrow a - q$ (\textit{mp\_sub}) \\ -\\ -Add $\beta^{m+1}$ if a carry occured. \\ -8. If $a < 0$ then (\textit{mp\_cmp\_d}) \\ -\hspace{3mm}8.1 $q \leftarrow 1$ (\textit{mp\_set}) \\ -\hspace{3mm}8.2 $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\ -\hspace{3mm}8.3 $a \leftarrow a + q$ \\ -\\ -Now subtract the modulus if the residue is too large (e.g. quotient too small). \\ -9. While $a \ge b$ do (\textit{mp\_cmp}) \\ -\hspace{3mm}9.1 $c \leftarrow a - b$ \\ -10. Clear $q$. \\ -11. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_reduce} -\end{figure} - -\textbf{Algorithm mp\_reduce.} -This algorithm will reduce the input $a$ modulo $b$ in place using the Barrett algorithm. It is loosely based on algorithm 14.42 of HAC -\cite[pp. 602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}. The algorithm has several restrictions and assumptions which must -be adhered to for the algorithm to work. - -First the modulus $b$ is assumed to be positive and greater than one. If the modulus were less than or equal to one than subtracting -a multiple of it would either accomplish nothing or actually enlarge the input. The input $a$ must be in the range $0 \le a < b^2$ in order -for the quotient to have enough precision. If $a$ is the product of two numbers that were already reduced modulo $b$, this will not be a problem. -Technically the algorithm will still work if $a \ge b^2$ but it will take much longer to finish. The value of $\mu$ is passed as an argument to this -algorithm and is assumed to be calculated and stored before the algorithm is used. - -Recall that the multiplication for the quotient on step 3 must only produce digits at or above the $m-1$'th position. An algorithm called -$s\_mp\_mul\_high\_digs$ which has not been presented is used to accomplish this task. The algorithm is based on $s\_mp\_mul\_digs$ except that -instead of stopping at a given level of precision it starts at a given level of precision. This optimal algorithm can only be used if the number -of digits in $b$ is very much smaller than $\beta$. - -While it is known that -$a \ge b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ only the lower $m+1$ digits are being used to compute the residue, so an implied -``borrow'' from the higher digits might leave a negative result. After the multiple of the modulus has been subtracted from $a$ the residue must be -fixed up in case it is negative. The invariant $\beta^{m+1}$ must be added to the residue to make it positive again. - -The while loop at step 9 will subtract $b$ until the residue is less than $b$. If the algorithm is performed correctly this step is -performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should. - -EXAM,bn_mp_reduce.c - -The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up. This essentially halves -the number of single precision multiplications required. However, the optimization is only safe if $\beta$ is much larger than the number of digits -in the modulus. In the source code this is evaluated on lines @36,if@ to @44,}@ where algorithm s\_mp\_mul\_high\_digs is used when it is -safe to do so. - -\subsection{The Barrett Setup Algorithm} -In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance. Ideally this value should be computed once and stored for -future use so that the Barrett algorithm can be used without delay. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_reduce\_setup}. \\ -\textbf{Input}. mp\_int $a$ ($a > 1$) \\ -\textbf{Output}. $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\ -\hline \\ -1. $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot m}$ (\textit{mp\_2expt}) \\ -2. $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\ -3. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_reduce\_setup} -\end{figure} - -\textbf{Algorithm mp\_reduce\_setup.} -This algorithm computes the reciprocal $\mu$ required for Barrett reduction. First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot m}$ which -is equivalent and much faster. The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$. - -EXAM,bn_mp_reduce_setup.c - -This simple routine calculates the reciprocal $\mu$ required by Barrett reduction. Note the extended usage of algorithm mp\_div where the variable -which would received the remainder is passed as NULL. As will be discussed in~\ref{sec:division} the division routine allows both the quotient and the -remainder to be passed as NULL meaning to ignore the value. - -\section{The Montgomery Reduction} -Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting -form of reduction in common use. It computes a modular residue which is not actually equal to the residue of the input yet instead equal to a -residue times a constant. However, as perplexing as this may sound the algorithm is relatively simple and very efficient. - -Throughout this entire section the variable $n$ will represent the modulus used to form the residue. As will be discussed shortly the value of -$n$ must be odd. The variable $x$ will represent the quantity of which the residue is sought. Similar to the Barrett algorithm the input -is restricted to $0 \le x < n^2$. To begin the description some simple number theory facts must be established. - -\textbf{Fact 1.} Adding $n$ to $x$ does not change the residue since in effect it adds one to the quotient $\lfloor x / n \rfloor$. Another way -to explain this is that $n$ is (\textit{or multiples of $n$ are}) congruent to zero modulo $n$. Adding zero will not change the value of the residue. - -\textbf{Fact 2.} If $x$ is even then performing a division by two in $\Z$ is congruent to $x \cdot 2^{-1} \mbox{ (mod }n\mbox{)}$. Actually -this is an application of the fact that if $x$ is evenly divisible by any $k \in \Z$ then division in $\Z$ will be congruent to -multiplication by $k^{-1}$ modulo $n$. - -From these two simple facts the following simple algorithm can be derived. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Montgomery Reduction}. \\ -\textbf{Input}. Integer $x$, $n$ and $k$ \\ -\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\ -\hline \\ -1. for $t$ from $1$ to $k$ do \\ -\hspace{3mm}1.1 If $x$ is odd then \\ -\hspace{6mm}1.1.1 $x \leftarrow x + n$ \\ -\hspace{3mm}1.2 $x \leftarrow x/2$ \\ -2. Return $x$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Montgomery Reduction} -\end{figure} - -The algorithm reduces the input one bit at a time using the two congruencies stated previously. Inside the loop $n$, which is odd, is -added to $x$ if $x$ is odd. This forces $x$ to be even which allows the division by two in $\Z$ to be congruent to a modular division by two. Since -$x$ is assumed to be initially much larger than $n$ the addition of $n$ will contribute an insignificant magnitude to $x$. Let $r$ represent the -final result of the Montgomery algorithm. If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to -$0 \le r < \lfloor x/2^k \rfloor + n$. As a result at most a single subtraction is required to get the residue desired. - -\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{|c|l|} -\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\ -\hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\ -\hline $2$ & $x/2 = 1453$ \\ -\hline $3$ & $x + n = 1710$, $x/2 = 855$ \\ -\hline $4$ & $x + n = 1112$, $x/2 = 556$ \\ -\hline $5$ & $x/2 = 278$ \\ -\hline $6$ & $x/2 = 139$ \\ -\hline $7$ & $x + n = 396$, $x/2 = 198$ \\ -\hline $8$ & $x/2 = 99$ \\ -\hline $9$ & $x + n = 356$, $x/2 = 178$ \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Example of Montgomery Reduction (I)} -\label{fig:MONT1} -\end{figure} - -Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 9$ (note $\beta^k = 512$ which is larger than $n$). The result of -the algorithm $r = 178$ is congruent to the value of $2^{-9} \cdot 5555 \mbox{ (mod }257\mbox{)}$. When $r$ is multiplied by $2^9$ modulo $257$ the correct residue -$r \equiv 158$ is produced. - -Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$. The current algorithm requires $2k^2$ single precision shifts -and $k^2$ single precision additions. At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful. -Fortunately there exists an alternative representation of the algorithm. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Montgomery Reduction} (modified I). \\ -\textbf{Input}. Integer $x$, $n$ and $k$ ($2^k > n$) \\ -\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\ -\hline \\ -1. for $t$ from $1$ to $k$ do \\ -\hspace{3mm}1.1 If the $t$'th bit of $x$ is one then \\ -\hspace{6mm}1.1.1 $x \leftarrow x + 2^tn$ \\ -2. Return $x/2^k$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Montgomery Reduction (modified I)} -\end{figure} - -This algorithm is equivalent since $2^tn$ is a multiple of $n$ and the lower $k$ bits of $x$ are zero by step 2. The number of single -precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement. - -\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{|c|l|r|} -\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\ -\hline -- & $5555$ & $1010110110011$ \\ -\hline $1$ & $x + 2^{0}n = 5812$ & $1011010110100$ \\ -\hline $2$ & $5812$ & $1011010110100$ \\ -\hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\ -\hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\ -\hline $5$ & $8896$ & $10001011000000$ \\ -\hline $6$ & $8896$ & $10001011000000$ \\ -\hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\ -\hline $8$ & $25344$ & $110001100000000$ \\ -\hline $9$ & $x + 2^{7}n = 91136$ & $10110010000000000$ \\ -\hline -- & $x/2^k = 178$ & \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Example of Montgomery Reduction (II)} -\label{fig:MONT2} -\end{figure} - -Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 9$. -With this algorithm a single shift right at the end is the only right shift required to reduce the input instead of $k$ right shifts inside the -loop. Note that for the iterations $t = 2, 5, 6$ and $8$ where the result $x$ is not changed. In those iterations the $t$'th bit of $x$ is -zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero. - -\subsection{Digit Based Montgomery Reduction} -Instead of computing the reduction on a bit-by-bit basis it is actually much faster to compute it on digit-by-digit basis. Consider the -previous algorithm re-written to compute the Montgomery reduction in this new fashion. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Montgomery Reduction} (modified II). \\ -\textbf{Input}. Integer $x$, $n$ and $k$ ($\beta^k > n$) \\ -\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ -\hline \\ -1. for $t$ from $0$ to $k - 1$ do \\ -\hspace{3mm}1.1 $x \leftarrow x + \mu n \beta^t$ \\ -2. Return $x/\beta^k$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Montgomery Reduction (modified II)} -\end{figure} - -The value $\mu n \beta^t$ is a multiple of the modulus $n$ meaning that it will not change the residue. If the first digit of -the value $\mu n \beta^t$ equals the negative (modulo $\beta$) of the $t$'th digit of $x$ then the addition will result in a zero digit. This -problem breaks down to solving the following congruency. - -\begin{center} -\begin{tabular}{rcl} -$x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\ -$\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\ -$\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\ -\end{tabular} -\end{center} - -In each iteration of the loop on step 1 a new value of $\mu$ must be calculated. The value of $-1/n_0 \mbox{ (mod }\beta\mbox{)}$ is used -extensively in this algorithm and should be precomputed. Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$. - -For example, let $\beta = 10$ represent the radix. Let $n = 17$ represent the modulus which implies $k = 2$ and $\rho \equiv 7$. Let $x = 33$ -represent the value to reduce. - -\newpage\begin{figure} -\begin{center} -\begin{tabular}{|c|c|c|} -\hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\ -\hline -- & $33$ & --\\ -\hline $0$ & $33 + \mu n = 50$ & $1$ \\ -\hline $1$ & $50 + \mu n \beta = 900$ & $5$ \\ -\hline -\end{tabular} -\end{center} -\caption{Example of Montgomery Reduction} -\end{figure} - -The final result $900$ is then divided by $\beta^k$ to produce the final result $9$. The first observation is that $9 \nequiv x \mbox{ (mod }n\mbox{)}$ -which implies the result is not the modular residue of $x$ modulo $n$. However, recall that the residue is actually multiplied by $\beta^{-k}$ in -the algorithm. To get the true residue the value must be multiplied by $\beta^k$. In this case $\beta^k \equiv 15 \mbox{ (mod }n\mbox{)}$ and -the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$. - -\subsection{Baseline Montgomery Reduction} -The baseline Montgomery reduction algorithm will produce the residue for any size input. It is designed to be a catch-all algororithm for -Montgomery reductions. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_montgomery\_reduce}. \\ -\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\ -\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\ -\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ -\hline \\ -1. $digs \leftarrow 2n.used + 1$ \\ -2. If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\ -\hspace{3mm}2.1 Use algorithm fast\_mp\_montgomery\_reduce instead. \\ -\\ -Setup $x$ for the reduction. \\ -3. If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\ -4. $x.used \leftarrow digs$ \\ -\\ -Eliminate the lower $k$ digits. \\ -5. For $ix$ from $0$ to $k - 1$ do \\ -\hspace{3mm}5.1 $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}5.2 $u \leftarrow 0$ \\ -\hspace{3mm}5.3 For $iy$ from $0$ to $k - 1$ do \\ -\hspace{6mm}5.3.1 $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\ -\hspace{6mm}5.3.2 $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{6mm}5.3.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -\hspace{3mm}5.4 While $u > 0$ do \\ -\hspace{6mm}5.4.1 $iy \leftarrow iy + 1$ \\ -\hspace{6mm}5.4.2 $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\ -\hspace{6mm}5.4.3 $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\ -\hspace{6mm}5.4.4 $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\ -\\ -Divide by $\beta^k$ and fix up as required. \\ -6. $x \leftarrow \lfloor x / \beta^k \rfloor$ \\ -7. If $x \ge n$ then \\ -\hspace{3mm}7.1 $x \leftarrow x - n$ \\ -8. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_montgomery\_reduce} -\end{figure} - -\textbf{Algorithm mp\_montgomery\_reduce.} -This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm. The algorithm is loosely based -on algorithm 14.32 of \cite[pp.601]{HAC} except it merges the multiplication of $\mu n \beta^t$ with the addition in the inner loop. The -restrictions on this algorithm are fairly easy to adapt to. First $0 \le x < n^2$ bounds the input to numbers in the same range as -for the Barrett algorithm. Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$. $\rho$ must be calculated in -advance of this algorithm. Finally the variable $k$ is fixed and a pseudonym for $n.used$. - -Step 2 decides whether a faster Montgomery algorithm can be used. It is based on the Comba technique meaning that there are limits on -the size of the input. This algorithm is discussed in ~COMBARED~. - -Step 5 is the main reduction loop of the algorithm. The value of $\mu$ is calculated once per iteration in the outer loop. The inner loop -calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits. Both the addition and -multiplication are performed in the same loop to save time and memory. Step 5.4 will handle any additional carries that escape the inner loop. - -Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications -in the inner loop. In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision -multiplications. - -EXAM,bn_mp_montgomery_reduce.c - -This is the baseline implementation of the Montgomery reduction algorithm. Lines @30,digs@ to @35,}@ determine if the Comba based -routine can be used instead. Line @47,mu@ computes the value of $\mu$ for that particular iteration of the outer loop. - -The multiplication $\mu n \beta^{ix}$ is performed in one step in the inner loop. The alias $tmpx$ refers to the $ix$'th digit of $x$ and -the alias $tmpn$ refers to the modulus $n$. - -\subsection{Faster ``Comba'' Montgomery Reduction} -MARK,COMBARED - -The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial -nature of the inner loop. The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba -technique. The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates -a $k \times 1$ product $k$ times. - -The biggest obstacle is that at the $ix$'th iteration of the outer loop the value of $x_{ix}$ is required to calculate $\mu$. This means the -carries from $0$ to $ix - 1$ must have been propagated upwards to form a valid $ix$'th digit. The solution as it turns out is very simple. -Perform a Comba like multiplier and inside the outer loop just after the inner loop fix up the $ix + 1$'th digit by forwarding the carry. - -With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases -the speed of the algorithm. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\ -\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\ -\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\ -\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ -\hline \\ -Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\ -1. if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\ -Copy the digits of $x$ into the array $\hat W$ \\ -2. For $ix$ from $0$ to $x.used - 1$ do \\ -\hspace{3mm}2.1 $\hat W_{ix} \leftarrow x_{ix}$ \\ -3. For $ix$ from $x.used$ to $2n.used - 1$ do \\ -\hspace{3mm}3.1 $\hat W_{ix} \leftarrow 0$ \\ -Elimiate the lower $k$ digits. \\ -4. for $ix$ from $0$ to $n.used - 1$ do \\ -\hspace{3mm}4.1 $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}4.2 For $iy$ from $0$ to $n.used - 1$ do \\ -\hspace{6mm}4.2.1 $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\ -\hspace{3mm}4.3 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\ -Propagate carries upwards. \\ -5. for $ix$ from $n.used$ to $2n.used + 1$ do \\ -\hspace{3mm}5.1 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\ -Shift right and reduce modulo $\beta$ simultaneously. \\ -6. for $ix$ from $0$ to $n.used + 1$ do \\ -\hspace{3mm}6.1 $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\ -Zero excess digits and fixup $x$. \\ -7. if $x.used > n.used + 1$ then do \\ -\hspace{3mm}7.1 for $ix$ from $n.used + 1$ to $x.used - 1$ do \\ -\hspace{6mm}7.1.1 $x_{ix} \leftarrow 0$ \\ -8. $x.used \leftarrow n.used + 1$ \\ -9. Clamp excessive digits of $x$. \\ -10. If $x \ge n$ then \\ -\hspace{3mm}10.1 $x \leftarrow x - n$ \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm fast\_mp\_montgomery\_reduce} -\end{figure} - -\textbf{Algorithm fast\_mp\_montgomery\_reduce.} -This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique. It is on most computer platforms significantly -faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}). The algorithm has the same restrictions -on the input as the baseline reduction algorithm. An additional two restrictions are imposed on this algorithm. The number of digits $k$ in the -the modulus $n$ must not violate $MP\_WARRAY > 2k +1$ and $n < \delta$. When $\beta = 2^{28}$ this algorithm can be used to reduce modulo -a modulus of at most $3,556$ bits in length. - -As in the other Comba reduction algorithms there is a $\hat W$ array which stores the columns of the product. It is initially filled with the -contents of $x$ with the excess digits zeroed. The reduction loop is very similar the to the baseline loop at heart. The multiplication on step -4.1 can be single precision only since $ab \mbox{ (mod }\beta\mbox{)} \equiv (a \mbox{ mod }\beta)(b \mbox{ mod }\beta)$. Some multipliers such -as those on the ARM processors take a variable length time to complete depending on the number of bytes of result it must produce. By performing -a single precision multiplication instead half the amount of time is spent. - -Also note that digit $\hat W_{ix}$ must have the carry from the $ix - 1$'th digit propagated upwards in order for this to work. That is what step -4.3 will do. In effect over the $n.used$ iterations of the outer loop the $n.used$'th lower columns all have the their carries propagated forwards. Note -how the upper bits of those same words are not reduced modulo $\beta$. This is because those values will be discarded shortly and there is no -point. - -Step 5 will propagate the remainder of the carries upwards. On step 6 the columns are reduced modulo $\beta$ and shifted simultaneously as they are -stored in the destination $x$. - -EXAM,bn_fast_mp_montgomery_reduce.c - -The $\hat W$ array is first filled with digits of $x$ on line @49,for@ then the rest of the digits are zeroed on line @54,for@. Both loops share -the same alias variables to make the code easier to read. - -The value of $\mu$ is calculated in an interesting fashion. First the value $\hat W_{ix}$ is reduced modulo $\beta$ and cast to a mp\_digit. This -forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision. Line @101,>>@ fixes the carry -for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$. - -The for loop on line @113,for@ propagates the rest of the carries upwards through the columns. The for loop on line @126,for@ reduces the columns -modulo $\beta$ and shifts them $k$ places at the same time. The alias $\_ \hat W$ actually refers to the array $\hat W$ starting at the $n.used$'th -digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$. - -\subsection{Montgomery Setup} -To calculate the variable $\rho$ a relatively simple algorithm will be required. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_montgomery\_setup}. \\ -\textbf{Input}. mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\ -\textbf{Output}. $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\ -\hline \\ -1. $b \leftarrow n_0$ \\ -2. If $b$ is even return(\textit{MP\_VAL}) \\ -3. $x \leftarrow (((b + 2) \mbox{ AND } 4) << 1) + b$ \\ -4. for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\ -\hspace{3mm}4.1 $x \leftarrow x \cdot (2 - bx)$ \\ -5. $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\ -6. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_montgomery\_setup} -\end{figure} - -\textbf{Algorithm mp\_montgomery\_setup.} -This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms. It uses a very interesting trick -to calculate $1/n_0$ when $\beta$ is a power of two. - -EXAM,bn_mp_montgomery_setup.c - -This source code computes the value of $\rho$ required to perform Montgomery reduction. It has been modified to avoid performing excess -multiplications when $\beta$ is not the default 28-bits. - -\section{The Diminished Radix Algorithm} -The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett -or Montgomery methods for certain forms of moduli. The technique is based on the following simple congruence. - -\begin{equation} -(x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)} -\end{equation} - -This observation was used in the MMB \cite{MMB} block cipher to create a diffusion primitive. It used the fact that if $n = 2^{31}$ and $k=1$ that -then a x86 multiplier could produce the 62-bit product and use the ``shrd'' instruction to perform a double-precision right shift. The proof -of the above equation is very simple. First write $x$ in the product form. - -\begin{equation} -x = qn + r -\end{equation} - -Now reduce both sides modulo $(n - k)$. - -\begin{equation} -x \equiv qk + r \mbox{ (mod }(n-k)\mbox{)} -\end{equation} - -The variable $n$ reduces modulo $n - k$ to $k$. By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$ -into the equation the original congruence is reproduced, thus concluding the proof. The following algorithm is based on this observation. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Diminished Radix Reduction}. \\ -\textbf{Input}. Integer $x$, $n$, $k$ \\ -\textbf{Output}. $x \mbox{ mod } (n - k)$ \\ -\hline \\ -1. $q \leftarrow \lfloor x / n \rfloor$ \\ -2. $q \leftarrow k \cdot q$ \\ -3. $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\ -4. $x \leftarrow x + q$ \\ -5. If $x \ge (n - k)$ then \\ -\hspace{3mm}5.1 $x \leftarrow x - (n - k)$ \\ -\hspace{3mm}5.2 Goto step 1. \\ -6. Return $x$ \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Diminished Radix Reduction} -\label{fig:DR} -\end{figure} - -This algorithm will reduce $x$ modulo $n - k$ and return the residue. If $0 \le x < (n - k)^2$ then the algorithm will loop almost always -once or twice and occasionally three times. For simplicity sake the value of $x$ is bounded by the following simple polynomial. - -\begin{equation} -0 \le x < n^2 + k^2 - 2nk -\end{equation} - -The true bound is $0 \le x < (n - k - 1)^2$ but this has quite a few more terms. The value of $q$ after step 1 is bounded by the following. - -\begin{equation} -q < n - 2k - k^2/n -\end{equation} - -Since $k^2$ is going to be considerably smaller than $n$ that term will always be zero. The value of $x$ after step 3 is bounded trivially as -$0 \le x < n$. By step four the sum $x + q$ is bounded by - -\begin{equation} -0 \le q + x < (k + 1)n - 2k^2 - 1 -\end{equation} - -With a second pass $q$ will be loosely bounded by $0 \le q < k^2$ after step 2 while $x$ will still be loosely bounded by $0 \le x < n$ after step 3. After the second pass it is highly unlike that the -sum in step 4 will exceed $n - k$. In practice fewer than three passes of the algorithm are required to reduce virtually every input in the -range $0 \le x < (n - k - 1)^2$. - -\begin{figure} -\begin{small} -\begin{center} -\begin{tabular}{|l|} -\hline -$x = 123456789, n = 256, k = 3$ \\ -\hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\ -$q \leftarrow q*k = 1446759$ \\ -$x \leftarrow x \mbox{ mod } n = 21$ \\ -$x \leftarrow x + q = 1446780$ \\ -$x \leftarrow x - (n - k) = 1446527$ \\ -\hline -$q \leftarrow \lfloor x/n \rfloor = 5650$ \\ -$q \leftarrow q*k = 16950$ \\ -$x \leftarrow x \mbox{ mod } n = 127$ \\ -$x \leftarrow x + q = 17077$ \\ -$x \leftarrow x - (n - k) = 16824$ \\ -\hline -$q \leftarrow \lfloor x/n \rfloor = 65$ \\ -$q \leftarrow q*k = 195$ \\ -$x \leftarrow x \mbox{ mod } n = 184$ \\ -$x \leftarrow x + q = 379$ \\ -$x \leftarrow x - (n - k) = 126$ \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Example Diminished Radix Reduction} -\label{fig:EXDR} -\end{figure} - -Figure~\ref{fig:EXDR} demonstrates the reduction of $x = 123456789$ modulo $n - k = 253$ when $n = 256$ and $k = 3$. Note that even while $x$ -is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast. In this case only -three passes were required to find the residue $x \equiv 126$. - - -\subsection{Choice of Moduli} -On the surface this algorithm looks like a very expensive algorithm. It requires a couple of subtractions followed by multiplication and other -modular reductions. The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen. - -Division in general is a very expensive operation to perform. The one exception is when the division is by a power of the radix of representation used. -Division by ten for example is simple for pencil and paper mathematics since it amounts to shifting the decimal place to the right. Similarly division -by two (\textit{or powers of two}) is very simple for binary computers to perform. It would therefore seem logical to choose $n$ of the form $2^p$ -which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits. - -However, there is one operation related to division of power of twos that is even faster than this. If $n = \beta^p$ then the division may be -performed by moving whole digits to the right $p$ places. In practice division by $\beta^p$ is much faster than division by $2^p$ for any $p$. -Also with the choice of $n = \beta^p$ reducing $x$ modulo $n$ merely requires zeroing the digits above the $p-1$'th digit of $x$. - -Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted -modulus'' will refer to a modulus of the form $2^p - k$. The word ``restricted'' in this case refers to the fact that it is based on the -$2^p$ logic except $p$ must be a multiple of $lg(\beta)$. - -\subsection{Choice of $k$} -Now that division and reduction (\textit{step 1 and 3 of figure~\ref{fig:DR}}) have been optimized to simple digit operations the multiplication by $k$ -in step 2 is the most expensive operation. Fortunately the choice of $k$ is not terribly limited. For all intents and purposes it might -as well be a single digit. The smaller the value of $k$ is the faster the algorithm will be. - -\subsection{Restricted Diminished Radix Reduction} -The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$. This algorithm can reduce -an input $x$ within the range $0 \le x < n^2$ using only a couple passes of the algorithm demonstrated in figure~\ref{fig:DR}. The implementation -of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition -of $x$ and $q$. The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular -exponentiations are performed. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_dr\_reduce}. \\ -\textbf{Input}. mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\ -\hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\ -\textbf{Output}. $x \mbox{ mod } n$ \\ -\hline \\ -1. $m \leftarrow n.used$ \\ -2. If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\ -3. $\mu \leftarrow 0$ \\ -4. for $i$ from $0$ to $m - 1$ do \\ -\hspace{3mm}4.1 $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\ -\hspace{3mm}4.2 $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}4.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -5. $x_{m} \leftarrow \mu$ \\ -6. for $i$ from $m + 1$ to $x.used - 1$ do \\ -\hspace{3mm}6.1 $x_{i} \leftarrow 0$ \\ -7. Clamp excess digits of $x$. \\ -8. If $x \ge n$ then \\ -\hspace{3mm}8.1 $x \leftarrow x - n$ \\ -\hspace{3mm}8.2 Goto step 3. \\ -9. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_dr\_reduce} -\end{figure} - -\textbf{Algorithm mp\_dr\_reduce.} -This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$. It has similar restrictions to that of the Barrett reduction -with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$. - -This algorithm essentially implements the pseudo-code in figure~\ref{fig:DR} except with a slight optimization. The division by $\beta^m$, multiplication by $k$ -and addition of $x \mbox{ mod }\beta^m$ are all performed simultaneously inside the loop on step 4. The division by $\beta^m$ is emulated by accessing -the term at the $m+i$'th position which is subsequently multiplied by $k$ and added to the term at the $i$'th position. After the loop the $m$'th -digit is set to the carry and the upper digits are zeroed. Steps 5 and 6 emulate the reduction modulo $\beta^m$ that should have happend to -$x$ before the addition of the multiple of the upper half. - -At step 8 if $x$ is still larger than $n$ another pass of the algorithm is required. First $n$ is subtracted from $x$ and then the algorithm resumes -at step 3. - -EXAM,bn_mp_dr_reduce.c - -The first step is to grow $x$ as required to $2m$ digits since the reduction is performed in place on $x$. The label on line @49,top:@ is where -the algorithm will resume if further reduction passes are required. In theory it could be placed at the top of the function however, the size of -the modulus and question of whether $x$ is large enough are invariant after the first pass meaning that it would be a waste of time. - -The aliases $tmpx1$ and $tmpx2$ refer to the digits of $x$ where the latter is offset by $m$ digits. By reading digits from $x$ offset by $m$ digits -a division by $\beta^m$ can be simulated virtually for free. The loop on line @61,for@ performs the bulk of the work (\textit{corresponds to step 4 of algorithm 7.11}) -in this algorithm. - -By line @68,mu@ the pointer $tmpx1$ points to the $m$'th digit of $x$ which is where the final carry will be placed. Similarly by line @71,for@ the -same pointer will point to the $m+1$'th digit where the zeroes will be placed. - -Since the algorithm is only valid if both $x$ and $n$ are greater than zero an unsigned comparison suffices to determine if another pass is required. -With the same logic at line @82,sub@ the value of $x$ is known to be greater than or equal to $n$ meaning that an unsigned subtraction can be used -as well. Since the destination of the subtraction is the larger of the inputs the call to algorithm s\_mp\_sub cannot fail and the return code -does not need to be checked. - -\subsubsection{Setup} -To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required. This algorithm is not really complicated but provided for -completeness. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_dr\_setup}. \\ -\textbf{Input}. mp\_int $n$ \\ -\textbf{Output}. $k = \beta - n_0$ \\ -\hline \\ -1. $k \leftarrow \beta - n_0$ \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_dr\_setup} -\end{figure} - -EXAM,bn_mp_dr_setup.c - -\subsubsection{Modulus Detection} -Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus. An integer is said to be -of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\ -\textbf{Input}. mp\_int $n$ \\ -\textbf{Output}. $1$ if $n$ is in D.R form, $0$ otherwise \\ -\hline -1. If $n.used < 2$ then return($0$). \\ -2. for $ix$ from $1$ to $n.used - 1$ do \\ -\hspace{3mm}2.1 If $n_{ix} \ne \beta - 1$ return($0$). \\ -3. Return($1$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_dr\_is\_modulus} -\end{figure} - -\textbf{Algorithm mp\_dr\_is\_modulus.} -This algorithm determines if a value is in Diminished Radix form. Step 1 rejects obvious cases where fewer than two digits are -in the mp\_int. Step 2 tests all but the first digit to see if they are equal to $\beta - 1$. If the algorithm manages to get to -step 3 then $n$ must be of Diminished Radix form. - -EXAM,bn_mp_dr_is_modulus.c - -\subsection{Unrestricted Diminished Radix Reduction} -The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$. This algorithm -is a straightforward adaptation of algorithm~\ref{fig:DR}. - -In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead. However, this new -algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_reduce\_2k}. \\ -\textbf{Input}. mp\_int $a$ and $n$. mp\_digit $k$ \\ -\hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\ -\textbf{Output}. $a \mbox{ (mod }n\mbox{)}$ \\ -\hline -1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ -2. While $a \ge n$ do \\ -\hspace{3mm}2.1 $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\ -\hspace{3mm}2.2 $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\ -\hspace{3mm}2.3 $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\ -\hspace{3mm}2.4 $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\ -\hspace{3mm}2.5 If $a \ge n$ then do \\ -\hspace{6mm}2.5.1 $a \leftarrow a - n$ \\ -3. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_reduce\_2k} -\end{figure} - -\textbf{Algorithm mp\_reduce\_2k.} -This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$. Division by $2^p$ is emulated with a right -shift which makes the algorithm fairly inexpensive to use. - -EXAM,bn_mp_reduce_2k.c - -The algorithm mp\_count\_bits calculates the number of bits in an mp\_int which is used to find the initial value of $p$. The call to mp\_div\_2d -on line @31,mp_div_2d@ calculates both the quotient $q$ and the remainder $a$ required. By doing both in a single function call the code size -is kept fairly small. The multiplication by $k$ is only performed if $k > 1$. This allows reductions modulo $2^p - 1$ to be performed without -any multiplications. - -The unsigned s\_mp\_add, mp\_cmp\_mag and s\_mp\_sub are used in place of their full sign counterparts since the inputs are only valid if they are -positive. By using the unsigned versions the overhead is kept to a minimum. - -\subsubsection{Unrestricted Setup} -To setup this reduction algorithm the value of $k = 2^p - n$ is required. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\ -\textbf{Input}. mp\_int $n$ \\ -\textbf{Output}. $k = 2^p - n$ \\ -\hline -1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ -2. $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\ -3. $x \leftarrow x - n$ (\textit{mp\_sub}) \\ -4. $k \leftarrow x_0$ \\ -5. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_reduce\_2k\_setup} -\end{figure} - -\textbf{Algorithm mp\_reduce\_2k\_setup.} -This algorithm computes the value of $k$ required for the algorithm mp\_reduce\_2k. By making a temporary variable $x$ equal to $2^p$ a subtraction -is sufficient to solve for $k$. Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$. - -EXAM,bn_mp_reduce_2k_setup.c - -\subsubsection{Unrestricted Detection} -An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true. - -\begin{enumerate} -\item The number has only one digit. -\item The number has more than one digit and every bit from the $\beta$'th to the most significant is one. -\end{enumerate} - -If either condition is true than there is a power of two $2^p$ such that $0 < 2^p - n < \beta$. If the input is only -one digit than it will always be of the correct form. Otherwise all of the bits above the first digit must be one. This arises from the fact -that there will be value of $k$ that when added to the modulus causes a carry in the first digit which propagates all the way to the most -significant bit. The resulting sum will be a power of two. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\ -\textbf{Input}. mp\_int $n$ \\ -\textbf{Output}. $1$ if of proper form, $0$ otherwise \\ -\hline -1. If $n.used = 0$ then return($0$). \\ -2. If $n.used = 1$ then return($1$). \\ -3. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ -4. for $x$ from $lg(\beta)$ to $p$ do \\ -\hspace{3mm}4.1 If the ($x \mbox{ mod }lg(\beta)$)'th bit of the $\lfloor x / lg(\beta) \rfloor$ of $n$ is zero then return($0$). \\ -5. Return($1$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_reduce\_is\_2k} -\end{figure} - -\textbf{Algorithm mp\_reduce\_is\_2k.} -This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly. - -EXAM,bn_mp_reduce_is_2k.c - - - -\section{Algorithm Comparison} -So far three very different algorithms for modular reduction have been discussed. Each of the algorithms have their own strengths and weaknesses -that makes having such a selection very useful. The following table sumarizes the three algorithms along with comparisons of work factors. Since -all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table. - -\begin{center} -\begin{small} -\begin{tabular}{|c|c|c|c|c|c|} -\hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\ -\hline Barrett & $m^2 + 2m - 1$ & None & $79$ & $1087$ & $4223$ \\ -\hline Montgomery & $m^2 + m$ & $n$ must be odd & $72$ & $1056$ & $4160$ \\ -\hline D.R. & $2m$ & $n = \beta^m - k$ & $16$ & $64$ & $128$ \\ -\hline -\end{tabular} -\end{small} -\end{center} - -In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete. However, in practice since Montgomery -reduction can be written as a single function with the Comba technique it is much faster. Barrett reduction suffers from the overhead of -calling the half precision multipliers, addition and division by $\beta$ algorithms. - -For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice. The one set of algorithms where Diminished Radix reduction truly -shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}. In these algorithms -primes of the form $\beta^m - k$ can be found and shared amongst users. These primes will allow the Diminished Radix algorithm to be used in -modular exponentiation to greatly speed up the operation. - - - -\section*{Exercises} -\begin{tabular}{cl} -$\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\ - & calculates the correct value of $\rho$. \\ - & \\ -$\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly. \\ - & \\ -$\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\ - & (\textit{figure~\ref{fig:DR}}) terminates. Also prove the probability that it will \\ - & terminate within $1 \le k \le 10$ iterations. \\ - & \\ -\end{tabular} - - -\chapter{Exponentiation} -Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$. A variant of exponentiation, computed -in a finite field or ring, is called modular exponentiation. This latter style of operation is typically used in public key -cryptosystems such as RSA and Diffie-Hellman. The ability to quickly compute modular exponentiations is of great benefit to any -such cryptosystem and many methods have been sought to speed it up. - -\section{Exponentiation Basics} -A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired. However, as $b$ grows in size -the number of multiplications becomes prohibitive. Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature -with a $1024$-bit key. Such a calculation could never be completed as it would take simply far too long. - -Fortunately there is a very simple algorithm based on the laws of exponents. Recall that $lg_a(a^b) = b$ and that $lg_a(a^ba^c) = b + c$ which -are two trivial relationships between the base and the exponent. Let $b_i$ represent the $i$'th bit of $b$ starting from the least -significant bit. If $b$ is a $k$-bit integer than the following equation is true. - -\begin{equation} -a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i} -\end{equation} - -By taking the base $a$ logarithm of both sides of the equation the following equation is the result. - -\begin{equation} -b = \sum_{i=0}^{k-1}2^i \cdot b_i -\end{equation} - -The term $a^{2^i}$ can be found from the $i - 1$'th term by squaring the term since $\left ( a^{2^i} \right )^2$ is equal to -$a^{2^{i+1}}$. This observation forms the basis of essentially all fast exponentiation algorithms. It requires $k$ squarings and on average -$k \over 2$ multiplications to compute the result. This is indeed quite an improvement over simply multiplying by $a$ a total of $b-1$ times. - -While this current method is a considerable speed up there are further improvements to be made. For example, the $a^{2^i}$ term does not need to -be computed in an auxilary variable. Consider the following equivalent algorithm. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Left to Right Exponentiation}. \\ -\textbf{Input}. Integer $a$, $b$ and $k$ \\ -\textbf{Output}. $c = a^b$ \\ -\hline \\ -1. $c \leftarrow 1$ \\ -2. for $i$ from $k - 1$ to $0$ do \\ -\hspace{3mm}2.1 $c \leftarrow c^2$ \\ -\hspace{3mm}2.2 $c \leftarrow c \cdot a^{b_i}$ \\ -3. Return $c$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Left to Right Exponentiation} -\label{fig:LTOR} -\end{figure} - -This algorithm starts from the most significant bit and works towards the least significant bit. When the $i$'th bit of $b$ is set $a$ is -multiplied against the current product. In each iteration the product is squared which doubles the exponent of the individual terms of the -product. - -For example, let $b = 101100_2 \equiv 44_{10}$. The following chart demonstrates the actions of the algorithm. - -\newpage\begin{figure} -\begin{center} -\begin{tabular}{|c|c|} -\hline \textbf{Value of $i$} & \textbf{Value of $c$} \\ -\hline - & $1$ \\ -\hline $5$ & $a$ \\ -\hline $4$ & $a^2$ \\ -\hline $3$ & $a^4 \cdot a$ \\ -\hline $2$ & $a^8 \cdot a^2 \cdot a$ \\ -\hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\ -\hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\ -\hline -\end{tabular} -\end{center} -\caption{Example of Left to Right Exponentiation} -\end{figure} - -When the product $a^{32} \cdot a^8 \cdot a^4$ is simplified it is equal $a^{44}$ which is the desired exponentiation. This particular algorithm is -called ``Left to Right'' because it reads the exponent in that order. All of the exponentiation algorithms that will be presented are of this nature. - -\subsection{Single Digit Exponentiation} -The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit. It is intended -to be used when a small power of an input is required (\textit{e.g. $a^5$}). It is faster than simply multiplying $b - 1$ times for all values of -$b$ that are greater than three. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_expt\_d}. \\ -\textbf{Input}. mp\_int $a$ and mp\_digit $b$ \\ -\textbf{Output}. $c = a^b$ \\ -\hline \\ -1. $g \leftarrow a$ (\textit{mp\_init\_copy}) \\ -2. $c \leftarrow 1$ (\textit{mp\_set}) \\ -3. for $x$ from 1 to $lg(\beta)$ do \\ -\hspace{3mm}3.1 $c \leftarrow c^2$ (\textit{mp\_sqr}) \\ -\hspace{3mm}3.2 If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\ -\hspace{6mm}3.2.1 $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\ -\hspace{3mm}3.3 $b \leftarrow b << 1$ \\ -4. Clear $g$. \\ -5. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_expt\_d} -\end{figure} - -\textbf{Algorithm mp\_expt\_d.} -This algorithm computes the value of $a$ raised to the power of a single digit $b$. It uses the left to right exponentiation algorithm to -quickly compute the exponentiation. It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the -exponent is a fixed width. - -A copy of $a$ is made first to allow destination variable $c$ be the same as the source variable $a$. The result is set to the initial value of -$1$ in the subsequent step. - -Inside the loop the exponent is read from the most significant bit first down to the least significant bit. First $c$ is invariably squared -on step 3.1. In the following step if the most significant bit of $b$ is one the copy of $a$ is multiplied against $c$. The value -of $b$ is shifted left one bit to make the next bit down from the most signficant bit the new most significant bit. In effect each -iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location. - -EXAM,bn_mp_expt_d.c - -Line @29,mp_set@ sets the initial value of the result to $1$. Next the loop on line @31,for@ steps through each bit of the exponent starting from -the most significant down towards the least significant. The invariant squaring operation placed on line @333,mp_sqr@ is performed first. After -the squaring the result $c$ is multiplied by the base $g$ if and only if the most significant bit of the exponent is set. The shift on line -@47,<<@ moves all of the bits of the exponent upwards towards the most significant location. - -\section{$k$-ary Exponentiation} -When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor -slower than squaring. Recall from the previous algorithm that $b_{i}$ refers to the $i$'th bit of the exponent $b$. Suppose instead it referred to -the $i$'th $k$-bit digit of the exponent of $b$. For $k = 1$ the definitions are synonymous and for $k > 1$ algorithm~\ref{fig:KARY} -computes the same exponentiation. A group of $k$ bits from the exponent is called a \textit{window}. That is it is a small window on only a -portion of the entire exponent. Consider the following modification to the basic left to right exponentiation algorithm. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{$k$-ary Exponentiation}. \\ -\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\ -\textbf{Output}. $c = a^b$ \\ -\hline \\ -1. $c \leftarrow 1$ \\ -2. for $i$ from $t - 1$ to $0$ do \\ -\hspace{3mm}2.1 $c \leftarrow c^{2^k} $ \\ -\hspace{3mm}2.2 Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\ -\hspace{3mm}2.3 $c \leftarrow c \cdot a^g$ \\ -3. Return $c$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{$k$-ary Exponentiation} -\label{fig:KARY} -\end{figure} - -The squaring on step 2.1 can be calculated by squaring the value $c$ successively $k$ times. If the values of $a^g$ for $0 < g < 2^k$ have been -precomputed this algorithm requires only $t$ multiplications and $tk$ squarings. The table can be generated with $2^{k - 1} - 1$ squarings and -$2^{k - 1} + 1$ multiplications. This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$. -However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}. - -Suppose $k = 4$ and $t = 100$. This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation. The -original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value. The total number of squarings -has increased slightly but the number of multiplications has nearly halved. - -\subsection{Optimal Values of $k$} -An optimal value of $k$ will minimize $2^{k} + \lceil n / k \rceil + n - 1$ for a fixed number of bits in the exponent $n$. The simplest -approach is to brute force search amongst the values $k = 2, 3, \ldots, 8$ for the lowest result. Table~\ref{fig:OPTK} lists optimal values of $k$ -for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}. - -\begin{figure}[here] -\begin{center} -\begin{small} -\begin{tabular}{|c|c|c|c|c|c|} -\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\ -\hline $16$ & $2$ & $27$ & $24$ \\ -\hline $32$ & $3$ & $49$ & $48$ \\ -\hline $64$ & $3$ & $92$ & $96$ \\ -\hline $128$ & $4$ & $175$ & $192$ \\ -\hline $256$ & $4$ & $335$ & $384$ \\ -\hline $512$ & $5$ & $645$ & $768$ \\ -\hline $1024$ & $6$ & $1257$ & $1536$ \\ -\hline $2048$ & $6$ & $2452$ & $3072$ \\ -\hline $4096$ & $7$ & $4808$ & $6144$ \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Optimal Values of $k$ for $k$-ary Exponentiation} -\label{fig:OPTK} -\end{figure} - -\subsection{Sliding-Window Exponentiation} -A simple modification to the previous algorithm is only generate the upper half of the table in the range $2^{k-1} \le g < 2^k$. Essentially -this is a table for all values of $g$ where the most significant bit of $g$ is a one. However, in order for this to be allowed in the -algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided. - -Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}. - -\begin{figure}[here] -\begin{center} -\begin{small} -\begin{tabular}{|c|c|c|c|c|c|} -\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\ -\hline $16$ & $3$ & $24$ & $27$ \\ -\hline $32$ & $3$ & $45$ & $49$ \\ -\hline $64$ & $4$ & $87$ & $92$ \\ -\hline $128$ & $4$ & $167$ & $175$ \\ -\hline $256$ & $5$ & $322$ & $335$ \\ -\hline $512$ & $6$ & $628$ & $645$ \\ -\hline $1024$ & $6$ & $1225$ & $1257$ \\ -\hline $2048$ & $7$ & $2403$ & $2452$ \\ -\hline $4096$ & $8$ & $4735$ & $4808$ \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Optimal Values of $k$ for Sliding Window Exponentiation} -\label{fig:OPTK2} -\end{figure} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\ -\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\ -\textbf{Output}. $c = a^b$ \\ -\hline \\ -1. $c \leftarrow 1$ \\ -2. for $i$ from $t - 1$ to $0$ do \\ -\hspace{3mm}2.1 If the $i$'th bit of $b$ is a zero then \\ -\hspace{6mm}2.1.1 $c \leftarrow c^2$ \\ -\hspace{3mm}2.2 else do \\ -\hspace{6mm}2.2.1 $c \leftarrow c^{2^k}$ \\ -\hspace{6mm}2.2.2 Extract the $k$ bits from $(b_{i}b_{i-1}\ldots b_{i-(k-1)})$ and store it in $g$. \\ -\hspace{6mm}2.2.3 $c \leftarrow c \cdot a^g$ \\ -\hspace{6mm}2.2.4 $i \leftarrow i - k$ \\ -3. Return $c$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Sliding Window $k$-ary Exponentiation} -\end{figure} - -Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent. While this -algorithm requires the same number of squarings it can potentially have fewer multiplications. The pre-computed table $a^g$ is also half -the size as the previous table. - -Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms. The first algorithm will divide the exponent up as -the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$. The second algorithm will break the -exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$. The single digit $0$ in the second representation are where -a single squaring took place instead of a squaring and multiplication. In total the first method requires $10$ multiplications and $18$ -squarings. The second method requires $8$ multiplications and $18$ squarings. - -In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster. - -\section{Modular Exponentiation} - -Modular exponentiation is essentially computing the power of a base within a finite field or ring. For example, computing -$d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation. Instead of first computing $a^b$ and then reducing it -modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation. - -This guarantees that any intermediate result is bounded by $0 \le d \le c^2 - 2c + 1$ and can be reduced modulo $c$ quickly using -one of the algorithms presented in ~REDUCTION~. - -Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first. This algorithm -will allow the exponent $b$ to be negative which is computed as $c \equiv \left (1 / a \right )^{\vert b \vert} \mbox{(mod }d\mbox{)}$. The -value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}). If no inverse exists the algorithm -terminates with an error. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_exptmod}. \\ -\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ -\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ -\hline \\ -1. If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\ -2. If $b.sign = MP\_NEG$ then \\ -\hspace{3mm}2.1 $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\ -\hspace{3mm}2.2 $x' \leftarrow \vert x \vert$ \\ -\hspace{3mm}2.3 Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\ -3. if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\ -\hspace{3mm}3.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\ -4. else \\ -\hspace{3mm}4.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_exptmod} -\end{figure} - -\textbf{Algorithm mp\_exptmod.} -The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod. It is a sliding window $k$-ary algorithm -which uses Barrett reduction to reduce the product modulo $p$. The second algorithm mp\_exptmod\_fast performs the same operation -except it uses either Montgomery or Diminished Radix reduction. The two latter reduction algorithms are clumped in the same exponentiation -algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}). - -EXAM,bn_mp_exptmod.c - -In order to keep the algorithms in a known state the first step on line @29,if@ is to reject any negative modulus as input. If the exponent is -negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$. The temporary variable $tmpG$ is assigned -the modular inverse of $G$ and $tmpX$ is assigned the absolute value of $X$. The algorithm will recuse with these new values with a positive -exponent. - -If the exponent is positive the algorithm resumes the exponentiation. Line @63,dr_@ determines if the modulus is of the restricted Diminished Radix -form. If it is not line @65,reduce@ attempts to determine if it is of a unrestricted Diminished Radix form. The integer $dr$ will take on one -of three values. - -\begin{enumerate} -\item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form. -\item $dr = 1$ means that the modulus is of restricted Diminished Radix form. -\item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form. -\end{enumerate} - -Line @69,if@ determines if the fast modular exponentiation algorithm can be used. It is allowed if $dr \ne 0$ or if the modulus is odd. Otherwise, -the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction. - -\subsection{Barrett Modular Exponentiation} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_exptmod}. \\ -\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ -\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ -\hline \\ -1. $k \leftarrow lg(x)$ \\ -2. $winsize \leftarrow \left \lbrace \begin{array}{ll} - 2 & \mbox{if }k \le 7 \\ - 3 & \mbox{if }7 < k \le 36 \\ - 4 & \mbox{if }36 < k \le 140 \\ - 5 & \mbox{if }140 < k \le 450 \\ - 6 & \mbox{if }450 < k \le 1303 \\ - 7 & \mbox{if }1303 < k \le 3529 \\ - 8 & \mbox{if }3529 < k \\ - \end{array} \right .$ \\ -3. Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\ -4. Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\ -5. $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\ -\\ -Setup the table of small powers of $g$. First find $g^{2^{winsize}}$ and then all multiples of it. \\ -6. $k \leftarrow 2^{winsize - 1}$ \\ -7. $M_{k} \leftarrow M_1$ \\ -8. for $ix$ from 0 to $winsize - 2$ do \\ -\hspace{3mm}8.1 $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr}) \\ -\hspace{3mm}8.2 $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\ -9. for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\ -\hspace{3mm}9.1 $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\ -\hspace{3mm}9.2 $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\ -10. $res \leftarrow 1$ \\ -\\ -Start Sliding Window. \\ -11. $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\ -12. Loop \\ -\hspace{3mm}12.1 $bitcnt \leftarrow bitcnt - 1$ \\ -\hspace{3mm}12.2 If $bitcnt = 0$ then do \\ -\hspace{6mm}12.2.1 If $digidx = -1$ goto step 13. \\ -\hspace{6mm}12.2.2 $buf \leftarrow x_{digidx}$ \\ -\hspace{6mm}12.2.3 $digidx \leftarrow digidx - 1$ \\ -\hspace{6mm}12.2.4 $bitcnt \leftarrow lg(\beta)$ \\ -Continued on next page. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm s\_mp\_exptmod} -\end{figure} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\ -\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ -\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ -\hline \\ -\hspace{3mm}12.3 $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\ -\hspace{3mm}12.4 $buf \leftarrow buf << 1$ \\ -\hspace{3mm}12.5 if $mode = 0$ and $y = 0$ then goto step 12. \\ -\hspace{3mm}12.6 if $mode = 1$ and $y = 0$ then do \\ -\hspace{6mm}12.6.1 $res \leftarrow res^2$ \\ -\hspace{6mm}12.6.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ -\hspace{6mm}12.6.3 Goto step 12. \\ -\hspace{3mm}12.7 $bitcpy \leftarrow bitcpy + 1$ \\ -\hspace{3mm}12.8 $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\ -\hspace{3mm}12.9 $mode \leftarrow 2$ \\ -\hspace{3mm}12.10 If $bitcpy = winsize$ then do \\ -\hspace{6mm}Window is full so perform the squarings and single multiplication. \\ -\hspace{6mm}12.10.1 for $ix$ from $0$ to $winsize -1$ do \\ -\hspace{9mm}12.10.1.1 $res \leftarrow res^2$ \\ -\hspace{9mm}12.10.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ -\hspace{6mm}12.10.2 $res \leftarrow res \cdot M_{bitbuf}$ \\ -\hspace{6mm}12.10.3 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ -\hspace{6mm}Reset the window. \\ -\hspace{6mm}12.10.4 $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\ -\\ -No more windows left. Check for residual bits of exponent. \\ -13. If $mode = 2$ and $bitcpy > 0$ then do \\ -\hspace{3mm}13.1 for $ix$ form $0$ to $bitcpy - 1$ do \\ -\hspace{6mm}13.1.1 $res \leftarrow res^2$ \\ -\hspace{6mm}13.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ -\hspace{6mm}13.1.3 $bitbuf \leftarrow bitbuf << 1$ \\ -\hspace{6mm}13.1.4 If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\ -\hspace{9mm}13.1.4.1 $res \leftarrow res \cdot M_{1}$ \\ -\hspace{9mm}13.1.4.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ -14. $y \leftarrow res$ \\ -15. Clear $res$, $mu$ and the $M$ array. \\ -16. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm s\_mp\_exptmod (continued)} -\end{figure} - -\textbf{Algorithm s\_mp\_exptmod.} -This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$. It takes advantage of the Barrett reduction -algorithm to keep the product small throughout the algorithm. - -The first two steps determine the optimal window size based on the number of bits in the exponent. The larger the exponent the -larger the window size becomes. After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated. This -table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$. - -After the table is allocated the first power of $g$ is found. Since $g \ge p$ is allowed it must be first reduced modulo $p$ to make -the rest of the algorithm more efficient. The first element of the table at $2^{winsize - 1}$ is found by squaring $M_1$ successively $winsize - 2$ -times. The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$. - -Now that the table is available the sliding window may begin. The following list describes the functions of all the variables in the window. -\begin{enumerate} -\item The variable $mode$ dictates how the bits of the exponent are interpreted. -\begin{enumerate} - \item When $mode = 0$ the bits are ignored since no non-zero bit of the exponent has been seen yet. For example, if the exponent were simply - $1$ then there would be $lg(\beta) - 1$ zero bits before the first non-zero bit. In this case bits are ignored until a non-zero bit is found. - \item When $mode = 1$ a non-zero bit has been seen before and a new $winsize$-bit window has not been formed yet. In this mode leading $0$ bits - are read and a single squaring is performed. If a non-zero bit is read a new window is created. - \item When $mode = 2$ the algorithm is in the middle of forming a window and new bits are appended to the window from the most significant bit - downwards. -\end{enumerate} -\item The variable $bitcnt$ indicates how many bits are left in the current digit of the exponent left to be read. When it reaches zero a new digit - is fetched from the exponent. -\item The variable $buf$ holds the currently read digit of the exponent. -\item The variable $digidx$ is an index into the exponents digits. It starts at the leading digit $x.used - 1$ and moves towards the trailing digit. -\item The variable $bitcpy$ indicates how many bits are in the currently formed window. When it reaches $winsize$ the window is flushed and - the appropriate operations performed. -\item The variable $bitbuf$ holds the current bits of the window being formed. -\end{enumerate} - -All of step 12 is the window processing loop. It will iterate while there are digits available form the exponent to read. The first step -inside this loop is to extract a new digit if no more bits are available in the current digit. If there are no bits left a new digit is -read and if there are no digits left than the loop terminates. - -After a digit is made available step 12.3 will extract the most significant bit of the current digit and move all other bits in the digit -upwards. In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to -trailing edges the entire exponent is read from most significant bit to least significant bit. - -At step 12.5 if the $mode$ and currently extracted bit $y$ are both zero the bit is ignored and the next bit is read. This prevents the -algorithm from having to perform trivial squaring and reduction operations before the first non-zero bit is read. Step 12.6 and 12.7-10 handle -the two cases of $mode = 1$ and $mode = 2$ respectively. - -FIGU,expt_state,Sliding Window State Diagram - -By step 13 there are no more digits left in the exponent. However, there may be partial bits in the window left. If $mode = 2$ then -a Left-to-Right algorithm is used to process the remaining few bits. - -EXAM,bn_s_mp_exptmod.c - -Lines @31,if@ through @45,}@ determine the optimal window size based on the length of the exponent in bits. The window divisions are sorted -from smallest to greatest so that in each \textbf{if} statement only one condition must be tested. For example, by the \textbf{if} statement -on line @37,if@ the value of $x$ is already known to be greater than $140$. - -The conditional piece of code beginning on line @42,ifdef@ allows the window size to be restricted to five bits. This logic is used to ensure -the table of precomputed powers of $G$ remains relatively small. - -The for loop on line @60,for@ initializes the $M$ array while lines @71,mp_init@ and @75,mp_reduce@ through @85,}@ initialize the reduction -function that will be used for this modulus. - --- More later. - -\section{Quick Power of Two} -Calculating $b = 2^a$ can be performed much quicker than with any of the previous algorithms. Recall that a logical shift left $m << k$ is -equivalent to $m \cdot 2^k$. By this logic when $m = 1$ a quick power of two can be achieved. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_2expt}. \\ -\textbf{Input}. integer $b$ \\ -\textbf{Output}. $a \leftarrow 2^b$ \\ -\hline \\ -1. $a \leftarrow 0$ \\ -2. If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\ -3. $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\ -4. $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\ -5. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_2expt} -\end{figure} - -\textbf{Algorithm mp\_2expt.} - -EXAM,bn_mp_2expt.c - -\chapter{Higher Level Algorithms} - -This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package. These -routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important. - -The first section describes a method of integer division with remainder that is universally well known. It provides the signed division logic -for the package. The subsequent section discusses a set of algorithms which allow a single digit to be the 2nd operand for a variety of operations. -These algorithms serve mostly to simplify other algorithms where small constants are required. The last two sections discuss how to manipulate -various representations of integers. For example, converting from an mp\_int to a string of character. - -\section{Integer Division with Remainder} -\label{sec:division} - -Integer division aside from modular exponentiation is the most intensive algorithm to compute. Like addition, subtraction and multiplication -the basis of this algorithm is the long-hand division algorithm taught to school children. Throughout this discussion several common variables -will be used. Let $x$ represent the divisor and $y$ represent the dividend. Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and -let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$. The following simple algorithm will be used to start the discussion. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\ -\textbf{Input}. integer $x$ and $y$ \\ -\textbf{Output}. $q = \lfloor y/x\rfloor, r = y - xq$ \\ -\hline \\ -1. $q \leftarrow 0$ \\ -2. $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\ -3. for $t$ from $n$ down to $0$ do \\ -\hspace{3mm}3.1 Maximize $k$ such that $kx\beta^t$ is less than or equal to $y$ and $(k + 1)x\beta^t$ is greater. \\ -\hspace{3mm}3.2 $q \leftarrow q + k\beta^t$ \\ -\hspace{3mm}3.3 $y \leftarrow y - kx\beta^t$ \\ -4. $r \leftarrow y$ \\ -5. Return($q, r$) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Radix-$\beta$ Integer Division} -\label{fig:raddiv} -\end{figure} - -As children we are taught this very simple algorithm for the case of $\beta = 10$. Almost instinctively several optimizations are taught for which -their reason of existing are never explained. For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor. - -To find the first digit of the quotient the value of $k$ must be maximized such that $kx\beta^t$ is less than or equal to $y$ and -simultaneously $(k + 1)x\beta^t$ is greater than $y$. Implicitly $k$ is the maximum value the $t$'th digit of the quotient may have. The habitual method -used to find the maximum is to ``eyeball'' the two numbers, typically only the leading digits and quickly estimate a quotient. By only using leading -digits a much simpler division may be used to form an educated guess at what the value must be. In this case $k = \lfloor 54/23\rfloor = 2$ quickly -arises as a possible solution. Indeed $2x\beta^2 = 4600$ is less than $y = 5471$ and simultaneously $(k + 1)x\beta^2 = 6900$ is larger than $y$. -As a result $k\beta^2$ is added to the quotient which now equals $q = 200$ and $4600$ is subtracted from $y$ to give a remainder of $y = 841$. - -Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder -$y = 841 - 3x\beta = 181$. Finally the last iteration of the loop produces $k = 7$ which leads to the quotient $q = 230 + 7 = 237$ and the -remainder $y = 181 - 7x = 20$. The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since -$237 \cdot 23 + 20 = 5471$ is true. - -\subsection{Quotient Estimation} -\label{sec:divest} -As alluded to earlier the quotient digit $k$ can be estimated from only the leading digits of both the divisor and dividend. When $p$ leading -digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows. Technically -speaking the estimation is based on assuming the lower $\vert \vert y \vert \vert - p$ and $\vert \vert x \vert \vert - p$ lower digits of the -dividend and divisor are zero. - -The value of the estimation may off by a few values in either direction and in general is fairly correct. A simplification \cite[pp. 271]{TAOCPV2} -of the estimation technique is to use $t + 1$ digits of the dividend and $t$ digits of the divisor, in particularly when $t = 1$. The estimate -using this technique is never too small. For the following proof let $t = \vert \vert y \vert \vert - 1$ and $s = \vert \vert x \vert \vert - 1$ -represent the most significant digits of the dividend and divisor respectively. - -\textbf{Proof.}\textit{ The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to -$k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. } -The first obvious case is when $\hat k = \beta - 1$ in which case the proof is concluded since the real quotient cannot be larger. For all other -cases $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ and $\hat k x_s \ge y_t\beta + y_{t-1} - x_s + 1$. The latter portion of the inequalility -$-x_s + 1$ arises from the fact that a truncated integer division will give the same quotient for at most $x_s - 1$ values. Next a series of -inequalities will prove the hypothesis. - -\begin{equation} -y - \hat k x \le y - \hat k x_s\beta^s -\end{equation} - -This is trivially true since $x \ge x_s\beta^s$. Next we replace $\hat kx_s\beta^s$ by the previous inequality for $\hat kx_s$. - -\begin{equation} -y - \hat k x \le y_t\beta^t + \ldots + y_0 - (y_t\beta^t + y_{t-1}\beta^{t-1} - x_s\beta^t + \beta^s) -\end{equation} - -By simplifying the previous inequality the following inequality is formed. - -\begin{equation} -y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s -\end{equation} - -Subsequently, - -\begin{equation} -y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s < x_s\beta^s \le x -\end{equation} - -Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof. \textbf{QED} - - -\subsection{Normalized Integers} -For the purposes of division a normalized input is when the divisors leading digit $x_n$ is greater than or equal to $\beta / 2$. By multiplying both -$x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original -remainder. The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will -lie in the domain of a single digit. Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$. - -\begin{equation} -{{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta} -\end{equation} - -At most the quotient approaches $2\beta$, however, in practice this will not occur since that would imply the previous quotient digit was too small. - -\subsection{Radix-$\beta$ Division with Remainder} -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_div}. \\ -\textbf{Input}. mp\_int $a, b$ \\ -\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\ -\hline \\ -1. If $b = 0$ return(\textit{MP\_VAL}). \\ -2. If $\vert a \vert < \vert b \vert$ then do \\ -\hspace{3mm}2.1 $d \leftarrow a$ \\ -\hspace{3mm}2.2 $c \leftarrow 0$ \\ -\hspace{3mm}2.3 Return(\textit{MP\_OKAY}). \\ -\\ -Setup the quotient to receive the digits. \\ -3. Grow $q$ to $a.used + 2$ digits. \\ -4. $q \leftarrow 0$ \\ -5. $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\ -6. $sign \leftarrow \left \lbrace \begin{array}{ll} - MP\_ZPOS & \mbox{if }a.sign = b.sign \\ - MP\_NEG & \mbox{otherwise} \\ - \end{array} \right .$ \\ -\\ -Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\ -7. $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\ -8. $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\ -\\ -Find the leading digit of the quotient. \\ -9. $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\ -10. $y \leftarrow y \cdot \beta^{n - t}$ \\ -11. While ($x \ge y$) do \\ -\hspace{3mm}11.1 $q_{n - t} \leftarrow q_{n - t} + 1$ \\ -\hspace{3mm}11.2 $x \leftarrow x - y$ \\ -12. $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\ -\\ -Continued on the next page. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_div} -\end{figure} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_div} (continued). \\ -\textbf{Input}. mp\_int $a, b$ \\ -\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\ -\hline \\ -Now find the remainder fo the digits. \\ -13. for $i$ from $n$ down to $(t + 1)$ do \\ -\hspace{3mm}13.1 If $i > x.used$ then jump to the next iteration of this loop. \\ -\hspace{3mm}13.2 If $x_{i} = y_{t}$ then \\ -\hspace{6mm}13.2.1 $q_{i - t - 1} \leftarrow \beta - 1$ \\ -\hspace{3mm}13.3 else \\ -\hspace{6mm}13.3.1 $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\ -\hspace{6mm}13.3.2 $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\ -\hspace{6mm}13.3.3 $q_{i - t - 1} \leftarrow \hat r$ \\ -\hspace{3mm}13.4 $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\ -\\ -Fixup quotient estimation. \\ -\hspace{3mm}13.5 Loop \\ -\hspace{6mm}13.5.1 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\ -\hspace{6mm}13.5.2 t$1 \leftarrow 0$ \\ -\hspace{6mm}13.5.3 t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\ -\hspace{6mm}13.5.4 $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\ -\hspace{6mm}13.5.5 t$2_0 \leftarrow x_{i - 2}, $ t$2_1 \leftarrow x_{i - 1}, $ t$2_2 \leftarrow x_i, $ t$2.used \leftarrow 3$ \\ -\hspace{6mm}13.5.6 If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\ -\hspace{3mm}13.6 t$1 \leftarrow y \cdot q_{i - t - 1}$ \\ -\hspace{3mm}13.7 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\ -\hspace{3mm}13.8 $x \leftarrow x - $ t$1$ \\ -\hspace{3mm}13.9 If $x.sign = MP\_NEG$ then \\ -\hspace{6mm}13.10 t$1 \leftarrow y$ \\ -\hspace{6mm}13.11 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\ -\hspace{6mm}13.12 $x \leftarrow x + $ t$1$ \\ -\hspace{6mm}13.13 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\ -\\ -Finalize the result. \\ -14. Clamp excess digits of $q$ \\ -15. $c \leftarrow q, c.sign \leftarrow sign$ \\ -16. $x.sign \leftarrow a.sign$ \\ -17. $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\ -18. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_div (continued)} -\end{figure} -\textbf{Algorithm mp\_div.} -This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor. The algorithm is a signed -division and will produce a fully qualified quotient and remainder. - -First the divisor $b$ must be non-zero which is enforced in step one. If the divisor is larger than the dividend than the quotient is implicitly -zero and the remainder is the dividend. - -After the first two trivial cases of inputs are handled the variable $q$ is setup to receive the digits of the quotient. Two unsigned copies of the -divisor $y$ and dividend $x$ are made as well. The core of the division algorithm is an unsigned division and will only work if the values are -positive. Now the two values $x$ and $y$ must be normalized such that the leading digit of $y$ is greater than or equal to $\beta / 2$. -This is performed by shifting both to the left by enough bits to get the desired normalization. - -At this point the division algorithm can begin producing digits of the quotient. Recall that maximum value of the estimation used is -$2\beta - {2 \over \beta}$ which means that a digit of the quotient must be first produced by another means. In this case $y$ is shifted -to the left (\textit{step ten}) so that it has the same number of digits as $x$. The loop on step eleven will subtract multiples of the -shifted copy of $y$ until $x$ is smaller. Since the leading digit of $y$ is greater than or equal to $\beta/2$ this loop will iterate at most two -times to produce the desired leading digit of the quotient. - -Now the remainder of the digits can be produced. The equation $\hat q = \lfloor {{x_i \beta + x_{i-1}}\over y_t} \rfloor$ is used to fairly -accurately approximate the true quotient digit. The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by -induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$. - -Recall from section~\ref{sec:divest} that the estimation is never too low but may be too high. The next step of the estimation process is -to refine the estimation. The loop on step 13.5 uses $x_i\beta^2 + x_{i-1}\beta + x_{i-2}$ and $q_{i - t - 1}(y_t\beta + y_{t-1})$ as a higher -order approximation to adjust the quotient digit. - -After both phases of estimation the quotient digit may still be off by a value of one\footnote{This is similar to the error introduced -by optimizing Barrett reduction.}. Steps 13.6 and 13.7 subtract the multiple of the divisor from the dividend (\textit{Similar to step 3.3 of -algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large. - -Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the -remainder. An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC} -is that when the estimations are being made (\textit{inside the loop on step 13.5}) that the digits $y_{t-1}$, $x_{i-2}$ and $x_{i-1}$ may lie -outside their respective boundaries. For example, if $t = 0$ or $i \le 1$ then the digits would be undefined. In those cases the digits should -respectively be replaced with a zero. - -EXAM,bn_mp_div.c - -The implementation of this algorithm differs slightly from the pseudo code presented previously. In this algorithm either of the quotient $c$ or -remainder $d$ may be passed as a \textbf{NULL} pointer which indicates their value is not desired. For example, the C code to call the division -algorithm with only the quotient is - -\begin{verbatim} -mp_div(&a, &b, &c, NULL); /* c = [a/b] */ -\end{verbatim} - -Lines @108,if@ and @113,if@ handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor -respectively. After the two trivial cases all of the temporary variables are initialized. Line @147,neg@ determines the sign of -the quotient and line @148,sign@ ensures that both $x$ and $y$ are positive. - -The number of bits in the leading digit is calculated on line @151,norm@. Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits -of precision which when reduced modulo $lg(\beta)$ produces the value of $k$. In this case $k$ is the number of bits in the leading digit which is -exactly what is required. For the algorithm to operate $k$ must equal $lg(\beta) - 1$ and when it does not the inputs must be normalized by shifting -them to the left by $lg(\beta) - 1 - k$ bits. - -Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively. These are first used to produce the -leading digit of the quotient. The loop beginning on line @184,for@ will produce the remainder of the quotient digits. - -The conditional ``continue'' on line @186,continue@ is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the -algorithm eliminates multiple non-zero digits in a single iteration. This ensures that $x_i$ is always non-zero since by definition the digits -above the $i$'th position $x$ must be zero in order for the quotient to be precise\footnote{Precise as far as integer division is concerned.}. - -Lines @214,t1@, @216,t1@ and @222,t2@ through @225,t2@ manually construct the high accuracy estimations by setting the digits of the two mp\_int -variables directly. - -\section{Single Digit Helpers} - -This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants. All of -the helper functions assume the single digit input is positive and will treat them as such. - -\subsection{Single Digit Addition and Subtraction} - -Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction -algorithms. As a result these algorithms are subtantially simpler with a slight cost in performance. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_add\_d}. \\ -\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ -\textbf{Output}. $c = a + b$ \\ -\hline \\ -1. $t \leftarrow b$ (\textit{mp\_set}) \\ -2. $c \leftarrow a + t$ \\ -3. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_add\_d} -\end{figure} - -\textbf{Algorithm mp\_add\_d.} -This algorithm initiates a temporary mp\_int with the value of the single digit and uses algorithm mp\_add to add the two values together. - -EXAM,bn_mp_add_d.c - -Clever use of the letter 't'. - -\subsubsection{Subtraction} -The single digit subtraction algorithm mp\_sub\_d is essentially the same except it uses mp\_sub to subtract the digit from the mp\_int. - -\subsection{Single Digit Multiplication} -Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline -multiplication algorithm. Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands -only has one digit. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_mul\_d}. \\ -\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ -\textbf{Output}. $c = ab$ \\ -\hline \\ -1. $pa \leftarrow a.used$ \\ -2. Grow $c$ to at least $pa + 1$ digits. \\ -3. $oldused \leftarrow c.used$ \\ -4. $c.used \leftarrow pa + 1$ \\ -5. $c.sign \leftarrow a.sign$ \\ -6. $\mu \leftarrow 0$ \\ -7. for $ix$ from $0$ to $pa - 1$ do \\ -\hspace{3mm}7.1 $\hat r \leftarrow \mu + a_{ix}b$ \\ -\hspace{3mm}7.2 $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}7.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -8. $c_{pa} \leftarrow \mu$ \\ -9. for $ix$ from $pa + 1$ to $oldused$ do \\ -\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\ -10. Clamp excess digits of $c$. \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_mul\_d} -\end{figure} -\textbf{Algorithm mp\_mul\_d.} -This algorithm quickly multiplies an mp\_int by a small single digit value. It is specially tailored to the job and has a minimal of overhead. -Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations. - -EXAM,bn_mp_mul_d.c - -In this implementation the destination $c$ may point to the same mp\_int as the source $a$ since the result is written after the digit is -read from the source. This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively. - -\subsection{Single Digit Division} -Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion. Since the -divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_div\_d}. \\ -\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ -\textbf{Output}. $c = \lfloor a / b \rfloor, d = a - cb$ \\ -\hline \\ -1. If $b = 0$ then return(\textit{MP\_VAL}).\\ -2. If $b = 3$ then use algorithm mp\_div\_3 instead. \\ -3. Init $q$ to $a.used$ digits. \\ -4. $q.used \leftarrow a.used$ \\ -5. $q.sign \leftarrow a.sign$ \\ -6. $\hat w \leftarrow 0$ \\ -7. for $ix$ from $a.used - 1$ down to $0$ do \\ -\hspace{3mm}7.1 $\hat w \leftarrow \hat w \beta + a_{ix}$ \\ -\hspace{3mm}7.2 If $\hat w \ge b$ then \\ -\hspace{6mm}7.2.1 $t \leftarrow \lfloor \hat w / b \rfloor$ \\ -\hspace{6mm}7.2.2 $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\ -\hspace{3mm}7.3 else\\ -\hspace{6mm}7.3.1 $t \leftarrow 0$ \\ -\hspace{3mm}7.4 $q_{ix} \leftarrow t$ \\ -8. $d \leftarrow \hat w$ \\ -9. Clamp excess digits of $q$. \\ -10. $c \leftarrow q$ \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_div\_d} -\end{figure} -\textbf{Algorithm mp\_div\_d.} -This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach. Essentially in every iteration of the -algorithm another digit of the dividend is reduced and another digit of quotient produced. Provided $b < \beta$ the value of $\hat w$ -after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$. - -If the divisor $b$ is equal to three a variant of this algorithm is used which is called mp\_div\_3. It replaces the division by three with -a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup. In essence it is much like the Barrett reduction -from chapter seven. - -EXAM,bn_mp_div_d.c - -Like the implementation of algorithm mp\_div this algorithm allows either of the quotient or remainder to be passed as a \textbf{NULL} pointer to -indicate the respective value is not required. This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created. - -The division and remainder on lines @44,/@ and @45,%@ can be replaced often by a single division on most processors. For example, the 32-bit x86 based -processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously. Unfortunately the GCC -compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively. - -\subsection{Single Digit Root Extraction} - -Finding the $n$'th root of an integer is fairly easy as far as numerical analysis is concerned. Algorithms such as the Newton-Raphson approximation -(\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$. - -\begin{equation} -x_{i+1} = x_i - {f(x_i) \over f'(x_i)} -\label{eqn:newton} -\end{equation} - -In this case the $n$'th root is desired and $f(x) = x^n - a$ where $a$ is the integer of which the root is desired. The derivative of $f(x)$ is -simply $f'(x) = nx^{n - 1}$. Of particular importance is that this algorithm will be used over the integers not over the a more continuous domain -such as the real numbers. As a result the root found can be above the true root by few and must be manually adjusted. Ideally at the end of the -algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_n\_root}. \\ -\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ -\textbf{Output}. $c^b \le a$ \\ -\hline \\ -1. If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\ -2. $sign \leftarrow a.sign$ \\ -3. $a.sign \leftarrow MP\_ZPOS$ \\ -4. t$2 \leftarrow 2$ \\ -5. Loop \\ -\hspace{3mm}5.1 t$1 \leftarrow $ t$2$ \\ -\hspace{3mm}5.2 t$3 \leftarrow $ t$1^{b - 1}$ \\ -\hspace{3mm}5.3 t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\ -\hspace{3mm}5.4 t$2 \leftarrow $ t$2 - a$ \\ -\hspace{3mm}5.5 t$3 \leftarrow $ t$3 \cdot b$ \\ -\hspace{3mm}5.6 t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\ -\hspace{3mm}5.7 t$2 \leftarrow $ t$1 - $ t$3$ \\ -\hspace{3mm}5.8 If t$1 \ne $ t$2$ then goto step 5. \\ -6. Loop \\ -\hspace{3mm}6.1 t$2 \leftarrow $ t$1^b$ \\ -\hspace{3mm}6.2 If t$2 > a$ then \\ -\hspace{6mm}6.2.1 t$1 \leftarrow $ t$1 - 1$ \\ -\hspace{6mm}6.2.2 Goto step 6. \\ -7. $a.sign \leftarrow sign$ \\ -8. $c \leftarrow $ t$1$ \\ -9. $c.sign \leftarrow sign$ \\ -10. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_n\_root} -\end{figure} -\textbf{Algorithm mp\_n\_root.} -This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach. It is partially optimized based on the observation -that the numerator of ${f(x) \over f'(x)}$ can be derived from a partial denominator. That is at first the denominator is calculated by finding -$x^{b - 1}$. This value can then be multiplied by $x$ and have $a$ subtracted from it to find the numerator. This saves a total of $b - 1$ -multiplications by t$1$ inside the loop. - -The initial value of the approximation is t$2 = 2$ which allows the algorithm to start with very small values and quickly converge on the -root. Ideally this algorithm is meant to find the $n$'th root of an input where $n$ is bounded by $2 \le n \le 5$. - -EXAM,bn_mp_n_root.c - -\section{Random Number Generation} - -Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms. Pollard-Rho -factoring for example, can make use of random values as starting points to find factors of a composite integer. In this case the algorithm presented -is solely for simulations and not intended for cryptographic use. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_rand}. \\ -\textbf{Input}. An integer $b$ \\ -\textbf{Output}. A pseudo-random number of $b$ digits \\ -\hline \\ -1. $a \leftarrow 0$ \\ -2. If $b \le 0$ return(\textit{MP\_OKAY}) \\ -3. Pick a non-zero random digit $d$. \\ -4. $a \leftarrow a + d$ \\ -5. for $ix$ from 1 to $d - 1$ do \\ -\hspace{3mm}5.1 $a \leftarrow a \cdot \beta$ \\ -\hspace{3mm}5.2 Pick a random digit $d$. \\ -\hspace{3mm}5.3 $a \leftarrow a + d$ \\ -6. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_rand} -\end{figure} -\textbf{Algorithm mp\_rand.} -This algorithm produces a pseudo-random integer of $b$ digits. By ensuring that the first digit is non-zero the algorithm also guarantees that the -final result has at least $b$ digits. It relies heavily on a third-part random number generator which should ideally generate uniformly all of -the integers from $0$ to $\beta - 1$. - -EXAM,bn_mp_rand.c - -\section{Formatted Representations} -The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties. For example, the ability to -be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers -into a program. - -\subsection{Reading Radix-n Input} -For the purposes of this text we will assume that a simple lower ASCII map (\ref{fig:ASC}) is used for the values of from $0$ to $63$ to -printable characters. For example, when the character ``N'' is read it represents the integer $23$. The first $16$ characters of the -map are for the common representations up to hexadecimal. After that they match the ``base64'' encoding scheme which are suitable chosen -such that they are printable. While outputting as base64 may not be too helpful for human operators it does allow communication via non binary -mediums. - -\newpage\begin{figure}[here] -\begin{center} -\begin{tabular}{cc|cc|cc|cc} -\hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} \\ -\hline -0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\ -4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\ -8 & 8 & 9 & 9 & 10 & A & 11 & B \\ -12 & C & 13 & D & 14 & E & 15 & F \\ -16 & G & 17 & H & 18 & I & 19 & J \\ -20 & K & 21 & L & 22 & M & 23 & N \\ -24 & O & 25 & P & 26 & Q & 27 & R \\ -28 & S & 29 & T & 30 & U & 31 & V \\ -32 & W & 33 & X & 34 & Y & 35 & Z \\ -36 & a & 37 & b & 38 & c & 39 & d \\ -40 & e & 41 & f & 42 & g & 43 & h \\ -44 & i & 45 & j & 46 & k & 47 & l \\ -48 & m & 49 & n & 50 & o & 51 & p \\ -52 & q & 53 & r & 54 & s & 55 & t \\ -56 & u & 57 & v & 58 & w & 59 & x \\ -60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\ -\hline -\end{tabular} -\end{center} -\caption{Lower ASCII Map} -\label{fig:ASC} -\end{figure} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_read\_radix}. \\ -\textbf{Input}. A string $str$ of length $sn$ and radix $r$. \\ -\textbf{Output}. The radix-$\beta$ equivalent mp\_int. \\ -\hline \\ -1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\ -2. $ix \leftarrow 0$ \\ -3. If $str_0 =$ ``-'' then do \\ -\hspace{3mm}3.1 $ix \leftarrow ix + 1$ \\ -\hspace{3mm}3.2 $sign \leftarrow MP\_NEG$ \\ -4. else \\ -\hspace{3mm}4.1 $sign \leftarrow MP\_ZPOS$ \\ -5. $a \leftarrow 0$ \\ -6. for $iy$ from $ix$ to $sn - 1$ do \\ -\hspace{3mm}6.1 Let $y$ denote the position in the map of $str_{iy}$. \\ -\hspace{3mm}6.2 If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\ -\hspace{3mm}6.3 $a \leftarrow a \cdot r$ \\ -\hspace{3mm}6.4 $a \leftarrow a + y$ \\ -7. If $a \ne 0$ then $a.sign \leftarrow sign$ \\ -8. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_read\_radix} -\end{figure} -\textbf{Algorithm mp\_read\_radix.} -This algorithm will read an ASCII string and produce the radix-$\beta$ mp\_int representation of the same integer. A minus symbol ``-'' may precede the -string to indicate the value is negative, otherwise it is assumed to be positive. The algorithm will read up to $sn$ characters from the input -and will stop when it reads a character it cannot map the algorithm stops reading characters from the string. This allows numbers to be embedded -as part of larger input without any significant problem. - -EXAM,bn_mp_read_radix.c - -\subsection{Generating Radix-$n$ Output} -Generating radix-$n$ output is fairly trivial with a division and remainder algorithm. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_toradix}. \\ -\textbf{Input}. A mp\_int $a$ and an integer $r$\\ -\textbf{Output}. The radix-$r$ representation of $a$ \\ -\hline \\ -1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\ -2. If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}). \\ -3. $t \leftarrow a$ \\ -4. $str \leftarrow$ ``'' \\ -5. if $t.sign = MP\_NEG$ then \\ -\hspace{3mm}5.1 $str \leftarrow str + $ ``-'' \\ -\hspace{3mm}5.2 $t.sign = MP\_ZPOS$ \\ -6. While ($t \ne 0$) do \\ -\hspace{3mm}6.1 $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\ -\hspace{3mm}6.2 $t \leftarrow \lfloor t / r \rfloor$ \\ -\hspace{3mm}6.3 Look up $d$ in the map and store the equivalent character in $y$. \\ -\hspace{3mm}6.4 $str \leftarrow str + y$ \\ -7. If $str_0 = $``$-$'' then \\ -\hspace{3mm}7.1 Reverse the digits $str_1, str_2, \ldots str_n$. \\ -8. Otherwise \\ -\hspace{3mm}8.1 Reverse the digits $str_0, str_1, \ldots str_n$. \\ -9. Return(\textit{MP\_OKAY}).\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_toradix} -\end{figure} -\textbf{Algorithm mp\_toradix.} -This algorithm computes the radix-$r$ representation of an mp\_int $a$. The ``digits'' of the representation are extracted by reducing -successive powers of $\lfloor a / r^k \rfloor$ the input modulo $r$ until $r^k > a$. Note that instead of actually dividing by $r^k$ in -each iteration the quotient $\lfloor a / r \rfloor$ is saved for the next iteration. As a result a series of trivial $n \times 1$ divisions -are required instead of a series of $n \times k$ divisions. One design flaw of this approach is that the digits are produced in the reverse order -(see~\ref{fig:mpradix}). To remedy this flaw the digits must be swapped or simply ``reversed''. - -\begin{figure} -\begin{center} -\begin{tabular}{|c|c|c|} -\hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\ -\hline $1234$ & -- & -- \\ -\hline $123$ & $4$ & ``4'' \\ -\hline $12$ & $3$ & ``43'' \\ -\hline $1$ & $2$ & ``432'' \\ -\hline $0$ & $1$ & ``4321'' \\ -\hline -\end{tabular} -\end{center} -\caption{Example of Algorithm mp\_toradix.} -\label{fig:mpradix} -\end{figure} - -EXAM,bn_mp_toradix.c - -\chapter{Number Theoretic Algorithms} -This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi -symbol computation. These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and -various Sieve based factoring algorithms. - -\section{Greatest Common Divisor} -The greatest common divisor of two integers $a$ and $b$, often denoted as $(a, b)$ is the largest integer $k$ that is a proper divisor of -both $a$ and $b$. That is, $k$ is the largest integer such that $0 \equiv a \mbox{ (mod }k\mbox{)}$ and $0 \equiv b \mbox{ (mod }k\mbox{)}$ occur -simultaneously. - -The most common approach (cite) is to reduce one input modulo another. That is if $a$ and $b$ are divisible by some integer $k$ and if $qa + r = b$ then -$r$ is also divisible by $k$. The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Greatest Common Divisor (I)}. \\ -\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ -\textbf{Output}. The greatest common divisor $(a, b)$. \\ -\hline \\ -1. While ($b > 0$) do \\ -\hspace{3mm}1.1 $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\ -\hspace{3mm}1.2 $a \leftarrow b$ \\ -\hspace{3mm}1.3 $b \leftarrow r$ \\ -2. Return($a$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Greatest Common Divisor (I)} -\label{fig:gcd1} -\end{figure} - -This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly. However, divisions are -relatively expensive operations to perform and should ideally be avoided. There is another approach based on a similar relationship of -greatest common divisors. The faster approach is based on the observation that if $k$ divides both $a$ and $b$ it will also divide $a - b$. -In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Greatest Common Divisor (II)}. \\ -\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ -\textbf{Output}. The greatest common divisor $(a, b)$. \\ -\hline \\ -1. While ($b > 0$) do \\ -\hspace{3mm}1.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\ -\hspace{3mm}1.2 $b \leftarrow b - a$ \\ -2. Return($a$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Greatest Common Divisor (II)} -\label{fig:gcd2} -\end{figure} - -\textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.} -The algorithm in figure~\ref{fig:gcd2} will eventually terminate since $b \ge a$ the subtraction in step 1.2 will be a value less than $b$. In other -words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$. Since both $a$ and $b$ are always -divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the -second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof. \textbf{QED}. - -As a matter of practicality algorithm \ref{fig:gcd1} decreases far too slowly to be useful. Specially if $b$ is much larger than $a$ such that -$b - a$ is still very much larger than $a$. A simple addition to the algorithm is to divide $b - a$ by a power of some integer $p$ which does -not divide the greatest common divisor but will divide $b - a$. In this case ${b - a} \over p$ is also an integer and still divisible by -the greatest common divisor. - -However, instead of factoring $b - a$ to find a suitable value of $p$ the powers of $p$ can be removed from $a$ and $b$ that are in common first. -Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Greatest Common Divisor (III)}. \\ -\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ -\textbf{Output}. The greatest common divisor $(a, b)$. \\ -\hline \\ -1. $k \leftarrow 0$ \\ -2. While $a$ and $b$ are both divisible by $p$ do \\ -\hspace{3mm}2.1 $a \leftarrow \lfloor a / p \rfloor$ \\ -\hspace{3mm}2.2 $b \leftarrow \lfloor b / p \rfloor$ \\ -\hspace{3mm}2.3 $k \leftarrow k + 1$ \\ -3. While $a$ is divisible by $p$ do \\ -\hspace{3mm}3.1 $a \leftarrow \lfloor a / p \rfloor$ \\ -4. While $b$ is divisible by $p$ do \\ -\hspace{3mm}4.1 $b \leftarrow \lfloor b / p \rfloor$ \\ -5. While ($b > 0$) do \\ -\hspace{3mm}5.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\ -\hspace{3mm}5.2 $b \leftarrow b - a$ \\ -\hspace{3mm}5.3 While $b$ is divisible by $p$ do \\ -\hspace{6mm}5.3.1 $b \leftarrow \lfloor b / p \rfloor$ \\ -6. Return($a \cdot p^k$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Greatest Common Divisor (III)} -\label{fig:gcd3} -\end{figure} - -This algorithm is based on the first except it removes powers of $p$ first and inside the main loop to ensure the tuple $\left < a, b \right >$ -decreases more rapidly. The first loop on step two removes powers of $p$ that are in common. A count, $k$, is kept which will present a common -divisor of $p^k$. After step two the remaining common divisor of $a$ and $b$ cannot be divisible by $p$. This means that $p$ can be safely -divided out of the difference $b - a$ so long as the division leaves no remainder. - -In particular the value of $p$ should be chosen such that the division on step 5.3.1 occur often. It also helps that division by $p$ be easy -to compute. The ideal choice of $p$ is two since division by two amounts to a right logical shift. Another important observation is that by -step five both $a$ and $b$ are odd. Therefore, the diffrence $b - a$ must be even which means that each iteration removes one bit from the -largest of the pair. - -\subsection{Complete Greatest Common Divisor} -The algorithms presented so far cannot handle inputs which are zero or negative. The following algorithm can handle all input cases properly -and will produce the greatest common divisor. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_gcd}. \\ -\textbf{Input}. mp\_int $a$ and $b$ \\ -\textbf{Output}. The greatest common divisor $c = (a, b)$. \\ -\hline \\ -1. If $a = 0$ then \\ -\hspace{3mm}1.1 $c \leftarrow \vert b \vert $ \\ -\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ -2. If $b = 0$ then \\ -\hspace{3mm}2.1 $c \leftarrow \vert a \vert $ \\ -\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\ -3. $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\ -4. $k \leftarrow 0$ \\ -5. While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}5.1 $k \leftarrow k + 1$ \\ -\hspace{3mm}5.2 $u \leftarrow \lfloor u / 2 \rfloor$ \\ -\hspace{3mm}5.3 $v \leftarrow \lfloor v / 2 \rfloor$ \\ -6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\ -7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ -8. While $v.used > 0$ \\ -\hspace{3mm}8.1 If $\vert u \vert > \vert v \vert$ then \\ -\hspace{6mm}8.1.1 Swap $u$ and $v$. \\ -\hspace{3mm}8.2 $v \leftarrow \vert v \vert - \vert u \vert$ \\ -\hspace{3mm}8.3 While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{6mm}8.3.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ -9. $c \leftarrow u \cdot 2^k$ \\ -10. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_gcd} -\end{figure} -\textbf{Algorithm mp\_gcd.} -This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$. The algorithm was originally based on Algorithm B of -Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain. In theory it achieves the same asymptotic working time as -Algorithm B and in practice this appears to be true. - -The first two steps handle the cases where either one of or both inputs are zero. If either input is zero the greatest common divisor is the -largest input or zero if they are both zero. If the inputs are not trivial than $u$ and $v$ are assigned the absolute values of -$a$ and $b$ respectively and the algorithm will proceed to reduce the pair. - -Step five will divide out any common factors of two and keep track of the count in the variable $k$. After this step, two is no longer a -factor of the remaining greatest common divisor between $u$ and $v$ and can be safely evenly divided out of either whenever they are even. Step -six and seven ensure that the $u$ and $v$ respectively have no more factors of two. At most only one of the while--loops will iterate since -they cannot both be even. - -By step eight both of $u$ and $v$ are odd which is required for the inner logic. First the pair are swapped such that $v$ is equal to -or greater than $u$. This ensures that the subtraction on step 8.2 will always produce a positive and even result. Step 8.3 removes any -factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd. - -After $v = 0$ occurs the variable $u$ has the greatest common divisor of the pair $\left < u, v \right >$ just after step six. The result -must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier. - -EXAM,bn_mp_gcd.c - -This function makes use of the macros mp\_iszero and mp\_iseven. The former evaluates to $1$ if the input mp\_int is equivalent to the -integer zero otherwise it evaluates to $0$. The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise -it evaluates to $0$. Note that just because mp\_iseven may evaluate to $0$ does not mean the input is odd, it could also be zero. The three -trivial cases of inputs are handled on lines @23,zero@ through @29,}@. After those lines the inputs are assumed to be non-zero. - -Lines @32,if@ and @36,if@ make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively. At this point the common factors of two -must be divided out of the two inputs. The block starting at line @43,common@ removes common factors of two by first counting the number of trailing -zero bits in both. The local integer $k$ is used to keep track of how many factors of $2$ are pulled out of both values. It is assumed that -the number of factors will not exceed the maximum value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than -entries than are accessible by an ``int'' so this is not a limitation.}. - -At this point there are no more common factors of two in the two values. The divisions by a power of two on lines @60,div_2d@ and @67,div_2d@ remove -any independent factors of two such that both $u$ and $v$ are guaranteed to be an odd integer before hitting the main body of the algorithm. The while loop -on line @72, while@ performs the reduction of the pair until $v$ is equal to zero. The unsigned comparison and subtraction algorithms are used in -place of the full signed routines since both values are guaranteed to be positive and the result of the subtraction is guaranteed to be non-negative. - -\section{Least Common Multiple} -The least common multiple of a pair of integers is their product divided by their greatest common divisor. For two integers $a$ and $b$ the -least common multiple is normally denoted as $[ a, b ]$ and numerically equivalent to ${ab} \over {(a, b)}$. For example, if $a = 2 \cdot 2 \cdot 3 = 12$ -and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$. - -The least common multiple arises often in coding theory as well as number theory. If two functions have periods of $a$ and $b$ respectively they will -collide, that is be in synchronous states, after only $[ a, b ]$ iterations. This is why, for example, random number generators based on -Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}). -Similarly in number theory if a composite $n$ has two prime factors $p$ and $q$ then maximal order of any unit of $\Z/n\Z$ will be $[ p - 1, q - 1] $. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_lcm}. \\ -\textbf{Input}. mp\_int $a$ and $b$ \\ -\textbf{Output}. The least common multiple $c = [a, b]$. \\ -\hline \\ -1. $c \leftarrow (a, b)$ \\ -2. $t \leftarrow a \cdot b$ \\ -3. $c \leftarrow \lfloor t / c \rfloor$ \\ -4. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_lcm} -\end{figure} -\textbf{Algorithm mp\_lcm.} -This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$. It computes the least common multiple directly by -dividing the product of the two inputs by their greatest common divisor. - -EXAM,bn_mp_lcm.c - -\section{Jacobi Symbol Computation} -To explain the Jacobi Symbol we shall first discuss the Legendre function\footnote{Arrg. What is the name of this?} off which the Jacobi symbol is -defined. The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$. Numerically it is -equivalent to equation \ref{eqn:legendre}. - -\textit{-- Tom, don't be an ass, cite your source here...!} - -\begin{equation} -a^{(p-1)/2} \equiv \begin{array}{rl} - -1 & \mbox{if }a\mbox{ is a quadratic non-residue.} \\ - 0 & \mbox{if }a\mbox{ divides }p\mbox{.} \\ - 1 & \mbox{if }a\mbox{ is a quadratic residue}. - \end{array} \mbox{ (mod }p\mbox{)} -\label{eqn:legendre} -\end{equation} - -\textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.} -An integer $a$ is a quadratic residue if the following equation has a solution. - -\begin{equation} -x^2 \equiv a \mbox{ (mod }p\mbox{)} -\label{eqn:root} -\end{equation} - -Consider the following equation. - -\begin{equation} -0 \equiv x^{p-1} - 1 \equiv \left \lbrace \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \right \rbrace + \left ( a^{(p-1)/2} - 1 \right ) \mbox{ (mod }p\mbox{)} -\label{eqn:rooti} -\end{equation} - -Whether equation \ref{eqn:root} has a solution or not equation \ref{eqn:rooti} is always true. If $a^{(p-1)/2} - 1 \equiv 0 \mbox{ (mod }p\mbox{)}$ -then the quantity in the braces must be zero. By reduction, - -\begin{eqnarray} -\left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0 \nonumber \\ -\left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\ -x^2 \equiv a \mbox{ (mod }p\mbox{)} -\end{eqnarray} - -As a result there must be a solution to the quadratic equation and in turn $a$ must be a quadratic residue. If $a$ does not divide $p$ and $a$ -is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since -\begin{equation} -0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)} -\end{equation} -One of the terms on the right hand side must be zero. \textbf{QED} - -\subsection{Jacobi Symbol} -The Jacobi symbol is a generalization of the Legendre function for any odd non prime moduli $p$ greater than 2. If $p = \prod_{i=0}^n p_i$ then -the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation. - -\begin{equation} -\left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right ) -\end{equation} - -By inspection if $p$ is prime the Jacobi symbol is equivalent to the Legendre function. The following facts\footnote{See HAC \cite[pp. 72-74]{HAC} for -further details.} will be used to derive an efficient Jacobi symbol algorithm. Where $p$ is an odd integer greater than two and $a, b \in \Z$ the -following are true. - -\begin{enumerate} -\item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$. -\item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$. -\item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$. -\item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$. Otherwise, it equals $-1$. -\item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$. More specifically -$\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$. -\end{enumerate} - -Using these facts if $a = 2^k \cdot a'$ then - -\begin{eqnarray} -\left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\ - = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right ) -\label{eqn:jacobi} -\end{eqnarray} - -By fact five, - -\begin{equation} -\left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} -\end{equation} - -Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then - -\begin{equation} -\left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} -\end{equation} - -By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed. - -\begin{equation} -\left ( { a \over p } \right ) = \left ( {2 \over p } \right )^k \left ( {{p\mbox{ mod }a'} \over a'} \right ) \cdot (-1)^{(p-1)(a'-1)/4} -\end{equation} - -The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively. The value of -$\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$. Using this approach the -factors of $p$ do not have to be known. Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the -Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_jacobi}. \\ -\textbf{Input}. mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\ -\textbf{Output}. The Jacobi symbol $c = \left ( {a \over p } \right )$. \\ -\hline \\ -1. If $a = 0$ then \\ -\hspace{3mm}1.1 $c \leftarrow 0$ \\ -\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ -2. If $a = 1$ then \\ -\hspace{3mm}2.1 $c \leftarrow 1$ \\ -\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\ -3. $a' \leftarrow a$ \\ -4. $k \leftarrow 0$ \\ -5. While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}5.1 $k \leftarrow k + 1$ \\ -\hspace{3mm}5.2 $a' \leftarrow \lfloor a' / 2 \rfloor$ \\ -6. If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\ -\hspace{3mm}6.1 $s \leftarrow 1$ \\ -7. else \\ -\hspace{3mm}7.1 $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\ -\hspace{3mm}7.2 If $r = 1$ or $r = 7$ then \\ -\hspace{6mm}7.2.1 $s \leftarrow 1$ \\ -\hspace{3mm}7.3 else \\ -\hspace{6mm}7.3.1 $s \leftarrow -1$ \\ -8. If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\ -\hspace{3mm}8.1 $s \leftarrow -s$ \\ -9. If $a' \ne 1$ then \\ -\hspace{3mm}9.1 $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\ -\hspace{3mm}9.2 $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\ -10. $c \leftarrow s$ \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_jacobi} -\end{figure} -\textbf{Algorithm mp\_jacobi.} -This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three. The algorithm -is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}. - -Step numbers one and two handle the trivial cases of $a = 0$ and $a = 1$ respectively. Step five determines the number of two factors in the -input $a$. If $k$ is even than the term $\left ( { 2 \over p } \right )^k$ must always evaluate to one. If $k$ is odd than the term evaluates to one -if $p_0$ is congruent to one or seven modulo eight, otherwise it evaluates to $-1$. After the the $\left ( { 2 \over p } \right )^k$ term is handled -the $(-1)^{(p-1)(a'-1)/4}$ is computed and multiplied against the current product $s$. The latter term evaluates to one if both $p$ and $a'$ -are congruent to one modulo four, otherwise it evaluates to negative one. - -By step nine if $a'$ does not equal one a recursion is required. Step 9.1 computes $p' \equiv p \mbox{ (mod }a'\mbox{)}$ and will recurse to compute -$\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product. - -EXAM,bn_mp_jacobi.c - -As a matter of practicality the variable $a'$ as per the pseudo-code is reprensented by the variable $a1$ since the $'$ symbol is not valid for a C -variable name character. - -The two simple cases of $a = 0$ and $a = 1$ are handled at the very beginning to simplify the algorithm. If the input is non-trivial the algorithm -has to proceed compute the Jacobi. The variable $s$ is used to hold the current Jacobi product. Note that $s$ is merely a C ``int'' data type since -the values it may obtain are merely $-1$, $0$ and $1$. - -After a local copy of $a$ is made all of the factors of two are divided out and the total stored in $k$. Technically only the least significant -bit of $k$ is required, however, it makes the algorithm simpler to follow to perform an addition. In practice an exclusive-or and addition have the same -processor requirements and neither is faster than the other. - -Line @59, if@ through @70, }@ determines the value of $\left ( { 2 \over p } \right )^k$. If the least significant bit of $k$ is zero than -$k$ is even and the value is one. Otherwise, the value of $s$ depends on which residue class $p$ belongs to modulo eight. The value of -$(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines @73, if@ through @75, }@. - -Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$. - -\textit{-- Comment about default $s$ and such...} - -\section{Modular Inverse} -\label{sec:modinv} -The modular inverse of a number actually refers to the modular multiplicative inverse. Essentially for any integer $a$ such that $(a, p) = 1$ there -exist another integer $b$ such that $ab \equiv 1 \mbox{ (mod }p\mbox{)}$. The integer $b$ is called the multiplicative inverse of $a$ which is -denoted as $b = a^{-1}$. Technically speaking modular inversion is a well defined operation for any finite ring or field not just for rings and -fields of integers. However, the former will be the matter of discussion. - -The simplest approach is to compute the algebraic inverse of the input. That is to compute $b \equiv a^{\Phi(p) - 1}$. If $\Phi(p)$ is the -order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$. The proof of which is trivial. - -\begin{equation} -ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)} -\end{equation} - -However, as simple as this approach may be it has two serious flaws. It requires that the value of $\Phi(p)$ be known which if $p$ is composite -requires all of the prime factors. This approach also is very slow as the size of $p$ grows. - -A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear -Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation. - -\begin{equation} -ab + pq = 1 -\end{equation} - -Where $a$, $b$, $p$ and $q$ are all integers. If such a pair of integers $ \left < b, q \right >$ exist than $b$ is the multiplicative inverse of -$a$ modulo $p$. The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$. -However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place. The -binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine -equation. - -\subsection{General Case} -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_invmod}. \\ -\textbf{Input}. mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$. \\ -\textbf{Output}. The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\ -\hline \\ -1. If $b \le 0$ then return(\textit{MP\_VAL}). \\ -2. If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\ -3. $x \leftarrow \vert a \vert, y \leftarrow b$ \\ -4. If $x_0 \equiv y_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\ -5. $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\ -6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\ -\hspace{3mm}6.2 If ($A.used > 0$ and $A_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($B.used > 0$ and $B_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\ -\hspace{6mm}6.2.1 $A \leftarrow A + y$ \\ -\hspace{6mm}6.2.2 $B \leftarrow B - x$ \\ -\hspace{3mm}6.3 $A \leftarrow \lfloor A / 2 \rfloor$ \\ -\hspace{3mm}6.4 $B \leftarrow \lfloor B / 2 \rfloor$ \\ -7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ -\hspace{3mm}7.2 If ($C.used > 0$ and $C_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($D.used > 0$ and $D_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\ -\hspace{6mm}7.2.1 $C \leftarrow C + y$ \\ -\hspace{6mm}7.2.2 $D \leftarrow D - x$ \\ -\hspace{3mm}7.3 $C \leftarrow \lfloor C / 2 \rfloor$ \\ -\hspace{3mm}7.4 $D \leftarrow \lfloor D / 2 \rfloor$ \\ -8. If $u \ge v$ then \\ -\hspace{3mm}8.1 $u \leftarrow u - v$ \\ -\hspace{3mm}8.2 $A \leftarrow A - C$ \\ -\hspace{3mm}8.3 $B \leftarrow B - D$ \\ -9. else \\ -\hspace{3mm}9.1 $v \leftarrow v - u$ \\ -\hspace{3mm}9.2 $C \leftarrow C - A$ \\ -\hspace{3mm}9.3 $D \leftarrow D - B$ \\ -10. If $u \ne 0$ goto step 6. \\ -11. If $v \ne 1$ return(\textit{MP\_VAL}). \\ -12. While $C \le 0$ do \\ -\hspace{3mm}12.1 $C \leftarrow C + b$ \\ -13. While $C \ge b$ do \\ -\hspace{3mm}13.1 $C \leftarrow C - b$ \\ -14. $c \leftarrow C$ \\ -15. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\end{figure} -\textbf{Algorithm mp\_invmod.} -This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$. This algorithm is a variation of the -extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}. It has been modified to only compute the modular inverse and not a complete -Diophantine solution. - -If $b \le 0$ than the modulus is invalid and MP\_VAL is returned. Similarly if both $a$ and $b$ are even then there cannot be a multiplicative -inverse for $a$ and the error is reported. - -The astute reader will observe that steps seven through nine are very similar to the binary greatest common divisor algorithm mp\_gcd. In this case -the other variables to the Diophantine equation are solved. The algorithm terminates when $u = 0$ in which case the solution is - -\begin{equation} -Ca + Db = v -\end{equation} - -If $v$, the greatest common divisor of $a$ and $b$ is not equal to one then the algorithm will report an error as no inverse exists. Otherwise, $C$ -is the modular inverse of $a$. The actual value of $C$ is congruent to, but not necessarily equal to, the ideal modular inverse which should lie -within $1 \le a^{-1} < b$. Step numbers twelve and thirteen adjust the inverse until it is in range. If the original input $a$ is within $0 < a < p$ -then only a couple of additions or subtractions will be required to adjust the inverse. - -EXAM,bn_mp_invmod.c - -\subsubsection{Odd Moduli} - -When the modulus $b$ is odd the variables $A$ and $C$ are fixed and are not required to compute the inverse. In particular by attempting to solve -the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$. - -The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed. This -optimization will halve the time required to compute the modular inverse. - -\section{Primality Tests} - -A non-zero integer $a$ is said to be prime if it is not divisible by any other integer excluding one and itself. For example, $a = 7$ is prime -since the integers $2 \ldots 6$ do not evenly divide $a$. By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$. - -Prime numbers arise in cryptography considerably as they allow finite fields to be formed. The ability to determine whether an integer is prime or -not quickly has been a viable subject in cryptography and number theory for considerable time. The algorithms that will be presented are all -probablistic algorithms in that when they report an integer is composite it must be composite. However, when the algorithms report an integer is -prime the algorithm may be incorrect. - -As will be discussed it is possible to limit the probability of error so well that for practical purposes the probablity of error might as -well be zero. For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question. - -\subsection{Trial Division} - -Trial division means to attempt to evenly divide a candidate integer by small prime integers. If the candidate can be evenly divided it obviously -cannot be prime. By dividing by all primes $1 < p \le \sqrt{n}$ this test can actually prove whether an integer is prime. However, such a test -would require a prohibitive amount of time as $n$ grows. - -Instead of dividing by every prime, a smaller, more mangeable set of primes may be used instead. By performing trial division with only a subset -of the primes less than $\sqrt{n} + 1$ the algorithm cannot prove if a candidate is prime. However, often it can prove a candidate is not prime. - -The benefit of this test is that trial division by small values is fairly efficient. Specially compared to the other algorithms that will be -discussed shortly. The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by -$1 - {1.12 \over ln(q)}$. The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range -$3 \le q \le 100$. - -At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly. At $q = 90$ further testing is generally not going to -be of any practical use. In the case of LibTomMath the default limit $q = 256$ was chosen since it is not too high and will eliminate -approximately $80\%$ of all candidate integers. The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base. The -array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\ -\textbf{Input}. mp\_int $a$ \\ -\textbf{Output}. $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$. \\ -\hline \\ -1. for $ix$ from $0$ to $PRIME\_SIZE$ do \\ -\hspace{3mm}1.1 $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\ -\hspace{3mm}1.2 If $d = 0$ then \\ -\hspace{6mm}1.2.1 $c \leftarrow 1$ \\ -\hspace{6mm}1.2.2 Return(\textit{MP\_OKAY}). \\ -2. $c \leftarrow 0$ \\ -3. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_prime\_is\_divisible} -\end{figure} -\textbf{Algorithm mp\_prime\_is\_divisible.} -This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions. - -EXAM,bn_mp_prime_is_divisible.c - -The algorithm defaults to a return of $0$ in case an error occurs. The values in the prime table are all specified to be in the range of a -mp\_digit. The table \_\_prime\_tab is defined in the following file. - -EXAM,bn_prime_tab.c - -Note that there are two possible tables. When an mp\_digit is 7-bits long only the primes upto $127$ may be included, otherwise the primes -upto $1619$ are used. Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit. - -\subsection{The Fermat Test} -The Fermat test is probably one the oldest tests to have a non-trivial probability of success. It is based on the fact that if $n$ is in -fact prime then $a^{n} \equiv a \mbox{ (mod }n\mbox{)}$ for all $0 < a < n$. The reason being that if $n$ is prime than the order of -the multiplicative sub group is $n - 1$. Any base $a$ must have an order which divides $n - 1$ and as such $a^n$ is equivalent to -$a^1 = a$. - -If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$. In which case -it is possible that $a^n \nequiv a \mbox{ (mod }n\mbox{)}$. However, this test is not absolute as it is possible that the order -of a base will divide $n - 1$ which would then be reported as prime. Such a base yields what is known as a Fermat pseudo-prime. Several -integers known as Carmichael numbers will be a pseudo-prime to all valid bases. Fortunately such numbers are extremely rare as $n$ grows -in size. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_prime\_fermat}. \\ -\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\ -\textbf{Output}. $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$. \\ -\hline \\ -1. $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\ -2. If $t = b$ then \\ -\hspace{3mm}2.1 $c = 1$ \\ -3. else \\ -\hspace{3mm}3.1 $c = 0$ \\ -4. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_prime\_fermat} -\end{figure} -\textbf{Algorithm mp\_prime\_fermat.} -This algorithm determines whether an mp\_int $a$ is a Fermat prime to the base $b$ or not. It uses a single modular exponentiation to -determine the result. - -EXAM,bn_mp_prime_fermat.c - -\subsection{The Miller-Rabin Test} -The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen -candidate integers. The algorithm is based on the observation that if $n - 1 = 2^kr$ and if $b^r \nequiv \pm 1$ then after upto $k - 1$ squarings the -value must be equal to $-1$. The squarings are stopped as soon as $-1$ is observed. If the value of $1$ is observed first it means that -some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\ -\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\ -\textbf{Output}. $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$. \\ -\hline -1. $a' \leftarrow a - 1$ \\ -2. $r \leftarrow n1$ \\ -3. $c \leftarrow 0, s \leftarrow 0$ \\ -4. While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}4.1 $s \leftarrow s + 1$ \\ -\hspace{3mm}4.2 $r \leftarrow \lfloor r / 2 \rfloor$ \\ -5. $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\ -6. If $y \nequiv \pm 1$ then \\ -\hspace{3mm}6.1 $j \leftarrow 1$ \\ -\hspace{3mm}6.2 While $j \le (s - 1)$ and $y \nequiv a'$ \\ -\hspace{6mm}6.2.1 $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\ -\hspace{6mm}6.2.2 If $y = 1$ then goto step 8. \\ -\hspace{6mm}6.2.3 $j \leftarrow j + 1$ \\ -\hspace{3mm}6.3 If $y \nequiv a'$ goto step 8. \\ -7. $c \leftarrow 1$\\ -8. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_prime\_miller\_rabin} -\end{figure} -\textbf{Algorithm mp\_prime\_miller\_rabin.} -This algorithm performs one trial round of the Miller-Rabin algorithm to the base $b$. It will set $c = 1$ if the algorithm cannot determine -if $b$ is composite or $c = 0$ if $b$ is provably composite. The values of $s$ and $r$ are computed such that $a' = a - 1 = 2^sr$. - -If the value $y \equiv b^r$ is congruent to $\pm 1$ then the algorithm cannot prove if $a$ is composite or not. Otherwise, the algorithm will -square $y$ upto $s - 1$ times stopping only when $y \equiv -1$. If $y^2 \equiv 1$ and $y \nequiv \pm 1$ then the algorithm can report that $a$ -is provably composite. If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite. If $a$ is not provably -composite then it is \textit{probably} prime. - -EXAM,bn_mp_prime_miller_rabin.c - - - - -\backmatter -\appendix -\begin{thebibliography}{ABCDEF} -\bibitem[1]{TAOCPV2} -Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998 - -\bibitem[2]{HAC} -A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996 - -\bibitem[3]{ROSE} -Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999 - -\bibitem[4]{COMBA} -Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990) - -\bibitem[5]{KARA} -A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294 - -\bibitem[6]{KARAP} -Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002 - -\bibitem[7]{BARRETT} -Paul Barrett, \textit{Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor}, Advances in Cryptology, Crypto '86, Springer-Verlag. - -\bibitem[8]{MONT} -P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985. - -\bibitem[9]{DRMET} -Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories - -\bibitem[10]{MMB} -J. Daemen and R. Govaerts and J. Vandewalle, \textit{Block ciphers based on Modular Arithmetic}, State and {P}rogress in the {R}esearch of {C}ryptography, 1993, pp. 80-89 - -\bibitem[11]{RSAREF} -R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems} - -\bibitem[12]{DHREF} -Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976 - -\bibitem[13]{IEEE} -IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985) - -\bibitem[14]{GMP} -GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/} - -\bibitem[15]{MPI} -Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/} - -\bibitem[16]{OPENSSL} -OpenSSL Cryptographic Toolkit, \url{http://openssl.org} - -\bibitem[17]{LIP} -Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip} - -\bibitem[18]{ISOC} -JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.'' - -\bibitem[19]{JAVA} -The Sun Java Website, \url{http://java.sun.com/} - -\end{thebibliography} - -\input{tommath.ind} - -\end{document} diff --git a/lib/hcrypto/libtommath/tommath.tex b/lib/hcrypto/libtommath/tommath.tex deleted file mode 100644 index 17d6041d5..000000000 --- a/lib/hcrypto/libtommath/tommath.tex +++ /dev/null @@ -1,6692 +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\labs{{\mathit labs}} -\def\abs{{\mathit abs}} -\def\rep{{\mathit rep}} -\def\mod{{\mathit\ mod\ }} -\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})} -\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor} -\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil} -\def\Or{{\rm\ or\ }} -\def\And{{\rm\ and\ }} -\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}} -\def\implies{\Rightarrow} -\def\undefined{{\rm ``undefined"}} -\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}} -\let\oldphi\phi -\def\phi{\varphi} -\def\Pr{{\rm Pr}} -\newcommand{\str}[1]{{\mathbf{#1}}} -\def\F{{\mathbb F}} -\def\N{{\mathbb N}} -\def\Z{{\mathbb Z}} -\def\R{{\mathbb R}} -\def\C{{\mathbb C}} -\def\Q{{\mathbb Q}} -\definecolor{DGray}{gray}{0.5} -\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}} -\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}} -\def\gap{\vspace{0.5ex}} -\makeindex -\begin{document} -\frontmatter -\pagestyle{empty} -\title{Multi--Precision Math} -\author{\mbox{ -%\begin{small} -\begin{tabular}{c} -Tom St Denis \\ -Algonquin College \\ -\\ -Mads Rasmussen \\ -Open Communications Security \\ -\\ -Greg Rose \\ -QUALCOMM Australia \\ -\end{tabular} -%\end{small} -} -} -\maketitle -This text has been placed in the public domain. This text corresponds to the v0.39 release of the -LibTomMath project. - -\begin{alltt} -Tom St Denis -111 Banning Rd -Ottawa, Ontario -K2L 1C3 -Canada - -Phone: 1-613-836-3160 -Email: tomstdenis@gmail.com -\end{alltt} - -This text is formatted to the international B5 paper size of 176mm wide by 250mm tall using the \LaTeX{} -{\em book} macro package and the Perl {\em booker} package. - -\tableofcontents -\listoffigures -\chapter*{Prefaces} -When I tell people about my LibTom projects and that I release them as public domain they are often puzzled. -They ask why I did it and especially why I continue to work on them for free. The best I can explain it is ``Because I can.'' -Which seems odd and perhaps too terse for adult conversation. I often qualify it with ``I am able, I am willing.'' which -perhaps explains it better. I am the first to admit there is not anything that special with what I have done. Perhaps -others can see that too and then we would have a society to be proud of. My LibTom projects are what I am doing to give -back to society in the form of tools and knowledge that can help others in their endeavours. - -I started writing this book because it was the most logical task to further my goal of open academia. The LibTomMath source -code itself was written to be easy to follow and learn from. There are times, however, where pure C source code does not -explain the algorithms properly. Hence this book. The book literally starts with the foundation of the library and works -itself outwards to the more complicated algorithms. The use of both pseudo--code and verbatim source code provides a duality -of ``theory'' and ``practice'' that the computer science students of the world shall appreciate. I never deviate too far -from relatively straightforward algebra and I hope that this book can be a valuable learning asset. - -This book and indeed much of the LibTom projects would not exist in their current form if it was not for a plethora -of kind people donating their time, resources and kind words to help support my work. Writing a text of significant -length (along with the source code) is a tiresome and lengthy process. Currently the LibTom project is four years old, -comprises of literally thousands of users and over 100,000 lines of source code, TeX and other material. People like Mads and Greg -were there at the beginning to encourage me to work well. It is amazing how timely validation from others can boost morale to -continue the project. Definitely my parents were there for me by providing room and board during the many months of work in 2003. - -To my many friends whom I have met through the years I thank you for the good times and the words of encouragement. I hope I -honour your kind gestures with this project. - -Open Source. Open Academia. Open Minds. - -\begin{flushright} Tom St Denis \end{flushright} - -\newpage -I found the opportunity to work with Tom appealing for several reasons, not only could I broaden my own horizons, but also -contribute to educate others facing the problem of having to handle big number mathematical calculations. - -This book is Tom's child and he has been caring and fostering the project ever since the beginning with a clear mind of -how he wanted the project to turn out. I have helped by proofreading the text and we have had several discussions about -the layout and language used. - -I hold a masters degree in cryptography from the University of Southern Denmark and have always been interested in the -practical aspects of cryptography. - -Having worked in the security consultancy business for several years in S\~{a}o Paulo, Brazil, I have been in touch with a -great deal of work in which multiple precision mathematics was needed. Understanding the possibilities for speeding up -multiple precision calculations is often very important since we deal with outdated machine architecture where modular -reductions, for example, become painfully slow. - -This text is for people who stop and wonder when first examining algorithms such as RSA for the first time and asks -themselves, ``You tell me this is only secure for large numbers, fine; but how do you implement these numbers?'' - -\begin{flushright} -Mads Rasmussen - -S\~{a}o Paulo - SP - -Brazil -\end{flushright} - -\newpage -It's all because I broke my leg. That just happened to be at about the same time that Tom asked for someone to review the section of the book about -Karatsuba multiplication. I was laid up, alone and immobile, and thought ``Why not?'' I vaguely knew what Karatsuba multiplication was, but not -really, so I thought I could help, learn, and stop myself from watching daytime cable TV, all at once. - -At the time of writing this, I've still not met Tom or Mads in meatspace. I've been following Tom's progress since his first splash on the -sci.crypt Usenet news group. I watched him go from a clueless newbie, to the cryptographic equivalent of a reformed smoker, to a real -contributor to the field, over a period of about two years. I've been impressed with his obvious intelligence, and astounded by his productivity. -Of course, he's young enough to be my own child, so he doesn't have my problems with staying awake. - -When I reviewed that single section of the book, in its very earliest form, I was very pleasantly surprised. So I decided to collaborate more fully, -and at least review all of it, and perhaps write some bits too. There's still a long way to go with it, and I have watched a number of close -friends go through the mill of publication, so I think that the way to go is longer than Tom thinks it is. Nevertheless, it's a good effort, -and I'm pleased to be involved with it. - -\begin{flushright} -Greg Rose, Sydney, Australia, June 2003. -\end{flushright} - -\mainmatter -\pagestyle{headings} -\chapter{Introduction} -\section{Multiple Precision Arithmetic} - -\subsection{What is Multiple Precision Arithmetic?} -When we think of long-hand arithmetic such as addition or multiplication we rarely consider the fact that we instinctively -raise or lower the precision of the numbers we are dealing with. For example, in decimal we almost immediate can -reason that $7$ times $6$ is $42$. However, $42$ has two digits of precision as opposed to one digit we started with. -Further multiplications of say $3$ result in a larger precision result $126$. In these few examples we have multiple -precisions for the numbers we are working with. Despite the various levels of precision a single subset\footnote{With the occasional optimization.} - of algorithms can be designed to accomodate them. - -By way of comparison a fixed or single precision operation would lose precision on various operations. For example, in -the decimal system with fixed precision $6 \cdot 7 = 2$. - -Essentially at the heart of computer based multiple precision arithmetic are the same long-hand algorithms taught in -schools to manually add, subtract, multiply and divide. - -\subsection{The Need for Multiple Precision Arithmetic} -The most prevalent need for multiple precision arithmetic, often referred to as ``bignum'' math, is within the implementation -of public-key cryptography algorithms. Algorithms such as RSA \cite{RSAREF} and Diffie-Hellman \cite{DHREF} require -integers of significant magnitude to resist known cryptanalytic attacks. For example, at the time of this writing a -typical RSA modulus would be at least greater than $10^{309}$. However, modern programming languages such as ISO C \cite{ISOC} and -Java \cite{JAVA} only provide instrinsic support for integers which are relatively small and single precision. - -\begin{figure}[!here] -\begin{center} -\begin{tabular}{|r|c|} -\hline \textbf{Data Type} & \textbf{Range} \\ -\hline char & $-128 \ldots 127$ \\ -\hline short & $-32768 \ldots 32767$ \\ -\hline long & $-2147483648 \ldots 2147483647$ \\ -\hline long long & $-9223372036854775808 \ldots 9223372036854775807$ \\ -\hline -\end{tabular} -\end{center} -\caption{Typical Data Types for the C Programming Language} -\label{fig:ISOC} -\end{figure} - -The largest data type guaranteed to be provided by the ISO C programming -language\footnote{As per the ISO C standard. However, each compiler vendor is allowed to augment the precision as they -see fit.} can only represent values up to $10^{19}$ as shown in figure \ref{fig:ISOC}. On its own the C language is -insufficient to accomodate the magnitude required for the problem at hand. An RSA modulus of magnitude $10^{19}$ could be -trivially factored\footnote{A Pollard-Rho factoring would take only $2^{16}$ time.} on the average desktop computer, -rendering any protocol based on the algorithm insecure. Multiple precision algorithms solve this very problem by -extending the range of representable integers while using single precision data types. - -Most advancements in fast multiple precision arithmetic stem from the need for faster and more efficient cryptographic -primitives. Faster modular reduction and exponentiation algorithms such as Barrett's algorithm, which have appeared in -various cryptographic journals, can render algorithms such as RSA and Diffie-Hellman more efficient. In fact, several -major companies such as RSA Security, Certicom and Entrust have built entire product lines on the implementation and -deployment of efficient algorithms. - -However, cryptography is not the only field of study that can benefit from fast multiple precision integer routines. -Another auxiliary use of multiple precision integers is high precision floating point data types. -The basic IEEE \cite{IEEE} standard floating point type is made up of an integer mantissa $q$, an exponent $e$ and a sign bit $s$. -Numbers are given in the form $n = q \cdot b^e \cdot -1^s$ where $b = 2$ is the most common base for IEEE. Since IEEE -floating point is meant to be implemented in hardware the precision of the mantissa is often fairly small -(\textit{23, 48 and 64 bits}). The mantissa is merely an integer and a multiple precision integer could be used to create -a mantissa of much larger precision than hardware alone can efficiently support. This approach could be useful where -scientific applications must minimize the total output error over long calculations. - -Yet another use for large integers is within arithmetic on polynomials of large characteristic (i.e. $GF(p)[x]$ for large $p$). -In fact the library discussed within this text has already been used to form a polynomial basis library\footnote{See \url{http://poly.libtomcrypt.org} for more details.}. - -\subsection{Benefits of Multiple Precision Arithmetic} -\index{precision} -The benefit of multiple precision representations over single or fixed precision representations is that -no precision is lost while representing the result of an operation which requires excess precision. For example, -the product of two $n$-bit integers requires at least $2n$ bits of precision to be represented faithfully. A multiple -precision algorithm would augment the precision of the destination to accomodate the result while a single precision system -would truncate excess bits to maintain a fixed level of precision. - -It is possible to implement algorithms which require large integers with fixed precision algorithms. For example, elliptic -curve cryptography (\textit{ECC}) is often implemented on smartcards by fixing the precision of the integers to the maximum -size the system will ever need. Such an approach can lead to vastly simpler algorithms which can accomodate the -integers required even if the host platform cannot natively accomodate them\footnote{For example, the average smartcard -processor has an 8 bit accumulator.}. However, as efficient as such an approach may be, the resulting source code is not -normally very flexible. It cannot, at runtime, accomodate inputs of higher magnitude than the designer anticipated. - -Multiple precision algorithms have the most overhead of any style of arithmetic. For the the most part the -overhead can be kept to a minimum with careful planning, but overall, it is not well suited for most memory starved -platforms. However, multiple precision algorithms do offer the most flexibility in terms of the magnitude of the -inputs. That is, the same algorithms based on multiple precision integers can accomodate any reasonable size input -without the designer's explicit forethought. This leads to lower cost of ownership for the code as it only has to -be written and tested once. - -\section{Purpose of This Text} -The purpose of this text is to instruct the reader regarding how to implement efficient multiple precision algorithms. -That is to not only explain a limited subset of the core theory behind the algorithms but also the various ``house keeping'' -elements that are neglected by authors of other texts on the subject. Several well reknowned texts \cite{TAOCPV2,HAC} -give considerably detailed explanations of the theoretical aspects of algorithms and often very little information -regarding the practical implementation aspects. - -In most cases how an algorithm is explained and how it is actually implemented are two very different concepts. For -example, the Handbook of Applied Cryptography (\textit{HAC}), algorithm 14.7 on page 594, gives a relatively simple -algorithm for performing multiple precision integer addition. However, the description lacks any discussion concerning -the fact that the two integer inputs may be of differing magnitudes. As a result the implementation is not as simple -as the text would lead people to believe. Similarly the division routine (\textit{algorithm 14.20, pp. 598}) does not -discuss how to handle sign or handle the dividend's decreasing magnitude in the main loop (\textit{step \#3}). - -Both texts also do not discuss several key optimal algorithms required such as ``Comba'' and Karatsuba multipliers -and fast modular inversion, which we consider practical oversights. These optimal algorithms are vital to achieve -any form of useful performance in non-trivial applications. - -To solve this problem the focus of this text is on the practical aspects of implementing a multiple precision integer -package. As a case study the ``LibTomMath''\footnote{Available at \url{http://math.libtomcrypt.com}} package is used -to demonstrate algorithms with real implementations\footnote{In the ISO C programming language.} that have been field -tested and work very well. The LibTomMath library is freely available on the Internet for all uses and this text -discusses a very large portion of the inner workings of the library. - -The algorithms that are presented will always include at least one ``pseudo-code'' description followed -by the actual C source code that implements the algorithm. The pseudo-code can be used to implement the same -algorithm in other programming languages as the reader sees fit. - -This text shall also serve as a walkthrough of the creation of multiple precision algorithms from scratch. Showing -the reader how the algorithms fit together as well as where to start on various taskings. - -\section{Discussion and Notation} -\subsection{Notation} -A multiple precision integer of $n$-digits shall be denoted as $x = (x_{n-1}, \ldots, x_1, x_0)_{ \beta }$ and represent -the integer $x \equiv \sum_{i=0}^{n-1} x_i\beta^i$. The elements of the array $x$ are said to be the radix $\beta$ digits -of the integer. For example, $x = (1,2,3)_{10}$ would represent the integer -$1\cdot 10^2 + 2\cdot10^1 + 3\cdot10^0 = 123$. - -\index{mp\_int} -The term ``mp\_int'' shall refer to a composite structure which contains the digits of the integer it represents, as well -as auxilary data required to manipulate the data. These additional members are discussed further in section -\ref{sec:MPINT}. For the purposes of this text a ``multiple precision integer'' and an ``mp\_int'' are assumed to be -synonymous. When an algorithm is specified to accept an mp\_int variable it is assumed the various auxliary data members -are present as well. An expression of the type \textit{variablename.item} implies that it should evaluate to the -member named ``item'' of the variable. For example, a string of characters may have a member ``length'' which would -evaluate to the number of characters in the string. If the string $a$ equals ``hello'' then it follows that -$a.length = 5$. - -For certain discussions more generic algorithms are presented to help the reader understand the final algorithm used -to solve a given problem. When an algorithm is described as accepting an integer input it is assumed the input is -a plain integer with no additional multiple-precision members. That is, algorithms that use integers as opposed to -mp\_ints as inputs do not concern themselves with the housekeeping operations required such as memory management. These -algorithms will be used to establish the relevant theory which will subsequently be used to describe a multiple -precision algorithm to solve the same problem. - -\subsection{Precision Notation} -The variable $\beta$ represents the radix of a single digit of a multiple precision integer and -must be of the form $q^p$ for $q, p \in \Z^+$. A single precision variable must be able to represent integers in -the range $0 \le x < q \beta$ while a double precision variable must be able to represent integers in the range -$0 \le x < q \beta^2$. The extra radix-$q$ factor allows additions and subtractions to proceed without truncation of the -carry. Since all modern computers are binary, it is assumed that $q$ is two. - -\index{mp\_digit} \index{mp\_word} -Within the source code that will be presented for each algorithm, the data type \textbf{mp\_digit} will represent -a single precision integer type, while, the data type \textbf{mp\_word} will represent a double precision integer type. In -several algorithms (notably the Comba routines) temporary results will be stored in arrays of double precision mp\_words. -For the purposes of this text $x_j$ will refer to the $j$'th digit of a single precision array and $\hat x_j$ will refer to -the $j$'th digit of a double precision array. Whenever an expression is to be assigned to a double precision -variable it is assumed that all single precision variables are promoted to double precision during the evaluation. -Expressions that are assigned to a single precision variable are truncated to fit within the precision of a single -precision data type. - -For example, if $\beta = 10^2$ a single precision data type may represent a value in the -range $0 \le x < 10^3$, while a double precision data type may represent a value in the range $0 \le x < 10^5$. Let -$a = 23$ and $b = 49$ represent two single precision variables. The single precision product shall be written -as $c \leftarrow a \cdot b$ while the double precision product shall be written as $\hat c \leftarrow a \cdot b$. -In this particular case, $\hat c = 1127$ and $c = 127$. The most significant digit of the product would not fit -in a single precision data type and as a result $c \ne \hat c$. - -\subsection{Algorithm Inputs and Outputs} -Within the algorithm descriptions all variables are assumed to be scalars of either single or double precision -as indicated. The only exception to this rule is when variables have been indicated to be of type mp\_int. This -distinction is important as scalars are often used as array indicies and various other counters. - -\subsection{Mathematical Expressions} -The $\lfloor \mbox{ } \rfloor$ brackets imply an expression truncated to an integer not greater than the expression -itself. For example, $\lfloor 5.7 \rfloor = 5$. Similarly the $\lceil \mbox{ } \rceil$ brackets imply an expression -rounded to an integer not less than the expression itself. For example, $\lceil 5.1 \rceil = 6$. Typically when -the $/$ division symbol is used the intention is to perform an integer division with truncation. For example, -$5/2 = 2$ which will often be written as $\lfloor 5/2 \rfloor = 2$ for clarity. When an expression is written as a -fraction a real value division is implied, for example ${5 \over 2} = 2.5$. - -The norm of a multiple precision integer, for example $\vert \vert x \vert \vert$, will be used to represent the number of digits in the representation -of the integer. For example, $\vert \vert 123 \vert \vert = 3$ and $\vert \vert 79452 \vert \vert = 5$. - -\subsection{Work Effort} -\index{big-Oh} -To measure the efficiency of the specified algorithms, a modified big-Oh notation is used. In this system all -single precision operations are considered to have the same cost\footnote{Except where explicitly noted.}. -That is a single precision addition, multiplication and division are assumed to take the same time to -complete. While this is generally not true in practice, it will simplify the discussions considerably. - -Some algorithms have slight advantages over others which is why some constants will not be removed in -the notation. For example, a normal baseline multiplication (section \ref{sec:basemult}) requires $O(n^2)$ work while a -baseline squaring (section \ref{sec:basesquare}) requires $O({{n^2 + n}\over 2})$ work. In standard big-Oh notation these -would both be said to be equivalent to $O(n^2)$. However, -in the context of the this text this is not the case as the magnitude of the inputs will typically be rather small. As a -result small constant factors in the work effort will make an observable difference in algorithm efficiency. - -All of the algorithms presented in this text have a polynomial time work level. That is, of the form -$O(n^k)$ for $n, k \in \Z^{+}$. This will help make useful comparisons in terms of the speed of the algorithms and how -various optimizations will help pay off in the long run. - -\section{Exercises} -Within the more advanced chapters a section will be set aside to give the reader some challenging exercises related to -the discussion at hand. These exercises are not designed to be prize winning problems, but instead to be thought -provoking. Wherever possible the problems are forward minded, stating problems that will be answered in subsequent -chapters. The reader is encouraged to finish the exercises as they appear to get a better understanding of the -subject material. - -That being said, the problems are designed to affirm knowledge of a particular subject matter. Students in particular -are encouraged to verify they can answer the problems correctly before moving on. - -Similar to the exercises of \cite[pp. ix]{TAOCPV2} these exercises are given a scoring system based on the difficulty of -the problem. However, unlike \cite{TAOCPV2} the problems do not get nearly as hard. The scoring of these -exercises ranges from one (the easiest) to five (the hardest). The following table sumarizes the -scoring system used. - -\begin{figure}[here] -\begin{center} -\begin{small} -\begin{tabular}{|c|l|} -\hline $\left [ 1 \right ]$ & An easy problem that should only take the reader a manner of \\ - & minutes to solve. Usually does not involve much computer time \\ - & to solve. \\ -\hline $\left [ 2 \right ]$ & An easy problem that involves a marginal amount of computer \\ - & time usage. Usually requires a program to be written to \\ - & solve the problem. \\ -\hline $\left [ 3 \right ]$ & A moderately hard problem that requires a non-trivial amount \\ - & of work. Usually involves trivial research and development of \\ - & new theory from the perspective of a student. \\ -\hline $\left [ 4 \right ]$ & A moderately hard problem that involves a non-trivial amount \\ - & of work and research, the solution to which will demonstrate \\ - & a higher mastery of the subject matter. \\ -\hline $\left [ 5 \right ]$ & A hard problem that involves concepts that are difficult for a \\ - & novice to solve. Solutions to these problems will demonstrate a \\ - & complete mastery of the given subject. \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Exercise Scoring System} -\end{figure} - -Problems at the first level are meant to be simple questions that the reader can answer quickly without programming a solution or -devising new theory. These problems are quick tests to see if the material is understood. Problems at the second level -are also designed to be easy but will require a program or algorithm to be implemented to arrive at the answer. These -two levels are essentially entry level questions. - -Problems at the third level are meant to be a bit more difficult than the first two levels. The answer is often -fairly obvious but arriving at an exacting solution requires some thought and skill. These problems will almost always -involve devising a new algorithm or implementing a variation of another algorithm previously presented. Readers who can -answer these questions will feel comfortable with the concepts behind the topic at hand. - -Problems at the fourth level are meant to be similar to those of the level three questions except they will require -additional research to be completed. The reader will most likely not know the answer right away, nor will the text provide -the exact details of the answer until a subsequent chapter. - -Problems at the fifth level are meant to be the hardest -problems relative to all the other problems in the chapter. People who can correctly answer fifth level problems have a -mastery of the subject matter at hand. - -Often problems will be tied together. The purpose of this is to start a chain of thought that will be discussed in future chapters. The reader -is encouraged to answer the follow-up problems and try to draw the relevance of problems. - -\section{Introduction to LibTomMath} - -\subsection{What is LibTomMath?} -LibTomMath is a free and open source multiple precision integer library written entirely in portable ISO C. By portable it -is meant that the library does not contain any code that is computer platform dependent or otherwise problematic to use on -any given platform. - -The library has been successfully tested under numerous operating systems including Unix\footnote{All of these -trademarks belong to their respective rightful owners.}, MacOS, Windows, Linux, PalmOS and on standalone hardware such -as the Gameboy Advance. The library is designed to contain enough functionality to be able to develop applications such -as public key cryptosystems and still maintain a relatively small footprint. - -\subsection{Goals of LibTomMath} - -Libraries which obtain the most efficiency are rarely written in a high level programming language such as C. However, -even though this library is written entirely in ISO C, considerable care has been taken to optimize the algorithm implementations within the -library. Specifically the code has been written to work well with the GNU C Compiler (\textit{GCC}) on both x86 and ARM -processors. Wherever possible, highly efficient algorithms, such as Karatsuba multiplication, sliding window -exponentiation and Montgomery reduction have been provided to make the library more efficient. - -Even with the nearly optimal and specialized algorithms that have been included the Application Programing Interface -(\textit{API}) has been kept as simple as possible. Often generic place holder routines will make use of specialized -algorithms automatically without the developer's specific attention. One such example is the generic multiplication -algorithm \textbf{mp\_mul()} which will automatically use Toom--Cook, Karatsuba, Comba or baseline multiplication -based on the magnitude of the inputs and the configuration of the library. - -Making LibTomMath as efficient as possible is not the only goal of the LibTomMath project. Ideally the library should -be source compatible with another popular library which makes it more attractive for developers to use. In this case the -MPI library was used as a API template for all the basic functions. MPI was chosen because it is another library that fits -in the same niche as LibTomMath. Even though LibTomMath uses MPI as the template for the function names and argument -passing conventions, it has been written from scratch by Tom St Denis. - -The project is also meant to act as a learning tool for students, the logic being that no easy-to-follow ``bignum'' -library exists which can be used to teach computer science students how to perform fast and reliable multiple precision -integer arithmetic. To this end the source code has been given quite a few comments and algorithm discussion points. - -\section{Choice of LibTomMath} -LibTomMath was chosen as the case study of this text not only because the author of both projects is one and the same but -for more worthy reasons. Other libraries such as GMP \cite{GMP}, MPI \cite{MPI}, LIP \cite{LIP} and OpenSSL -\cite{OPENSSL} have multiple precision integer arithmetic routines but would not be ideal for this text for -reasons that will be explained in the following sub-sections. - -\subsection{Code Base} -The LibTomMath code base is all portable ISO C source code. This means that there are no platform dependent conditional -segments of code littered throughout the source. This clean and uncluttered approach to the library means that a -developer can more readily discern the true intent of a given section of source code without trying to keep track of -what conditional code will be used. - -The code base of LibTomMath is well organized. Each function is in its own separate source code file -which allows the reader to find a given function very quickly. On average there are $76$ lines of code per source -file which makes the source very easily to follow. By comparison MPI and LIP are single file projects making code tracing -very hard. GMP has many conditional code segments which also hinder tracing. - -When compiled with GCC for the x86 processor and optimized for speed the entire library is approximately $100$KiB\footnote{The notation ``KiB'' means $2^{10}$ octets, similarly ``MiB'' means $2^{20}$ octets.} - which is fairly small compared to GMP (over $250$KiB). LibTomMath is slightly larger than MPI (which compiles to about -$50$KiB) but LibTomMath is also much faster and more complete than MPI. - -\subsection{API Simplicity} -LibTomMath is designed after the MPI library and shares the API design. Quite often programs that use MPI will build -with LibTomMath without change. The function names correlate directly to the action they perform. Almost all of the -functions share the same parameter passing convention. The learning curve is fairly shallow with the API provided -which is an extremely valuable benefit for the student and developer alike. - -The LIP library is an example of a library with an API that is awkward to work with. LIP uses function names that are often ``compressed'' to -illegible short hand. LibTomMath does not share this characteristic. - -The GMP library also does not return error codes. Instead it uses a POSIX.1 \cite{POSIX1} signal system where errors -are signaled to the host application. This happens to be the fastest approach but definitely not the most versatile. In -effect a math error (i.e. invalid input, heap error, etc) can cause a program to stop functioning which is definitely -undersireable in many situations. - -\subsection{Optimizations} -While LibTomMath is certainly not the fastest library (GMP often beats LibTomMath by a factor of two) it does -feature a set of optimal algorithms for tasks such as modular reduction, exponentiation, multiplication and squaring. GMP -and LIP also feature such optimizations while MPI only uses baseline algorithms with no optimizations. GMP lacks a few -of the additional modular reduction optimizations that LibTomMath features\footnote{At the time of this writing GMP -only had Barrett and Montgomery modular reduction algorithms.}. - -LibTomMath is almost always an order of magnitude faster than the MPI library at computationally expensive tasks such as modular -exponentiation. In the grand scheme of ``bignum'' libraries LibTomMath is faster than the average library and usually -slower than the best libraries such as GMP and OpenSSL by only a small factor. - -\subsection{Portability and Stability} -LibTomMath will build ``out of the box'' on any platform equipped with a modern version of the GNU C Compiler -(\textit{GCC}). This means that without changes the library will build without configuration or setting up any -variables. LIP and MPI will build ``out of the box'' as well but have numerous known bugs. Most notably the author of -MPI has recently stopped working on his library and LIP has long since been discontinued. - -GMP requires a configuration script to run and will not build out of the box. GMP and LibTomMath are still in active -development and are very stable across a variety of platforms. - -\subsection{Choice} -LibTomMath is a relatively compact, well documented, highly optimized and portable library which seems only natural for -the case study of this text. Various source files from the LibTomMath project will be included within the text. However, -the reader is encouraged to download their own copy of the library to actually be able to work with the library. - -\chapter{Getting Started} -\section{Library Basics} -The trick to writing any useful library of source code is to build a solid foundation and work outwards from it. First, -a problem along with allowable solution parameters should be identified and analyzed. In this particular case the -inability to accomodate multiple precision integers is the problem. Futhermore, the solution must be written -as portable source code that is reasonably efficient across several different computer platforms. - -After a foundation is formed the remainder of the library can be designed and implemented in a hierarchical fashion. -That is, to implement the lowest level dependencies first and work towards the most abstract functions last. For example, -before implementing a modular exponentiation algorithm one would implement a modular reduction algorithm. -By building outwards from a base foundation instead of using a parallel design methodology the resulting project is -highly modular. Being highly modular is a desirable property of any project as it often means the resulting product -has a small footprint and updates are easy to perform. - -Usually when I start a project I will begin with the header files. I define the data types I think I will need and -prototype the initial functions that are not dependent on other functions (within the library). After I -implement these base functions I prototype more dependent functions and implement them. The process repeats until -I implement all of the functions I require. For example, in the case of LibTomMath I implemented functions such as -mp\_init() well before I implemented mp\_mul() and even further before I implemented mp\_exptmod(). As an example as to -why this design works note that the Karatsuba and Toom-Cook multipliers were written \textit{after} the -dependent function mp\_exptmod() was written. Adding the new multiplication algorithms did not require changes to the -mp\_exptmod() function itself and lowered the total cost of ownership (\textit{so to speak}) and of development -for new algorithms. This methodology allows new algorithms to be tested in a complete framework with relative ease. - -\begin{center} -\begin{figure}[here] -\includegraphics{pics/design_process.ps} -\caption{Design Flow of the First Few Original LibTomMath Functions.} -\label{pic:design_process} -\end{figure} -\end{center} - -Only after the majority of the functions were in place did I pursue a less hierarchical approach to auditing and optimizing -the source code. For example, one day I may audit the multipliers and the next day the polynomial basis functions. - -It only makes sense to begin the text with the preliminary data types and support algorithms required as well. -This chapter discusses the core algorithms of the library which are the dependents for every other algorithm. - -\section{What is a Multiple Precision Integer?} -Recall that most programming languages, in particular ISO C \cite{ISOC}, only have fixed precision data types that on their own cannot -be used to represent values larger than their precision will allow. The purpose of multiple precision algorithms is -to use fixed precision data types to create and manipulate multiple precision integers which may represent values -that are very large. - -As a well known analogy, school children are taught how to form numbers larger than nine by prepending more radix ten digits. In the decimal system -the largest single digit value is $9$. However, by concatenating digits together larger numbers may be represented. Newly prepended digits -(\textit{to the left}) are said to be in a different power of ten column. That is, the number $123$ can be described as having a $1$ in the hundreds -column, $2$ in the tens column and $3$ in the ones column. Or more formally $123 = 1 \cdot 10^2 + 2 \cdot 10^1 + 3 \cdot 10^0$. Computer based -multiple precision arithmetic is essentially the same concept. Larger integers are represented by adjoining fixed -precision computer words with the exception that a different radix is used. - -What most people probably do not think about explicitly are the various other attributes that describe a multiple precision -integer. For example, the integer $154_{10}$ has two immediately obvious properties. First, the integer is positive, -that is the sign of this particular integer is positive as opposed to negative. Second, the integer has three digits in -its representation. There is an additional property that the integer posesses that does not concern pencil-and-paper -arithmetic. The third property is how many digits placeholders are available to hold the integer. - -The human analogy of this third property is ensuring there is enough space on the paper to write the integer. For example, -if one starts writing a large number too far to the right on a piece of paper they will have to erase it and move left. -Similarly, computer algorithms must maintain strict control over memory usage to ensure that the digits of an integer -will not exceed the allowed boundaries. These three properties make up what is known as a multiple precision -integer or mp\_int for short. - -\subsection{The mp\_int Structure} -\label{sec:MPINT} -The mp\_int structure is the ISO C based manifestation of what represents a multiple precision integer. The ISO C standard does not provide for -any such data type but it does provide for making composite data types known as structures. The following is the structure definition -used within LibTomMath. - -\index{mp\_int} -\begin{figure}[here] -\begin{center} -\begin{small} -%\begin{verbatim} -\begin{tabular}{|l|} -\hline -typedef struct \{ \\ -\hspace{3mm}int used, alloc, sign;\\ -\hspace{3mm}mp\_digit *dp;\\ -\} \textbf{mp\_int}; \\ -\hline -\end{tabular} -%\end{verbatim} -\end{small} -\caption{The mp\_int Structure} -\label{fig:mpint} -\end{center} -\end{figure} - -The mp\_int structure (fig. \ref{fig:mpint}) can be broken down as follows. - -\begin{enumerate} -\item The \textbf{used} parameter denotes how many digits of the array \textbf{dp} contain the digits used to represent -a given integer. The \textbf{used} count must be positive (or zero) and may not exceed the \textbf{alloc} count. - -\item The \textbf{alloc} parameter denotes how -many digits are available in the array to use by functions before it has to increase in size. When the \textbf{used} count -of a result would exceed the \textbf{alloc} count all of the algorithms will automatically increase the size of the -array to accommodate the precision of the result. - -\item The pointer \textbf{dp} points to a dynamically allocated array of digits that represent the given multiple -precision integer. It is padded with $(\textbf{alloc} - \textbf{used})$ zero digits. The array is maintained in a least -significant digit order. As a pencil and paper analogy the array is organized such that the right most digits are stored -first starting at the location indexed by zero\footnote{In C all arrays begin at zero.} in the array. For example, -if \textbf{dp} contains $\lbrace a, b, c, \ldots \rbrace$ where \textbf{dp}$_0 = a$, \textbf{dp}$_1 = b$, \textbf{dp}$_2 = c$, $\ldots$ then -it would represent the integer $a + b\beta + c\beta^2 + \ldots$ - -\index{MP\_ZPOS} \index{MP\_NEG} -\item The \textbf{sign} parameter denotes the sign as either zero/positive (\textbf{MP\_ZPOS}) or negative (\textbf{MP\_NEG}). -\end{enumerate} - -\subsubsection{Valid mp\_int Structures} -Several rules are placed on the state of an mp\_int structure and are assumed to be followed for reasons of efficiency. -The only exceptions are when the structure is passed to initialization functions such as mp\_init() and mp\_init\_copy(). - -\begin{enumerate} -\item The value of \textbf{alloc} may not be less than one. That is \textbf{dp} always points to a previously allocated -array of digits. -\item The value of \textbf{used} may not exceed \textbf{alloc} and must be greater than or equal to zero. -\item The value of \textbf{used} implies the digit at index $(used - 1)$ of the \textbf{dp} array is non-zero. That is, -leading zero digits in the most significant positions must be trimmed. - \begin{enumerate} - \item Digits in the \textbf{dp} array at and above the \textbf{used} location must be zero. - \end{enumerate} -\item The value of \textbf{sign} must be \textbf{MP\_ZPOS} if \textbf{used} is zero; -this represents the mp\_int value of zero. -\end{enumerate} - -\section{Argument Passing} -A convention of argument passing must be adopted early on in the development of any library. Making the function -prototypes consistent will help eliminate many headaches in the future as the library grows to significant complexity. -In LibTomMath the multiple precision integer functions accept parameters from left to right as pointers to mp\_int -structures. That means that the source (input) operands are placed on the left and the destination (output) on the right. -Consider the following examples. - -\begin{verbatim} - mp_mul(&a, &b, &c); /* c = a * b */ - mp_add(&a, &b, &a); /* a = a + b */ - mp_sqr(&a, &b); /* b = a * a */ -\end{verbatim} - -The left to right order is a fairly natural way to implement the functions since it lets the developer read aloud the -functions and make sense of them. For example, the first function would read ``multiply a and b and store in c''. - -Certain libraries (\textit{LIP by Lenstra for instance}) accept parameters the other way around, to mimic the order -of assignment expressions. That is, the destination (output) is on the left and arguments (inputs) are on the right. In -truth, it is entirely a matter of preference. In the case of LibTomMath the convention from the MPI library has been -adopted. - -Another very useful design consideration, provided for in LibTomMath, is whether to allow argument sources to also be a -destination. For example, the second example (\textit{mp\_add}) adds $a$ to $b$ and stores in $a$. This is an important -feature to implement since it allows the calling functions to cut down on the number of variables it must maintain. -However, to implement this feature specific care has to be given to ensure the destination is not modified before the -source is fully read. - -\section{Return Values} -A well implemented application, no matter what its purpose, should trap as many runtime errors as possible and return them -to the caller. By catching runtime errors a library can be guaranteed to prevent undefined behaviour. However, the end -developer can still manage to cause a library to crash. For example, by passing an invalid pointer an application may -fault by dereferencing memory not owned by the application. - -In the case of LibTomMath the only errors that are checked for are related to inappropriate inputs (division by zero for -instance) and memory allocation errors. It will not check that the mp\_int passed to any function is valid nor -will it check pointers for validity. Any function that can cause a runtime error will return an error code as an -\textbf{int} data type with one of the following values (fig \ref{fig:errcodes}). - -\index{MP\_OKAY} \index{MP\_VAL} \index{MP\_MEM} -\begin{figure}[here] -\begin{center} -\begin{tabular}{|l|l|} -\hline \textbf{Value} & \textbf{Meaning} \\ -\hline \textbf{MP\_OKAY} & The function was successful \\ -\hline \textbf{MP\_VAL} & One of the input value(s) was invalid \\ -\hline \textbf{MP\_MEM} & The function ran out of heap memory \\ -\hline -\end{tabular} -\end{center} -\caption{LibTomMath Error Codes} -\label{fig:errcodes} -\end{figure} - -When an error is detected within a function it should free any memory it allocated, often during the initialization of -temporary mp\_ints, and return as soon as possible. The goal is to leave the system in the same state it was when the -function was called. Error checking with this style of API is fairly simple. - -\begin{verbatim} - int err; - if ((err = mp_add(&a, &b, &c)) != MP_OKAY) { - printf("Error: %s\n", mp_error_to_string(err)); - exit(EXIT_FAILURE); - } -\end{verbatim} - -The GMP \cite{GMP} library uses C style \textit{signals} to flag errors which is of questionable use. Not all errors are fatal -and it was not deemed ideal by the author of LibTomMath to force developers to have signal handlers for such cases. - -\section{Initialization and Clearing} -The logical starting point when actually writing multiple precision integer functions is the initialization and -clearing of the mp\_int structures. These two algorithms will be used by the majority of the higher level algorithms. - -Given the basic mp\_int structure an initialization routine must first allocate memory to hold the digits of -the integer. Often it is optimal to allocate a sufficiently large pre-set number of digits even though -the initial integer will represent zero. If only a single digit were allocated quite a few subsequent re-allocations -would occur when operations are performed on the integers. There is a tradeoff between how many default digits to allocate -and how many re-allocations are tolerable. Obviously allocating an excessive amount of digits initially will waste -memory and become unmanageable. - -If the memory for the digits has been successfully allocated then the rest of the members of the structure must -be initialized. Since the initial state of an mp\_int is to represent the zero integer, the allocated digits must be set -to zero. The \textbf{used} count set to zero and \textbf{sign} set to \textbf{MP\_ZPOS}. - -\subsection{Initializing an mp\_int} -An mp\_int is said to be initialized if it is set to a valid, preferably default, state such that all of the members of the -structure are set to valid values. The mp\_init algorithm will perform such an action. - -\index{mp\_init} -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_init}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. Allocate memory and initialize $a$ to a known valid mp\_int state. \\ -\hline \\ -1. Allocate memory for \textbf{MP\_PREC} digits. \\ -2. If the allocation failed return(\textit{MP\_MEM}) \\ -3. for $n$ from $0$ to $MP\_PREC - 1$ do \\ -\hspace{3mm}3.1 $a_n \leftarrow 0$\\ -4. $a.sign \leftarrow MP\_ZPOS$\\ -5. $a.used \leftarrow 0$\\ -6. $a.alloc \leftarrow MP\_PREC$\\ -7. Return(\textit{MP\_OKAY})\\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_init} -\end{figure} - -\textbf{Algorithm mp\_init.} -The purpose of this function is to initialize an mp\_int structure so that the rest of the library can properly -manipulte it. It is assumed that the input may not have had any of its members previously initialized which is certainly -a valid assumption if the input resides on the stack. - -Before any of the members such as \textbf{sign}, \textbf{used} or \textbf{alloc} are initialized the memory for -the digits is allocated. If this fails the function returns before setting any of the other members. The \textbf{MP\_PREC} -name represents a constant\footnote{Defined in the ``tommath.h'' header file within LibTomMath.} -used to dictate the minimum precision of newly initialized mp\_int integers. Ideally, it is at least equal to the smallest -precision number you'll be working with. - -Allocating a block of digits at first instead of a single digit has the benefit of lowering the number of usually slow -heap operations later functions will have to perform in the future. If \textbf{MP\_PREC} is set correctly the slack -memory and the number of heap operations will be trivial. - -Once the allocation has been made the digits have to be set to zero as well as the \textbf{used}, \textbf{sign} and -\textbf{alloc} members initialized. This ensures that the mp\_int will always represent the default state of zero regardless -of the original condition of the input. - -\textbf{Remark.} -This function introduces the idiosyncrasy that all iterative loops, commonly initiated with the ``for'' keyword, iterate incrementally -when the ``to'' keyword is placed between two expressions. For example, ``for $a$ from $b$ to $c$ do'' means that -a subsequent expression (or body of expressions) are to be evaluated upto $c - b$ times so long as $b \le c$. In each -iteration the variable $a$ is substituted for a new integer that lies inclusively between $b$ and $c$. If $b > c$ occured -the loop would not iterate. By contrast if the ``downto'' keyword were used in place of ``to'' the loop would iterate -decrementally. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_init.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -One immediate observation of this initializtion function is that it does not return a pointer to a mp\_int structure. It -is assumed that the caller has already allocated memory for the mp\_int structure, typically on the application stack. The -call to mp\_init() is used only to initialize the members of the structure to a known default state. - -Here we see (line 24) the memory allocation is performed first. This allows us to exit cleanly and quickly -if there is an error. If the allocation fails the routine will return \textbf{MP\_MEM} to the caller to indicate there -was a memory error. The function XMALLOC is what actually allocates the memory. Technically XMALLOC is not a function -but a macro defined in ``tommath.h``. By default, XMALLOC will evaluate to malloc() which is the C library's built--in -memory allocation routine. - -In order to assure the mp\_int is in a known state the digits must be set to zero. On most platforms this could have been -accomplished by using calloc() instead of malloc(). However, to correctly initialize a integer type to a given value in a -portable fashion you have to actually assign the value. The for loop (line 30) performs this required -operation. - -After the memory has been successfully initialized the remainder of the members are initialized -(lines 34 through 35) to their respective default states. At this point the algorithm has succeeded and -a success code is returned to the calling function. If this function returns \textbf{MP\_OKAY} it is safe to assume the -mp\_int structure has been properly initialized and is safe to use with other functions within the library. - -\subsection{Clearing an mp\_int} -When an mp\_int is no longer required by the application, the memory that has been allocated for its digits must be -returned to the application's memory pool with the mp\_clear algorithm. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_clear}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. The memory for $a$ shall be deallocated. \\ -\hline \\ -1. If $a$ has been previously freed then return(\textit{MP\_OKAY}). \\ -2. for $n$ from 0 to $a.used - 1$ do \\ -\hspace{3mm}2.1 $a_n \leftarrow 0$ \\ -3. Free the memory allocated for the digits of $a$. \\ -4. $a.used \leftarrow 0$ \\ -5. $a.alloc \leftarrow 0$ \\ -6. $a.sign \leftarrow MP\_ZPOS$ \\ -7. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_clear} -\end{figure} - -\textbf{Algorithm mp\_clear.} -This algorithm accomplishes two goals. First, it clears the digits and the other mp\_int members. This ensures that -if a developer accidentally re-uses a cleared structure it is less likely to cause problems. The second goal -is to free the allocated memory. - -The logic behind the algorithm is extended by marking cleared mp\_int structures so that subsequent calls to this -algorithm will not try to free the memory multiple times. Cleared mp\_ints are detectable by having a pre-defined invalid -digit pointer \textbf{dp} setting. - -Once an mp\_int has been cleared the mp\_int structure is no longer in a valid state for any other algorithm -with the exception of algorithms mp\_init, mp\_init\_copy, mp\_init\_size and mp\_clear. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_clear.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The algorithm only operates on the mp\_int if it hasn't been previously cleared. The if statement (line 25) -checks to see if the \textbf{dp} member is not \textbf{NULL}. If the mp\_int is a valid mp\_int then \textbf{dp} cannot be -\textbf{NULL} in which case the if statement will evaluate to true. - -The digits of the mp\_int are cleared by the for loop (line 27) which assigns a zero to every digit. Similar to mp\_init() -the digits are assigned zero instead of using block memory operations (such as memset()) since this is more portable. - -The digits are deallocated off the heap via the XFREE macro. Similar to XMALLOC the XFREE macro actually evaluates to -a standard C library function. In this case the free() function. Since free() only deallocates the memory the pointer -still has to be reset to \textbf{NULL} manually (line 35). - -Now that the digits have been cleared and deallocated the other members are set to their final values (lines 36 and 37). - -\section{Maintenance Algorithms} - -The previous sections describes how to initialize and clear an mp\_int structure. To further support operations -that are to be performed on mp\_int structures (such as addition and multiplication) the dependent algorithms must be -able to augment the precision of an mp\_int and -initialize mp\_ints with differing initial conditions. - -These algorithms complete the set of low level algorithms required to work with mp\_int structures in the higher level -algorithms such as addition, multiplication and modular exponentiation. - -\subsection{Augmenting an mp\_int's Precision} -When storing a value in an mp\_int structure, a sufficient number of digits must be available to accomodate the entire -result of an operation without loss of precision. Quite often the size of the array given by the \textbf{alloc} member -is large enough to simply increase the \textbf{used} digit count. However, when the size of the array is too small it -must be re-sized appropriately to accomodate the result. The mp\_grow algorithm will provide this functionality. - -\newpage\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_grow}. \\ -\textbf{Input}. An mp\_int $a$ and an integer $b$. \\ -\textbf{Output}. $a$ is expanded to accomodate $b$ digits. \\ -\hline \\ -1. if $a.alloc \ge b$ then return(\textit{MP\_OKAY}) \\ -2. $u \leftarrow b\mbox{ (mod }MP\_PREC\mbox{)}$ \\ -3. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\ -4. Re-allocate the array of digits $a$ to size $v$ \\ -5. If the allocation failed then return(\textit{MP\_MEM}). \\ -6. for n from a.alloc to $v - 1$ do \\ -\hspace{+3mm}6.1 $a_n \leftarrow 0$ \\ -7. $a.alloc \leftarrow v$ \\ -8. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_grow} -\end{figure} - -\textbf{Algorithm mp\_grow.} -It is ideal to prevent re-allocations from being performed if they are not required (step one). This is useful to -prevent mp\_ints from growing excessively in code that erroneously calls mp\_grow. - -The requested digit count is padded up to next multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} (steps two and three). -This helps prevent many trivial reallocations that would grow an mp\_int by trivially small values. - -It is assumed that the reallocation (step four) leaves the lower $a.alloc$ digits of the mp\_int intact. This is much -akin to how the \textit{realloc} function from the standard C library works. Since the newly allocated digits are -assumed to contain undefined values they are initially set to zero. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_grow.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -A quick optimization is to first determine if a memory re-allocation is required at all. The if statement (line 24) checks -if the \textbf{alloc} member of the mp\_int is smaller than the requested digit count. If the count is not larger than \textbf{alloc} -the function skips the re-allocation part thus saving time. - -When a re-allocation is performed it is turned into an optimal request to save time in the future. The requested digit count is -padded upwards to 2nd multiple of \textbf{MP\_PREC} larger than \textbf{alloc} (line 25). The XREALLOC function is used -to re-allocate the memory. As per the other functions XREALLOC is actually a macro which evaluates to realloc by default. The realloc -function leaves the base of the allocation intact which means the first \textbf{alloc} digits of the mp\_int are the same as before -the re-allocation. All that is left is to clear the newly allocated digits and return. - -Note that the re-allocation result is actually stored in a temporary pointer $tmp$. This is to allow this function to return -an error with a valid pointer. Earlier releases of the library stored the result of XREALLOC into the mp\_int $a$. That would -result in a memory leak if XREALLOC ever failed. - -\subsection{Initializing Variable Precision mp\_ints} -Occasionally the number of digits required will be known in advance of an initialization, based on, for example, the size -of input mp\_ints to a given algorithm. The purpose of algorithm mp\_init\_size is similar to mp\_init except that it -will allocate \textit{at least} a specified number of digits. - -\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_init\_size}. \\ -\textbf{Input}. An mp\_int $a$ and the requested number of digits $b$. \\ -\textbf{Output}. $a$ is initialized to hold at least $b$ digits. \\ -\hline \\ -1. $u \leftarrow b \mbox{ (mod }MP\_PREC\mbox{)}$ \\ -2. $v \leftarrow b + 2 \cdot MP\_PREC - u$ \\ -3. Allocate $v$ digits. \\ -4. for $n$ from $0$ to $v - 1$ do \\ -\hspace{3mm}4.1 $a_n \leftarrow 0$ \\ -5. $a.sign \leftarrow MP\_ZPOS$\\ -6. $a.used \leftarrow 0$\\ -7. $a.alloc \leftarrow v$\\ -8. Return(\textit{MP\_OKAY})\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_init\_size} -\end{figure} - -\textbf{Algorithm mp\_init\_size.} -This algorithm will initialize an mp\_int structure $a$ like algorithm mp\_init with the exception that the number of -digits allocated can be controlled by the second input argument $b$. The input size is padded upwards so it is a -multiple of \textbf{MP\_PREC} plus an additional \textbf{MP\_PREC} digits. This padding is used to prevent trivial -allocations from becoming a bottleneck in the rest of the algorithms. - -Like algorithm mp\_init, the mp\_int structure is initialized to a default state representing the integer zero. This -particular algorithm is useful if it is known ahead of time the approximate size of the input. If the approximation is -correct no further memory re-allocations are required to work with the mp\_int. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_size.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The number of digits $b$ requested is padded (line 24) by first augmenting it to the next multiple of -\textbf{MP\_PREC} and then adding \textbf{MP\_PREC} to the result. If the memory can be successfully allocated the -mp\_int is placed in a default state representing the integer zero. Otherwise, the error code \textbf{MP\_MEM} will be -returned (line 29). - -The digits are allocated and set to zero at the same time with the calloc() function (line @25,XCALLOC@). The -\textbf{used} count is set to zero, the \textbf{alloc} count set to the padded digit count and the \textbf{sign} flag set -to \textbf{MP\_ZPOS} to achieve a default valid mp\_int state (lines 33, 34 and 35). If the function -returns succesfully then it is correct to assume that the mp\_int structure is in a valid state for the remainder of the -functions to work with. - -\subsection{Multiple Integer Initializations and Clearings} -Occasionally a function will require a series of mp\_int data types to be made available simultaneously. -The purpose of algorithm mp\_init\_multi is to initialize a variable length array of mp\_int structures in a single -statement. It is essentially a shortcut to multiple initializations. - -\newpage\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_init\_multi}. \\ -\textbf{Input}. Variable length array $V_k$ of mp\_int variables of length $k$. \\ -\textbf{Output}. The array is initialized such that each mp\_int of $V_k$ is ready to use. \\ -\hline \\ -1. for $n$ from 0 to $k - 1$ do \\ -\hspace{+3mm}1.1. Initialize the mp\_int $V_n$ (\textit{mp\_init}) \\ -\hspace{+3mm}1.2. If initialization failed then do \\ -\hspace{+6mm}1.2.1. for $j$ from $0$ to $n$ do \\ -\hspace{+9mm}1.2.1.1. Free the mp\_int $V_j$ (\textit{mp\_clear}) \\ -\hspace{+6mm}1.2.2. Return(\textit{MP\_MEM}) \\ -2. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_init\_multi} -\end{figure} - -\textbf{Algorithm mp\_init\_multi.} -The algorithm will initialize the array of mp\_int variables one at a time. If a runtime error has been detected -(\textit{step 1.2}) all of the previously initialized variables are cleared. The goal is an ``all or nothing'' -initialization which allows for quick recovery from runtime errors. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_multi.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This function intializes a variable length list of mp\_int structure pointers. However, instead of having the mp\_int -structures in an actual C array they are simply passed as arguments to the function. This function makes use of the -``...'' argument syntax of the C programming language. The list is terminated with a final \textbf{NULL} argument -appended on the right. - -The function uses the ``stdarg.h'' \textit{va} functions to step portably through the arguments to the function. A count -$n$ of succesfully initialized mp\_int structures is maintained (line 48) such that if a failure does occur, -the algorithm can backtrack and free the previously initialized structures (lines 28 to 47). - - -\subsection{Clamping Excess Digits} -When a function anticipates a result will be $n$ digits it is simpler to assume this is true within the body of -the function instead of checking during the computation. For example, a multiplication of a $i$ digit number by a -$j$ digit produces a result of at most $i + j$ digits. It is entirely possible that the result is $i + j - 1$ -though, with no final carry into the last position. However, suppose the destination had to be first expanded -(\textit{via mp\_grow}) to accomodate $i + j - 1$ digits than further expanded to accomodate the final carry. -That would be a considerable waste of time since heap operations are relatively slow. - -The ideal solution is to always assume the result is $i + j$ and fix up the \textbf{used} count after the function -terminates. This way a single heap operation (\textit{at most}) is required. However, if the result was not checked -there would be an excess high order zero digit. - -For example, suppose the product of two integers was $x_n = (0x_{n-1}x_{n-2}...x_0)_{\beta}$. The leading zero digit -will not contribute to the precision of the result. In fact, through subsequent operations more leading zero digits would -accumulate to the point the size of the integer would be prohibitive. As a result even though the precision is very -low the representation is excessively large. - -The mp\_clamp algorithm is designed to solve this very problem. It will trim high-order zeros by decrementing the -\textbf{used} count until a non-zero most significant digit is found. Also in this system, zero is considered to be a -positive number which means that if the \textbf{used} count is decremented to zero, the sign must be set to -\textbf{MP\_ZPOS}. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_clamp}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. Any excess leading zero digits of $a$ are removed \\ -\hline \\ -1. while $a.used > 0$ and $a_{a.used - 1} = 0$ do \\ -\hspace{+3mm}1.1 $a.used \leftarrow a.used - 1$ \\ -2. if $a.used = 0$ then do \\ -\hspace{+3mm}2.1 $a.sign \leftarrow MP\_ZPOS$ \\ -\hline \\ -\end{tabular} -\end{center} -\caption{Algorithm mp\_clamp} -\end{figure} - -\textbf{Algorithm mp\_clamp.} -As can be expected this algorithm is very simple. The loop on step one is expected to iterate only once or twice at -the most. For example, this will happen in cases where there is not a carry to fill the last position. Step two fixes the sign for -when all of the digits are zero to ensure that the mp\_int is valid at all times. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_clamp.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Note on line 28 how to test for the \textbf{used} count is made on the left of the \&\& operator. In the C programming -language the terms to \&\& are evaluated left to right with a boolean short-circuit if any condition fails. This is -important since if the \textbf{used} is zero the test on the right would fetch below the array. That is obviously -undesirable. The parenthesis on line 31 is used to make sure the \textbf{used} count is decremented and not -the pointer ``a''. - -\section*{Exercises} -\begin{tabular}{cl} -$\left [ 1 \right ]$ & Discuss the relevance of the \textbf{used} member of the mp\_int structure. \\ - & \\ -$\left [ 1 \right ]$ & Discuss the consequences of not using padding when performing allocations. \\ - & \\ -$\left [ 2 \right ]$ & Estimate an ideal value for \textbf{MP\_PREC} when performing 1024-bit RSA \\ - & encryption when $\beta = 2^{28}$. \\ - & \\ -$\left [ 1 \right ]$ & Discuss the relevance of the algorithm mp\_clamp. What does it prevent? \\ - & \\ -$\left [ 1 \right ]$ & Give an example of when the algorithm mp\_init\_copy might be useful. \\ - & \\ -\end{tabular} - - -%%% -% CHAPTER FOUR -%%% - -\chapter{Basic Operations} - -\section{Introduction} -In the previous chapter a series of low level algorithms were established that dealt with initializing and maintaining -mp\_int structures. This chapter will discuss another set of seemingly non-algebraic algorithms which will form the low -level basis of the entire library. While these algorithm are relatively trivial it is important to understand how they -work before proceeding since these algorithms will be used almost intrinsically in the following chapters. - -The algorithms in this chapter deal primarily with more ``programmer'' related tasks such as creating copies of -mp\_int structures, assigning small values to mp\_int structures and comparisons of the values mp\_int structures -represent. - -\section{Assigning Values to mp\_int Structures} -\subsection{Copying an mp\_int} -Assigning the value that a given mp\_int structure represents to another mp\_int structure shall be known as making -a copy for the purposes of this text. The copy of the mp\_int will be a separate entity that represents the same -value as the mp\_int it was copied from. The mp\_copy algorithm provides this functionality. - -\newpage\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_copy}. \\ -\textbf{Input}. An mp\_int $a$ and $b$. \\ -\textbf{Output}. Store a copy of $a$ in $b$. \\ -\hline \\ -1. If $b.alloc < a.used$ then grow $b$ to $a.used$ digits. (\textit{mp\_grow}) \\ -2. for $n$ from 0 to $a.used - 1$ do \\ -\hspace{3mm}2.1 $b_{n} \leftarrow a_{n}$ \\ -3. for $n$ from $a.used$ to $b.used - 1$ do \\ -\hspace{3mm}3.1 $b_{n} \leftarrow 0$ \\ -4. $b.used \leftarrow a.used$ \\ -5. $b.sign \leftarrow a.sign$ \\ -6. return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_copy} -\end{figure} - -\textbf{Algorithm mp\_copy.} -This algorithm copies the mp\_int $a$ such that upon succesful termination of the algorithm the mp\_int $b$ will -represent the same integer as the mp\_int $a$. The mp\_int $b$ shall be a complete and distinct copy of the -mp\_int $a$ meaing that the mp\_int $a$ can be modified and it shall not affect the value of the mp\_int $b$. - -If $b$ does not have enough room for the digits of $a$ it must first have its precision augmented via the mp\_grow -algorithm. The digits of $a$ are copied over the digits of $b$ and any excess digits of $b$ are set to zero (step two -and three). The \textbf{used} and \textbf{sign} members of $a$ are finally copied over the respective members of -$b$. - -\textbf{Remark.} This algorithm also introduces a new idiosyncrasy that will be used throughout the rest of the -text. The error return codes of other algorithms are not explicitly checked in the pseudo-code presented. For example, in -step one of the mp\_copy algorithm the return of mp\_grow is not explicitly checked to ensure it succeeded. Text space is -limited so it is assumed that if a algorithm fails it will clear all temporarily allocated mp\_ints and return -the error code itself. However, the C code presented will demonstrate all of the error handling logic required to -implement the pseudo-code. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_copy.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Occasionally a dependent algorithm may copy an mp\_int effectively into itself such as when the input and output -mp\_int structures passed to a function are one and the same. For this case it is optimal to return immediately without -copying digits (line 25). - -The mp\_int $b$ must have enough digits to accomodate the used digits of the mp\_int $a$. If $b.alloc$ is less than -$a.used$ the algorithm mp\_grow is used to augment the precision of $b$ (lines 30 to 33). In order to -simplify the inner loop that copies the digits from $a$ to $b$, two aliases $tmpa$ and $tmpb$ point directly at the digits -of the mp\_ints $a$ and $b$ respectively. These aliases (lines 43 and 46) allow the compiler to access the digits without first dereferencing the -mp\_int pointers and then subsequently the pointer to the digits. - -After the aliases are established the digits from $a$ are copied into $b$ (lines 49 to 51) and then the excess -digits of $b$ are set to zero (lines 54 to 56). Both ``for'' loops make use of the pointer aliases and in -fact the alias for $b$ is carried through into the second ``for'' loop to clear the excess digits. This optimization -allows the alias to stay in a machine register fairly easy between the two loops. - -\textbf{Remarks.} The use of pointer aliases is an implementation methodology first introduced in this function that will -be used considerably in other functions. Technically, a pointer alias is simply a short hand alias used to lower the -number of pointer dereferencing operations required to access data. For example, a for loop may resemble - -\begin{alltt} -for (x = 0; x < 100; x++) \{ - a->num[4]->dp[x] = 0; -\} -\end{alltt} - -This could be re-written using aliases as - -\begin{alltt} -mp_digit *tmpa; -a = a->num[4]->dp; -for (x = 0; x < 100; x++) \{ - *a++ = 0; -\} -\end{alltt} - -In this case an alias is used to access the -array of digits within an mp\_int structure directly. It may seem that a pointer alias is strictly not required -as a compiler may optimize out the redundant pointer operations. However, there are two dominant reasons to use aliases. - -The first reason is that most compilers will not effectively optimize pointer arithmetic. For example, some optimizations -may work for the Microsoft Visual C++ compiler (MSVC) and not for the GNU C Compiler (GCC). Also some optimizations may -work for GCC and not MSVC. As such it is ideal to find a common ground for as many compilers as possible. Pointer -aliases optimize the code considerably before the compiler even reads the source code which means the end compiled code -stands a better chance of being faster. - -The second reason is that pointer aliases often can make an algorithm simpler to read. Consider the first ``for'' -loop of the function mp\_copy() re-written to not use pointer aliases. - -\begin{alltt} - /* copy all the digits */ - for (n = 0; n < a->used; n++) \{ - b->dp[n] = a->dp[n]; - \} -\end{alltt} - -Whether this code is harder to read depends strongly on the individual. However, it is quantifiably slightly more -complicated as there are four variables within the statement instead of just two. - -\subsubsection{Nested Statements} -Another commonly used technique in the source routines is that certain sections of code are nested. This is used in -particular with the pointer aliases to highlight code phases. For example, a Comba multiplier (discussed in chapter six) -will typically have three different phases. First the temporaries are initialized, then the columns calculated and -finally the carries are propagated. In this example the middle column production phase will typically be nested as it -uses temporary variables and aliases the most. - -The nesting also simplies the source code as variables that are nested are only valid for their scope. As a result -the various temporary variables required do not propagate into other sections of code. - - -\subsection{Creating a Clone} -Another common operation is to make a local temporary copy of an mp\_int argument. To initialize an mp\_int -and then copy another existing mp\_int into the newly intialized mp\_int will be known as creating a clone. This is -useful within functions that need to modify an argument but do not wish to actually modify the original copy. The -mp\_init\_copy algorithm has been designed to help perform this task. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_init\_copy}. \\ -\textbf{Input}. An mp\_int $a$ and $b$\\ -\textbf{Output}. $a$ is initialized to be a copy of $b$. \\ -\hline \\ -1. Init $a$. (\textit{mp\_init}) \\ -2. Copy $b$ to $a$. (\textit{mp\_copy}) \\ -3. Return the status of the copy operation. \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_init\_copy} -\end{figure} - -\textbf{Algorithm mp\_init\_copy.} -This algorithm will initialize an mp\_int variable and copy another previously initialized mp\_int variable into it. As -such this algorithm will perform two operations in one step. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_init\_copy.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This will initialize \textbf{a} and make it a verbatim copy of the contents of \textbf{b}. Note that -\textbf{a} will have its own memory allocated which means that \textbf{b} may be cleared after the call -and \textbf{a} will be left intact. - -\section{Zeroing an Integer} -Reseting an mp\_int to the default state is a common step in many algorithms. The mp\_zero algorithm will be the algorithm used to -perform this task. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_zero}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. Zero the contents of $a$ \\ -\hline \\ -1. $a.used \leftarrow 0$ \\ -2. $a.sign \leftarrow$ MP\_ZPOS \\ -3. for $n$ from 0 to $a.alloc - 1$ do \\ -\hspace{3mm}3.1 $a_n \leftarrow 0$ \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_zero} -\end{figure} - -\textbf{Algorithm mp\_zero.} -This algorithm simply resets a mp\_int to the default state. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_zero.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -After the function is completed, all of the digits are zeroed, the \textbf{used} count is zeroed and the -\textbf{sign} variable is set to \textbf{MP\_ZPOS}. - -\section{Sign Manipulation} -\subsection{Absolute Value} -With the mp\_int representation of an integer, calculating the absolute value is trivial. The mp\_abs algorithm will compute -the absolute value of an mp\_int. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_abs}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. Computes $b = \vert a \vert$ \\ -\hline \\ -1. Copy $a$ to $b$. (\textit{mp\_copy}) \\ -2. If the copy failed return(\textit{MP\_MEM}). \\ -3. $b.sign \leftarrow MP\_ZPOS$ \\ -4. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_abs} -\end{figure} - -\textbf{Algorithm mp\_abs.} -This algorithm computes the absolute of an mp\_int input. First it copies $a$ over $b$. This is an example of an -algorithm where the check in mp\_copy that determines if the source and destination are equal proves useful. This allows, -for instance, the developer to pass the same mp\_int as the source and destination to this function without addition -logic to handle it. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_abs.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This fairly trivial algorithm first eliminates non--required duplications (line 28) and then sets the -\textbf{sign} flag to \textbf{MP\_ZPOS}. - -\subsection{Integer Negation} -With the mp\_int representation of an integer, calculating the negation is also trivial. The mp\_neg algorithm will compute -the negative of an mp\_int input. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_neg}. \\ -\textbf{Input}. An mp\_int $a$ \\ -\textbf{Output}. Computes $b = -a$ \\ -\hline \\ -1. Copy $a$ to $b$. (\textit{mp\_copy}) \\ -2. If the copy failed return(\textit{MP\_MEM}). \\ -3. If $a.used = 0$ then return(\textit{MP\_OKAY}). \\ -4. If $a.sign = MP\_ZPOS$ then do \\ -\hspace{3mm}4.1 $b.sign = MP\_NEG$. \\ -5. else do \\ -\hspace{3mm}5.1 $b.sign = MP\_ZPOS$. \\ -6. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_neg} -\end{figure} - -\textbf{Algorithm mp\_neg.} -This algorithm computes the negation of an input. First it copies $a$ over $b$. If $a$ has no used digits then -the algorithm returns immediately. Otherwise it flips the sign flag and stores the result in $b$. Note that if -$a$ had no digits then it must be positive by definition. Had step three been omitted then the algorithm would return -zero as negative. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_neg.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Like mp\_abs() this function avoids non--required duplications (line 22) and then sets the sign. We -have to make sure that only non--zero values get a \textbf{sign} of \textbf{MP\_NEG}. If the mp\_int is zero -than the \textbf{sign} is hard--coded to \textbf{MP\_ZPOS}. - -\section{Small Constants} -\subsection{Setting Small Constants} -Often a mp\_int must be set to a relatively small value such as $1$ or $2$. For these cases the mp\_set algorithm is useful. - -\newpage\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_set}. \\ -\textbf{Input}. An mp\_int $a$ and a digit $b$ \\ -\textbf{Output}. Make $a$ equivalent to $b$ \\ -\hline \\ -1. Zero $a$ (\textit{mp\_zero}). \\ -2. $a_0 \leftarrow b \mbox{ (mod }\beta\mbox{)}$ \\ -3. $a.used \leftarrow \left \lbrace \begin{array}{ll} - 1 & \mbox{if }a_0 > 0 \\ - 0 & \mbox{if }a_0 = 0 - \end{array} \right .$ \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_set} -\end{figure} - -\textbf{Algorithm mp\_set.} -This algorithm sets a mp\_int to a small single digit value. Step number 1 ensures that the integer is reset to the default state. The -single digit is set (\textit{modulo $\beta$}) and the \textbf{used} count is adjusted accordingly. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_set.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -First we zero (line 21) the mp\_int to make sure that the other members are initialized for a -small positive constant. mp\_zero() ensures that the \textbf{sign} is positive and the \textbf{used} count -is zero. Next we set the digit and reduce it modulo $\beta$ (line 22). After this step we have to -check if the resulting digit is zero or not. If it is not then we set the \textbf{used} count to one, otherwise -to zero. - -We can quickly reduce modulo $\beta$ since it is of the form $2^k$ and a quick binary AND operation with -$2^k - 1$ will perform the same operation. - -One important limitation of this function is that it will only set one digit. The size of a digit is not fixed, meaning source that uses -this function should take that into account. Only trivially small constants can be set using this function. - -\subsection{Setting Large Constants} -To overcome the limitations of the mp\_set algorithm the mp\_set\_int algorithm is ideal. It accepts a ``long'' -data type as input and will always treat it as a 32-bit integer. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_set\_int}. \\ -\textbf{Input}. An mp\_int $a$ and a ``long'' integer $b$ \\ -\textbf{Output}. Make $a$ equivalent to $b$ \\ -\hline \\ -1. Zero $a$ (\textit{mp\_zero}) \\ -2. for $n$ from 0 to 7 do \\ -\hspace{3mm}2.1 $a \leftarrow a \cdot 16$ (\textit{mp\_mul2d}) \\ -\hspace{3mm}2.2 $u \leftarrow \lfloor b / 2^{4(7 - n)} \rfloor \mbox{ (mod }16\mbox{)}$\\ -\hspace{3mm}2.3 $a_0 \leftarrow a_0 + u$ \\ -\hspace{3mm}2.4 $a.used \leftarrow a.used + 1$ \\ -3. Clamp excess used digits (\textit{mp\_clamp}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_set\_int} -\end{figure} - -\textbf{Algorithm mp\_set\_int.} -The algorithm performs eight iterations of a simple loop where in each iteration four bits from the source are added to the -mp\_int. Step 2.1 will multiply the current result by sixteen making room for four more bits in the less significant positions. In step 2.2 the -next four bits from the source are extracted and are added to the mp\_int. The \textbf{used} digit count is -incremented to reflect the addition. The \textbf{used} digit counter is incremented since if any of the leading digits were zero the mp\_int would have -zero digits used and the newly added four bits would be ignored. - -Excess zero digits are trimmed in steps 2.1 and 3 by using higher level algorithms mp\_mul2d and mp\_clamp. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_set\_int.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This function sets four bits of the number at a time to handle all practical \textbf{DIGIT\_BIT} sizes. The weird -addition on line 39 ensures that the newly added in bits are added to the number of digits. While it may not -seem obvious as to why the digit counter does not grow exceedingly large it is because of the shift on line 28 -as well as the call to mp\_clamp() on line 41. Both functions will clamp excess leading digits which keeps -the number of used digits low. - -\section{Comparisons} -\subsection{Unsigned Comparisions} -Comparing a multiple precision integer is performed with the exact same algorithm used to compare two decimal numbers. For example, -to compare $1,234$ to $1,264$ the digits are extracted by their positions. That is we compare $1 \cdot 10^3 + 2 \cdot 10^2 + 3 \cdot 10^1 + 4 \cdot 10^0$ -to $1 \cdot 10^3 + 2 \cdot 10^2 + 6 \cdot 10^1 + 4 \cdot 10^0$ by comparing single digits at a time starting with the highest magnitude -positions. If any leading digit of one integer is greater than a digit in the same position of another integer then obviously it must be greater. - -The first comparision routine that will be developed is the unsigned magnitude compare which will perform a comparison based on the digits of two -mp\_int variables alone. It will ignore the sign of the two inputs. Such a function is useful when an absolute comparison is required or if the -signs are known to agree in advance. - -To facilitate working with the results of the comparison functions three constants are required. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{|r|l|} -\hline \textbf{Constant} & \textbf{Meaning} \\ -\hline \textbf{MP\_GT} & Greater Than \\ -\hline \textbf{MP\_EQ} & Equal To \\ -\hline \textbf{MP\_LT} & Less Than \\ -\hline -\end{tabular} -\end{center} -\caption{Comparison Return Codes} -\end{figure} - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_cmp\_mag}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$. \\ -\textbf{Output}. Unsigned comparison results ($a$ to the left of $b$). \\ -\hline \\ -1. If $a.used > b.used$ then return(\textit{MP\_GT}) \\ -2. If $a.used < b.used$ then return(\textit{MP\_LT}) \\ -3. for n from $a.used - 1$ to 0 do \\ -\hspace{+3mm}3.1 if $a_n > b_n$ then return(\textit{MP\_GT}) \\ -\hspace{+3mm}3.2 if $a_n < b_n$ then return(\textit{MP\_LT}) \\ -4. Return(\textit{MP\_EQ}) \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_cmp\_mag} -\end{figure} - -\textbf{Algorithm mp\_cmp\_mag.} -By saying ``$a$ to the left of $b$'' it is meant that the comparison is with respect to $a$, that is if $a$ is greater than $b$ it will return -\textbf{MP\_GT} and similar with respect to when $a = b$ and $a < b$. The first two steps compare the number of digits used in both $a$ and $b$. -Obviously if the digit counts differ there would be an imaginary zero digit in the smaller number where the leading digit of the larger number is. -If both have the same number of digits than the actual digits themselves must be compared starting at the leading digit. - -By step three both inputs must have the same number of digits so its safe to start from either $a.used - 1$ or $b.used - 1$ and count down to -the zero'th digit. If after all of the digits have been compared, no difference is found, the algorithm returns \textbf{MP\_EQ}. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_cmp\_mag.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The two if statements (lines 25 and 29) compare the number of digits in the two inputs. These two are -performed before all of the digits are compared since it is a very cheap test to perform and can potentially save -considerable time. The implementation given is also not valid without those two statements. $b.alloc$ may be -smaller than $a.used$, meaning that undefined values will be read from $b$ past the end of the array of digits. - - - -\subsection{Signed Comparisons} -Comparing with sign considerations is also fairly critical in several routines (\textit{division for example}). Based on an unsigned magnitude -comparison a trivial signed comparison algorithm can be written. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_cmp}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$ \\ -\textbf{Output}. Signed Comparison Results ($a$ to the left of $b$) \\ -\hline \\ -1. if $a.sign = MP\_NEG$ and $b.sign = MP\_ZPOS$ then return(\textit{MP\_LT}) \\ -2. if $a.sign = MP\_ZPOS$ and $b.sign = MP\_NEG$ then return(\textit{MP\_GT}) \\ -3. if $a.sign = MP\_NEG$ then \\ -\hspace{+3mm}3.1 Return the unsigned comparison of $b$ and $a$ (\textit{mp\_cmp\_mag}) \\ -4 Otherwise \\ -\hspace{+3mm}4.1 Return the unsigned comparison of $a$ and $b$ \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_cmp} -\end{figure} - -\textbf{Algorithm mp\_cmp.} -The first two steps compare the signs of the two inputs. If the signs do not agree then it can return right away with the appropriate -comparison code. When the signs are equal the digits of the inputs must be compared to determine the correct result. In step -three the unsigned comparision flips the order of the arguments since they are both negative. For instance, if $-a > -b$ then -$\vert a \vert < \vert b \vert$. Step number four will compare the two when they are both positive. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_cmp.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The two if statements (lines 23 and 24) perform the initial sign comparison. If the signs are not the equal then which ever -has the positive sign is larger. The inputs are compared (line 32) based on magnitudes. If the signs were both -negative then the unsigned comparison is performed in the opposite direction (line 34). Otherwise, the signs are assumed to -be both positive and a forward direction unsigned comparison is performed. - -\section*{Exercises} -\begin{tabular}{cl} -$\left [ 2 \right ]$ & Modify algorithm mp\_set\_int to accept as input a variable length array of bits. \\ - & \\ -$\left [ 3 \right ]$ & Give the probability that algorithm mp\_cmp\_mag will have to compare $k$ digits \\ - & of two random digits (of equal magnitude) before a difference is found. \\ - & \\ -$\left [ 1 \right ]$ & Suggest a simple method to speed up the implementation of mp\_cmp\_mag based \\ - & on the observations made in the previous problem. \\ - & -\end{tabular} - -\chapter{Basic Arithmetic} -\section{Introduction} -At this point algorithms for initialization, clearing, zeroing, copying, comparing and setting small constants have been -established. The next logical set of algorithms to develop are addition, subtraction and digit shifting algorithms. These -algorithms make use of the lower level algorithms and are the cruicial building block for the multiplication algorithms. It is very important -that these algorithms are highly optimized. On their own they are simple $O(n)$ algorithms but they can be called from higher level algorithms -which easily places them at $O(n^2)$ or even $O(n^3)$ work levels. - -All of the algorithms within this chapter make use of the logical bit shift operations denoted by $<<$ and $>>$ for left and right -logical shifts respectively. A logical shift is analogous to sliding the decimal point of radix-10 representations. For example, the real -number $0.9345$ is equivalent to $93.45\%$ which is found by sliding the the decimal two places to the right (\textit{multiplying by $\beta^2 = 10^2$}). -Algebraically a binary logical shift is equivalent to a division or multiplication by a power of two. -For example, $a << k = a \cdot 2^k$ while $a >> k = \lfloor a/2^k \rfloor$. - -One significant difference between a logical shift and the way decimals are shifted is that digits below the zero'th position are removed -from the number. For example, consider $1101_2 >> 1$ using decimal notation this would produce $110.1_2$. However, with a logical shift the -result is $110_2$. - -\section{Addition and Subtraction} -In common twos complement fixed precision arithmetic negative numbers are easily represented by subtraction from the modulus. For example, with 32-bit integers -$a - b\mbox{ (mod }2^{32}\mbox{)}$ is the same as $a + (2^{32} - b) \mbox{ (mod }2^{32}\mbox{)}$ since $2^{32} \equiv 0 \mbox{ (mod }2^{32}\mbox{)}$. -As a result subtraction can be performed with a trivial series of logical operations and an addition. - -However, in multiple precision arithmetic negative numbers are not represented in the same way. Instead a sign flag is used to keep track of the -sign of the integer. As a result signed addition and subtraction are actually implemented as conditional usage of lower level addition or -subtraction algorithms with the sign fixed up appropriately. - -The lower level algorithms will add or subtract integers without regard to the sign flag. That is they will add or subtract the magnitude of -the integers respectively. - -\subsection{Low Level Addition} -An unsigned addition of multiple precision integers is performed with the same long-hand algorithm used to add decimal numbers. That is to add the -trailing digits first and propagate the resulting carry upwards. Since this is a lower level algorithm the name will have a ``s\_'' prefix. -Historically that convention stems from the MPI library where ``s\_'' stood for static functions that were hidden from the developer entirely. - -\newpage -\begin{figure}[!here] -\begin{center} -\begin{small} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_add}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$ \\ -\textbf{Output}. The unsigned addition $c = \vert a \vert + \vert b \vert$. \\ -\hline \\ -1. if $a.used > b.used$ then \\ -\hspace{+3mm}1.1 $min \leftarrow b.used$ \\ -\hspace{+3mm}1.2 $max \leftarrow a.used$ \\ -\hspace{+3mm}1.3 $x \leftarrow a$ \\ -2. else \\ -\hspace{+3mm}2.1 $min \leftarrow a.used$ \\ -\hspace{+3mm}2.2 $max \leftarrow b.used$ \\ -\hspace{+3mm}2.3 $x \leftarrow b$ \\ -3. If $c.alloc < max + 1$ then grow $c$ to hold at least $max + 1$ digits (\textit{mp\_grow}) \\ -4. $oldused \leftarrow c.used$ \\ -5. $c.used \leftarrow max + 1$ \\ -6. $u \leftarrow 0$ \\ -7. for $n$ from $0$ to $min - 1$ do \\ -\hspace{+3mm}7.1 $c_n \leftarrow a_n + b_n + u$ \\ -\hspace{+3mm}7.2 $u \leftarrow c_n >> lg(\beta)$ \\ -\hspace{+3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ -8. if $min \ne max$ then do \\ -\hspace{+3mm}8.1 for $n$ from $min$ to $max - 1$ do \\ -\hspace{+6mm}8.1.1 $c_n \leftarrow x_n + u$ \\ -\hspace{+6mm}8.1.2 $u \leftarrow c_n >> lg(\beta)$ \\ -\hspace{+6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ -9. $c_{max} \leftarrow u$ \\ -10. if $olduse > max$ then \\ -\hspace{+3mm}10.1 for $n$ from $max + 1$ to $oldused - 1$ do \\ -\hspace{+6mm}10.1.1 $c_n \leftarrow 0$ \\ -11. Clamp excess digits in $c$. (\textit{mp\_clamp}) \\ -12. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Algorithm s\_mp\_add} -\end{figure} - -\textbf{Algorithm s\_mp\_add.} -This algorithm is loosely based on algorithm 14.7 of HAC \cite[pp. 594]{HAC} but has been extended to allow the inputs to have different magnitudes. -Coincidentally the description of algorithm A in Knuth \cite[pp. 266]{TAOCPV2} shares the same deficiency as the algorithm from \cite{HAC}. Even the -MIX pseudo machine code presented by Knuth \cite[pp. 266-267]{TAOCPV2} is incapable of handling inputs which are of different magnitudes. - -The first thing that has to be accomplished is to sort out which of the two inputs is the largest. The addition logic -will simply add all of the smallest input to the largest input and store that first part of the result in the -destination. Then it will apply a simpler addition loop to excess digits of the larger input. - -The first two steps will handle sorting the inputs such that $min$ and $max$ hold the digit counts of the two -inputs. The variable $x$ will be an mp\_int alias for the largest input or the second input $b$ if they have the -same number of digits. After the inputs are sorted the destination $c$ is grown as required to accomodate the sum -of the two inputs. The original \textbf{used} count of $c$ is copied and set to the new used count. - -At this point the first addition loop will go through as many digit positions that both inputs have. The carry -variable $\mu$ is set to zero outside the loop. Inside the loop an ``addition'' step requires three statements to produce -one digit of the summand. First -two digits from $a$ and $b$ are added together along with the carry $\mu$. The carry of this step is extracted and stored -in $\mu$ and finally the digit of the result $c_n$ is truncated within the range $0 \le c_n < \beta$. - -Now all of the digit positions that both inputs have in common have been exhausted. If $min \ne max$ then $x$ is an alias -for one of the inputs that has more digits. A simplified addition loop is then used to essentially copy the remaining digits -and the carry to the destination. - -The final carry is stored in $c_{max}$ and digits above $max$ upto $oldused$ are zeroed which completes the addition. - - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_add.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -We first sort (lines 28 to 36) the inputs based on magnitude and determine the $min$ and $max$ variables. -Note that $x$ is a pointer to an mp\_int assigned to the largest input, in effect it is a local alias. Next we -grow the destination (38 to 42) ensure that it can accomodate the result of the addition. - -Similar to the implementation of mp\_copy this function uses the braced code and local aliases coding style. The three aliases that are on -lines 56, 59 and 62 represent the two inputs and destination variables respectively. These aliases are used to ensure the -compiler does not have to dereference $a$, $b$ or $c$ (respectively) to access the digits of the respective mp\_int. - -The initial carry $u$ will be cleared (line 65), note that $u$ is of type mp\_digit which ensures type -compatibility within the implementation. The initial addition (line 66 to 75) adds digits from -both inputs until the smallest input runs out of digits. Similarly the conditional addition loop -(line 81 to 90) adds the remaining digits from the larger of the two inputs. The addition is finished -with the final carry being stored in $tmpc$ (line 94). Note the ``++'' operator within the same expression. -After line 94, $tmpc$ will point to the $c.used$'th digit of the mp\_int $c$. This is useful -for the next loop (line 97 to 99) which set any old upper digits to zero. - -\subsection{Low Level Subtraction} -The low level unsigned subtraction algorithm is very similar to the low level unsigned addition algorithm. The principle difference is that the -unsigned subtraction algorithm requires the result to be positive. That is when computing $a - b$ the condition $\vert a \vert \ge \vert b\vert$ must -be met for this algorithm to function properly. Keep in mind this low level algorithm is not meant to be used in higher level algorithms directly. -This algorithm as will be shown can be used to create functional signed addition and subtraction algorithms. - - -For this algorithm a new variable is required to make the description simpler. Recall from section 1.3.1 that a mp\_digit must be able to represent -the range $0 \le x < 2\beta$ for the algorithms to work correctly. However, it is allowable that a mp\_digit represent a larger range of values. For -this algorithm we will assume that the variable $\gamma$ represents the number of bits available in a -mp\_digit (\textit{this implies $2^{\gamma} > \beta$}). - -For example, the default for LibTomMath is to use a ``unsigned long'' for the mp\_digit ``type'' while $\beta = 2^{28}$. In ISO C an ``unsigned long'' -data type must be able to represent $0 \le x < 2^{32}$ meaning that in this case $\gamma \ge 32$. - -\newpage\begin{figure}[!here] -\begin{center} -\begin{small} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_sub}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$ ($\vert a \vert \ge \vert b \vert$) \\ -\textbf{Output}. The unsigned subtraction $c = \vert a \vert - \vert b \vert$. \\ -\hline \\ -1. $min \leftarrow b.used$ \\ -2. $max \leftarrow a.used$ \\ -3. If $c.alloc < max$ then grow $c$ to hold at least $max$ digits. (\textit{mp\_grow}) \\ -4. $oldused \leftarrow c.used$ \\ -5. $c.used \leftarrow max$ \\ -6. $u \leftarrow 0$ \\ -7. for $n$ from $0$ to $min - 1$ do \\ -\hspace{3mm}7.1 $c_n \leftarrow a_n - b_n - u$ \\ -\hspace{3mm}7.2 $u \leftarrow c_n >> (\gamma - 1)$ \\ -\hspace{3mm}7.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ -8. if $min < max$ then do \\ -\hspace{3mm}8.1 for $n$ from $min$ to $max - 1$ do \\ -\hspace{6mm}8.1.1 $c_n \leftarrow a_n - u$ \\ -\hspace{6mm}8.1.2 $u \leftarrow c_n >> (\gamma - 1)$ \\ -\hspace{6mm}8.1.3 $c_n \leftarrow c_n \mbox{ (mod }\beta\mbox{)}$ \\ -9. if $oldused > max$ then do \\ -\hspace{3mm}9.1 for $n$ from $max$ to $oldused - 1$ do \\ -\hspace{6mm}9.1.1 $c_n \leftarrow 0$ \\ -10. Clamp excess digits of $c$. (\textit{mp\_clamp}). \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Algorithm s\_mp\_sub} -\end{figure} - -\textbf{Algorithm s\_mp\_sub.} -This algorithm performs the unsigned subtraction of two mp\_int variables under the restriction that the result must be positive. That is when -passing variables $a$ and $b$ the condition that $\vert a \vert \ge \vert b \vert$ must be met for the algorithm to function correctly. This -algorithm is loosely based on algorithm 14.9 \cite[pp. 595]{HAC} and is similar to algorithm S in \cite[pp. 267]{TAOCPV2} as well. As was the case -of the algorithm s\_mp\_add both other references lack discussion concerning various practical details such as when the inputs differ in magnitude. - -The initial sorting of the inputs is trivial in this algorithm since $a$ is guaranteed to have at least the same magnitude of $b$. Steps 1 and 2 -set the $min$ and $max$ variables. Unlike the addition routine there is guaranteed to be no carry which means that the final result can be at -most $max$ digits in length as opposed to $max + 1$. Similar to the addition algorithm the \textbf{used} count of $c$ is copied locally and -set to the maximal count for the operation. - -The subtraction loop that begins on step seven is essentially the same as the addition loop of algorithm s\_mp\_add except single precision -subtraction is used instead. Note the use of the $\gamma$ variable to extract the carry (\textit{also known as the borrow}) within the subtraction -loops. Under the assumption that two's complement single precision arithmetic is used this will successfully extract the desired carry. - -For example, consider subtracting $0101_2$ from $0100_2$ where $\gamma = 4$ and $\beta = 2$. The least significant bit will force a carry upwards to -the third bit which will be set to zero after the borrow. After the very first bit has been subtracted $4 - 1 \equiv 0011_2$ will remain, When the -third bit of $0101_2$ is subtracted from the result it will cause another carry. In this case though the carry will be forced to propagate all the -way to the most significant bit. - -Recall that $\beta < 2^{\gamma}$. This means that if a carry does occur just before the $lg(\beta)$'th bit it will propagate all the way to the most -significant bit. Thus, the high order bits of the mp\_digit that are not part of the actual digit will either be all zero, or all one. All that -is needed is a single zero or one bit for the carry. Therefore a single logical shift right by $\gamma - 1$ positions is sufficient to extract the -carry. This method of carry extraction may seem awkward but the reason for it becomes apparent when the implementation is discussed. - -If $b$ has a smaller magnitude than $a$ then step 9 will force the carry and copy operation to propagate through the larger input $a$ into $c$. Step -10 will ensure that any leading digits of $c$ above the $max$'th position are zeroed. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sub.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Like low level addition we ``sort'' the inputs. Except in this case the sorting is hardcoded -(lines 25 and 26). In reality the $min$ and $max$ variables are only aliases and are only -used to make the source code easier to read. Again the pointer alias optimization is used -within this algorithm. The aliases $tmpa$, $tmpb$ and $tmpc$ are initialized -(lines 42, 43 and 44) for $a$, $b$ and $c$ respectively. - -The first subtraction loop (lines 47 through 61) subtract digits from both inputs until the smaller of -the two inputs has been exhausted. As remarked earlier there is an implementation reason for using the ``awkward'' -method of extracting the carry (line 57). The traditional method for extracting the carry would be to shift -by $lg(\beta)$ positions and logically AND the least significant bit. The AND operation is required because all of -the bits above the $\lg(\beta)$'th bit will be set to one after a carry occurs from subtraction. This carry -extraction requires two relatively cheap operations to extract the carry. The other method is to simply shift the -most significant bit to the least significant bit thus extracting the carry with a single cheap operation. This -optimization only works on twos compliment machines which is a safe assumption to make. - -If $a$ has a larger magnitude than $b$ an additional loop (lines 64 through 73) is required to propagate -the carry through $a$ and copy the result to $c$. - -\subsection{High Level Addition} -Now that both lower level addition and subtraction algorithms have been established an effective high level signed addition algorithm can be -established. This high level addition algorithm will be what other algorithms and developers will use to perform addition of mp\_int data -types. - -Recall from section 5.2 that an mp\_int represents an integer with an unsigned mantissa (\textit{the array of digits}) and a \textbf{sign} -flag. A high level addition is actually performed as a series of eight separate cases which can be optimized down to three unique cases. - -\begin{figure}[!here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_add}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$ \\ -\textbf{Output}. The signed addition $c = a + b$. \\ -\hline \\ -1. if $a.sign = b.sign$ then do \\ -\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\ -\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add})\\ -2. else do \\ -\hspace{3mm}2.1 if $\vert a \vert < \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\ -\hspace{6mm}2.1.1 $c.sign \leftarrow b.sign$ \\ -\hspace{6mm}2.1.2 $c \leftarrow \vert b \vert - \vert a \vert$ (\textit{s\_mp\_sub}) \\ -\hspace{3mm}2.2 else do \\ -\hspace{6mm}2.2.1 $c.sign \leftarrow a.sign$ \\ -\hspace{6mm}2.2.2 $c \leftarrow \vert a \vert - \vert b \vert$ \\ -3. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_add} -\end{figure} - -\textbf{Algorithm mp\_add.} -This algorithm performs the signed addition of two mp\_int variables. There is no reference algorithm to draw upon from -either \cite{TAOCPV2} or \cite{HAC} since they both only provide unsigned operations. The algorithm is fairly -straightforward but restricted since subtraction can only produce positive results. - -\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{|c|c|c|c|c|} -\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert > \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\ -\hline $+$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\ -\hline $+$ & $+$ & No & $c = a + b$ & $a.sign$ \\ -\hline $-$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\ -\hline $-$ & $-$ & No & $c = a + b$ & $a.sign$ \\ -\hline &&&&\\ - -\hline $+$ & $-$ & No & $c = b - a$ & $b.sign$ \\ -\hline $-$ & $+$ & No & $c = b - a$ & $b.sign$ \\ - -\hline &&&&\\ - -\hline $+$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\ -\hline $-$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\ - -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Addition Guide Chart} -\label{fig:AddChart} -\end{figure} - -Figure~\ref{fig:AddChart} lists all of the eight possible input combinations and is sorted to show that only three -specific cases need to be handled. The return code of the unsigned operations at step 1.2, 2.1.2 and 2.2.2 are -forwarded to step three to check for errors. This simplifies the description of the algorithm considerably and best -follows how the implementation actually was achieved. - -Also note how the \textbf{sign} is set before the unsigned addition or subtraction is performed. Recall from the descriptions of algorithms -s\_mp\_add and s\_mp\_sub that the mp\_clamp function is used at the end to trim excess digits. The mp\_clamp algorithm will set the \textbf{sign} -to \textbf{MP\_ZPOS} when the \textbf{used} digit count reaches zero. - -For example, consider performing $-a + a$ with algorithm mp\_add. By the description of the algorithm the sign is set to \textbf{MP\_NEG} which would -produce a result of $-0$. However, since the sign is set first then the unsigned addition is performed the subsequent usage of algorithm mp\_clamp -within algorithm s\_mp\_add will force $-0$ to become $0$. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_add.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The source code follows the algorithm fairly closely. The most notable new source code addition is the usage of the $res$ integer variable which -is used to pass result of the unsigned operations forward. Unlike in the algorithm, the variable $res$ is merely returned as is without -explicitly checking it and returning the constant \textbf{MP\_OKAY}. The observation is this algorithm will succeed or fail only if the lower -level functions do so. Returning their return code is sufficient. - -\subsection{High Level Subtraction} -The high level signed subtraction algorithm is essentially the same as the high level signed addition algorithm. - -\newpage\begin{figure}[!here] -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_sub}. \\ -\textbf{Input}. Two mp\_ints $a$ and $b$ \\ -\textbf{Output}. The signed subtraction $c = a - b$. \\ -\hline \\ -1. if $a.sign \ne b.sign$ then do \\ -\hspace{3mm}1.1 $c.sign \leftarrow a.sign$ \\ -\hspace{3mm}1.2 $c \leftarrow \vert a \vert + \vert b \vert$ (\textit{s\_mp\_add}) \\ -2. else do \\ -\hspace{3mm}2.1 if $\vert a \vert \ge \vert b \vert$ then do (\textit{mp\_cmp\_mag}) \\ -\hspace{6mm}2.1.1 $c.sign \leftarrow a.sign$ \\ -\hspace{6mm}2.1.2 $c \leftarrow \vert a \vert - \vert b \vert$ (\textit{s\_mp\_sub}) \\ -\hspace{3mm}2.2 else do \\ -\hspace{6mm}2.2.1 $c.sign \leftarrow \left \lbrace \begin{array}{ll} - MP\_ZPOS & \mbox{if }a.sign = MP\_NEG \\ - MP\_NEG & \mbox{otherwise} \\ - \end{array} \right .$ \\ -\hspace{6mm}2.2.2 $c \leftarrow \vert b \vert - \vert a \vert$ \\ -3. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\caption{Algorithm mp\_sub} -\end{figure} - -\textbf{Algorithm mp\_sub.} -This algorithm performs the signed subtraction of two inputs. Similar to algorithm mp\_add there is no reference in either \cite{TAOCPV2} or -\cite{HAC}. Also this algorithm is restricted by algorithm s\_mp\_sub. Chart \ref{fig:SubChart} lists the eight possible inputs and -the operations required. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{|c|c|c|c|c|} -\hline \textbf{Sign of $a$} & \textbf{Sign of $b$} & \textbf{$\vert a \vert \ge \vert b \vert $} & \textbf{Unsigned Operation} & \textbf{Result Sign Flag} \\ -\hline $+$ & $-$ & Yes & $c = a + b$ & $a.sign$ \\ -\hline $+$ & $-$ & No & $c = a + b$ & $a.sign$ \\ -\hline $-$ & $+$ & Yes & $c = a + b$ & $a.sign$ \\ -\hline $-$ & $+$ & No & $c = a + b$ & $a.sign$ \\ -\hline &&&& \\ -\hline $+$ & $+$ & Yes & $c = a - b$ & $a.sign$ \\ -\hline $-$ & $-$ & Yes & $c = a - b$ & $a.sign$ \\ -\hline &&&& \\ -\hline $+$ & $+$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\ -\hline $-$ & $-$ & No & $c = b - a$ & $\mbox{opposite of }a.sign$ \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Subtraction Guide Chart} -\label{fig:SubChart} -\end{figure} - -Similar to the case of algorithm mp\_add the \textbf{sign} is set first before the unsigned addition or subtraction. That is to prevent the -algorithm from producing $-a - -a = -0$ as a result. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_sub.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Much like the implementation of algorithm mp\_add the variable $res$ is used to catch the return code of the unsigned addition or subtraction operations -and forward it to the end of the function. On line 39 the ``not equal to'' \textbf{MP\_LT} expression is used to emulate a -``greater than or equal to'' comparison. - -\section{Bit and Digit Shifting} -It is quite common to think of a multiple precision integer as a polynomial in $x$, that is $y = f(\beta)$ where $f(x) = \sum_{i=0}^{n-1} a_i x^i$. -This notation arises within discussion of Montgomery and Diminished Radix Reduction as well as Karatsuba multiplication and squaring. - -In order to facilitate operations on polynomials in $x$ as above a series of simple ``digit'' algorithms have to be established. That is to shift -the digits left or right as well to shift individual bits of the digits left and right. It is important to note that not all ``shift'' operations -are on radix-$\beta$ digits. - -\subsection{Multiplication by Two} - -In a binary system where the radix is a power of two multiplication by two not only arises often in other algorithms it is a fairly efficient -operation to perform. A single precision logical shift left is sufficient to multiply a single digit by two. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_mul\_2}. \\ -\textbf{Input}. One mp\_int $a$ \\ -\textbf{Output}. $b = 2a$. \\ -\hline \\ -1. If $b.alloc < a.used + 1$ then grow $b$ to hold $a.used + 1$ digits. (\textit{mp\_grow}) \\ -2. $oldused \leftarrow b.used$ \\ -3. $b.used \leftarrow a.used$ \\ -4. $r \leftarrow 0$ \\ -5. for $n$ from 0 to $a.used - 1$ do \\ -\hspace{3mm}5.1 $rr \leftarrow a_n >> (lg(\beta) - 1)$ \\ -\hspace{3mm}5.2 $b_n \leftarrow (a_n << 1) + r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}5.3 $r \leftarrow rr$ \\ -6. If $r \ne 0$ then do \\ -\hspace{3mm}6.1 $b_{n + 1} \leftarrow r$ \\ -\hspace{3mm}6.2 $b.used \leftarrow b.used + 1$ \\ -7. If $b.used < oldused - 1$ then do \\ -\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\ -\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\ -8. $b.sign \leftarrow a.sign$ \\ -9. Return(\textit{MP\_OKAY}).\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_mul\_2} -\end{figure} - -\textbf{Algorithm mp\_mul\_2.} -This algorithm will quickly multiply a mp\_int by two provided $\beta$ is a power of two. Neither \cite{TAOCPV2} nor \cite{HAC} describe such -an algorithm despite the fact it arises often in other algorithms. The algorithm is setup much like the lower level algorithm s\_mp\_add since -it is for all intents and purposes equivalent to the operation $b = \vert a \vert + \vert a \vert$. - -Step 1 and 2 grow the input as required to accomodate the maximum number of \textbf{used} digits in the result. The initial \textbf{used} count -is set to $a.used$ at step 4. Only if there is a final carry will the \textbf{used} count require adjustment. - -Step 6 is an optimization implementation of the addition loop for this specific case. That is since the two values being added together -are the same there is no need to perform two reads from the digits of $a$. Step 6.1 performs a single precision shift on the current digit $a_n$ to -obtain what will be the carry for the next iteration. Step 6.2 calculates the $n$'th digit of the result as single precision shift of $a_n$ plus -the previous carry. Recall from section 4.1 that $a_n << 1$ is equivalent to $a_n \cdot 2$. An iteration of the addition loop is finished with -forwarding the carry to the next iteration. - -Step 7 takes care of any final carry by setting the $a.used$'th digit of the result to the carry and augmenting the \textbf{used} count of $b$. -Step 8 clears any leading digits of $b$ in case it originally had a larger magnitude than $a$. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This implementation is essentially an optimized implementation of s\_mp\_add for the case of doubling an input. The only noteworthy difference -is the use of the logical shift operator on line 52 to perform a single precision doubling. - -\subsection{Division by Two} -A division by two can just as easily be accomplished with a logical shift right as multiplication by two can be with a logical shift left. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_div\_2}. \\ -\textbf{Input}. One mp\_int $a$ \\ -\textbf{Output}. $b = a/2$. \\ -\hline \\ -1. If $b.alloc < a.used$ then grow $b$ to hold $a.used$ digits. (\textit{mp\_grow}) \\ -2. If the reallocation failed return(\textit{MP\_MEM}). \\ -3. $oldused \leftarrow b.used$ \\ -4. $b.used \leftarrow a.used$ \\ -5. $r \leftarrow 0$ \\ -6. for $n$ from $b.used - 1$ to $0$ do \\ -\hspace{3mm}6.1 $rr \leftarrow a_n \mbox{ (mod }2\mbox{)}$\\ -\hspace{3mm}6.2 $b_n \leftarrow (a_n >> 1) + (r << (lg(\beta) - 1)) \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}6.3 $r \leftarrow rr$ \\ -7. If $b.used < oldused - 1$ then do \\ -\hspace{3mm}7.1 for $n$ from $b.used$ to $oldused - 1$ do \\ -\hspace{6mm}7.1.1 $b_n \leftarrow 0$ \\ -8. $b.sign \leftarrow a.sign$ \\ -9. Clamp excess digits of $b$. (\textit{mp\_clamp}) \\ -10. Return(\textit{MP\_OKAY}).\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_div\_2} -\end{figure} - -\textbf{Algorithm mp\_div\_2.} -This algorithm will divide an mp\_int by two using logical shifts to the right. Like mp\_mul\_2 it uses a modified low level addition -core as the basis of the algorithm. Unlike mp\_mul\_2 the shift operations work from the leading digit to the trailing digit. The algorithm -could be written to work from the trailing digit to the leading digit however, it would have to stop one short of $a.used - 1$ digits to prevent -reading past the end of the array of digits. - -Essentially the loop at step 6 is similar to that of mp\_mul\_2 except the logical shifts go in the opposite direction and the carry is at the -least significant bit not the most significant bit. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\section{Polynomial Basis Operations} -Recall from section 4.3 that any integer can be represented as a polynomial in $x$ as $y = f(\beta)$. Such a representation is also known as -the polynomial basis \cite[pp. 48]{ROSE}. Given such a notation a multiplication or division by $x$ amounts to shifting whole digits a single -place. The need for such operations arises in several other higher level algorithms such as Barrett and Montgomery reduction, integer -division and Karatsuba multiplication. - -Converting from an array of digits to polynomial basis is very simple. Consider the integer $y \equiv (a_2, a_1, a_0)_{\beta}$ and recall that -$y = \sum_{i=0}^{2} a_i \beta^i$. Simply replace $\beta$ with $x$ and the expression is in polynomial basis. For example, $f(x) = 8x + 9$ is the -polynomial basis representation for $89$ using radix ten. That is, $f(10) = 8(10) + 9 = 89$. - -\subsection{Multiplication by $x$} - -Given a polynomial in $x$ such as $f(x) = a_n x^n + a_{n-1} x^{n-1} + ... + a_0$ multiplying by $x$ amounts to shifting the coefficients up one -degree. In this case $f(x) \cdot x = a_n x^{n+1} + a_{n-1} x^n + ... + a_0 x$. From a scalar basis point of view multiplying by $x$ is equivalent to -multiplying by the integer $\beta$. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_lshd}. \\ -\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ -\textbf{Output}. $a \leftarrow a \cdot \beta^b$ (equivalent to multiplication by $x^b$). \\ -\hline \\ -1. If $b \le 0$ then return(\textit{MP\_OKAY}). \\ -2. If $a.alloc < a.used + b$ then grow $a$ to at least $a.used + b$ digits. (\textit{mp\_grow}). \\ -3. If the reallocation failed return(\textit{MP\_MEM}). \\ -4. $a.used \leftarrow a.used + b$ \\ -5. $i \leftarrow a.used - 1$ \\ -6. $j \leftarrow a.used - 1 - b$ \\ -7. for $n$ from $a.used - 1$ to $b$ do \\ -\hspace{3mm}7.1 $a_{i} \leftarrow a_{j}$ \\ -\hspace{3mm}7.2 $i \leftarrow i - 1$ \\ -\hspace{3mm}7.3 $j \leftarrow j - 1$ \\ -8. for $n$ from 0 to $b - 1$ do \\ -\hspace{3mm}8.1 $a_n \leftarrow 0$ \\ -9. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_lshd} -\end{figure} - -\textbf{Algorithm mp\_lshd.} -This algorithm multiplies an mp\_int by the $b$'th power of $x$. This is equivalent to multiplying by $\beta^b$. The algorithm differs -from the other algorithms presented so far as it performs the operation in place instead storing the result in a separate location. The -motivation behind this change is due to the way this function is typically used. Algorithms such as mp\_add store the result in an optionally -different third mp\_int because the original inputs are often still required. Algorithm mp\_lshd (\textit{and similarly algorithm mp\_rshd}) is -typically used on values where the original value is no longer required. The algorithm will return success immediately if -$b \le 0$ since the rest of algorithm is only valid when $b > 0$. - -First the destination $a$ is grown as required to accomodate the result. The counters $i$ and $j$ are used to form a \textit{sliding window} over -the digits of $a$ of length $b$. The head of the sliding window is at $i$ (\textit{the leading digit}) and the tail at $j$ (\textit{the trailing digit}). -The loop on step 7 copies the digit from the tail to the head. In each iteration the window is moved down one digit. The last loop on -step 8 sets the lower $b$ digits to zero. - -\newpage -\begin{center} -\begin{figure}[here] -\includegraphics{pics/sliding_window.ps} -\caption{Sliding Window Movement} -\label{pic:sliding_window} -\end{figure} -\end{center} - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_lshd.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The if statement (line 24) ensures that the $b$ variable is greater than zero since we do not interpret negative -shift counts properly. The \textbf{used} count is incremented by $b$ before the copy loop begins. This elminates -the need for an additional variable in the for loop. The variable $top$ (line 42) is an alias -for the leading digit while $bottom$ (line 45) is an alias for the trailing edge. The aliases form a -window of exactly $b$ digits over the input. - -\subsection{Division by $x$} - -Division by powers of $x$ is easily achieved by shifting the digits right and removing any that will end up to the right of the zero'th digit. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_rshd}. \\ -\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ -\textbf{Output}. $a \leftarrow a / \beta^b$ (Divide by $x^b$). \\ -\hline \\ -1. If $b \le 0$ then return. \\ -2. If $a.used \le b$ then do \\ -\hspace{3mm}2.1 Zero $a$. (\textit{mp\_zero}). \\ -\hspace{3mm}2.2 Return. \\ -3. $i \leftarrow 0$ \\ -4. $j \leftarrow b$ \\ -5. for $n$ from 0 to $a.used - b - 1$ do \\ -\hspace{3mm}5.1 $a_i \leftarrow a_j$ \\ -\hspace{3mm}5.2 $i \leftarrow i + 1$ \\ -\hspace{3mm}5.3 $j \leftarrow j + 1$ \\ -6. for $n$ from $a.used - b$ to $a.used - 1$ do \\ -\hspace{3mm}6.1 $a_n \leftarrow 0$ \\ -7. $a.used \leftarrow a.used - b$ \\ -8. Return. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_rshd} -\end{figure} - -\textbf{Algorithm mp\_rshd.} -This algorithm divides the input in place by the $b$'th power of $x$. It is analogous to dividing by a $\beta^b$ but much quicker since -it does not require single precision division. This algorithm does not actually return an error code as it cannot fail. - -If the input $b$ is less than one the algorithm quickly returns without performing any work. If the \textbf{used} count is less than or equal -to the shift count $b$ then it will simply zero the input and return. - -After the trivial cases of inputs have been handled the sliding window is setup. Much like the case of algorithm mp\_lshd a sliding window that -is $b$ digits wide is used to copy the digits. Unlike mp\_lshd the window slides in the opposite direction from the trailing to the leading digit. -Also the digits are copied from the leading to the trailing edge. - -Once the window copy is complete the upper digits must be zeroed and the \textbf{used} count decremented. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_rshd.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The only noteworthy element of this routine is the lack of a return type since it cannot fail. Like mp\_lshd() we -form a sliding window except we copy in the other direction. After the window (line 60) we then zero -the upper digits of the input to make sure the result is correct. - -\section{Powers of Two} - -Now that algorithms for moving single bits as well as whole digits exist algorithms for moving the ``in between'' distances are required. For -example, to quickly multiply by $2^k$ for any $k$ without using a full multiplier algorithm would prove useful. Instead of performing single -shifts $k$ times to achieve a multiplication by $2^{\pm k}$ a mixture of whole digit shifting and partial digit shifting is employed. - -\subsection{Multiplication by Power of Two} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_mul\_2d}. \\ -\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ -\textbf{Output}. $c \leftarrow a \cdot 2^b$. \\ -\hline \\ -1. $c \leftarrow a$. (\textit{mp\_copy}) \\ -2. If $c.alloc < c.used + \lfloor b / lg(\beta) \rfloor + 2$ then grow $c$ accordingly. \\ -3. If the reallocation failed return(\textit{MP\_MEM}). \\ -4. If $b \ge lg(\beta)$ then \\ -\hspace{3mm}4.1 $c \leftarrow c \cdot \beta^{\lfloor b / lg(\beta) \rfloor}$ (\textit{mp\_lshd}). \\ -\hspace{3mm}4.2 If step 4.1 failed return(\textit{MP\_MEM}). \\ -5. $d \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ -6. If $d \ne 0$ then do \\ -\hspace{3mm}6.1 $mask \leftarrow 2^d$ \\ -\hspace{3mm}6.2 $r \leftarrow 0$ \\ -\hspace{3mm}6.3 for $n$ from $0$ to $c.used - 1$ do \\ -\hspace{6mm}6.3.1 $rr \leftarrow c_n >> (lg(\beta) - d) \mbox{ (mod }mask\mbox{)}$ \\ -\hspace{6mm}6.3.2 $c_n \leftarrow (c_n << d) + r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{6mm}6.3.3 $r \leftarrow rr$ \\ -\hspace{3mm}6.4 If $r > 0$ then do \\ -\hspace{6mm}6.4.1 $c_{c.used} \leftarrow r$ \\ -\hspace{6mm}6.4.2 $c.used \leftarrow c.used + 1$ \\ -7. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_mul\_2d} -\end{figure} - -\textbf{Algorithm mp\_mul\_2d.} -This algorithm multiplies $a$ by $2^b$ and stores the result in $c$. The algorithm uses algorithm mp\_lshd and a derivative of algorithm mp\_mul\_2 to -quickly compute the product. - -First the algorithm will multiply $a$ by $x^{\lfloor b / lg(\beta) \rfloor}$ which will ensure that the remainder multiplicand is less than -$\beta$. For example, if $b = 37$ and $\beta = 2^{28}$ then this step will multiply by $x$ leaving a multiplication by $2^{37 - 28} = 2^{9}$ -left. - -After the digits have been shifted appropriately at most $lg(\beta) - 1$ shifts are left to perform. Step 5 calculates the number of remaining shifts -required. If it is non-zero a modified shift loop is used to calculate the remaining product. -Essentially the loop is a generic version of algorithm mp\_mul\_2 designed to handle any shift count in the range $1 \le x < lg(\beta)$. The $mask$ -variable is used to extract the upper $d$ bits to form the carry for the next iteration. - -This algorithm is loosely measured as a $O(2n)$ algorithm which means that if the input is $n$-digits that it takes $2n$ ``time'' to -complete. It is possible to optimize this algorithm down to a $O(n)$ algorithm at a cost of making the algorithm slightly harder to follow. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_2d.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The shifting is performed in--place which means the first step (line 25) is to copy the input to the -destination. We avoid calling mp\_copy() by making sure the mp\_ints are different. The destination then -has to be grown (line 32) to accomodate the result. - -If the shift count $b$ is larger than $lg(\beta)$ then a call to mp\_lshd() is used to handle all of the multiples -of $lg(\beta)$. Leaving only a remaining shift of $lg(\beta) - 1$ or fewer bits left. Inside the actual shift -loop (lines 46 to 76) we make use of pre--computed values $shift$ and $mask$. These are used to -extract the carry bit(s) to pass into the next iteration of the loop. The $r$ and $rr$ variables form a -chain between consecutive iterations to propagate the carry. - -\subsection{Division by Power of Two} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_div\_2d}. \\ -\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ -\textbf{Output}. $c \leftarrow \lfloor a / 2^b \rfloor, d \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\ -\hline \\ -1. If $b \le 0$ then do \\ -\hspace{3mm}1.1 $c \leftarrow a$ (\textit{mp\_copy}) \\ -\hspace{3mm}1.2 $d \leftarrow 0$ (\textit{mp\_zero}) \\ -\hspace{3mm}1.3 Return(\textit{MP\_OKAY}). \\ -2. $c \leftarrow a$ \\ -3. $d \leftarrow a \mbox{ (mod }2^b\mbox{)}$ (\textit{mp\_mod\_2d}) \\ -4. If $b \ge lg(\beta)$ then do \\ -\hspace{3mm}4.1 $c \leftarrow \lfloor c/\beta^{\lfloor b/lg(\beta) \rfloor} \rfloor$ (\textit{mp\_rshd}). \\ -5. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ -6. If $k \ne 0$ then do \\ -\hspace{3mm}6.1 $mask \leftarrow 2^k$ \\ -\hspace{3mm}6.2 $r \leftarrow 0$ \\ -\hspace{3mm}6.3 for $n$ from $c.used - 1$ to $0$ do \\ -\hspace{6mm}6.3.1 $rr \leftarrow c_n \mbox{ (mod }mask\mbox{)}$ \\ -\hspace{6mm}6.3.2 $c_n \leftarrow (c_n >> k) + (r << (lg(\beta) - k))$ \\ -\hspace{6mm}6.3.3 $r \leftarrow rr$ \\ -7. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\ -8. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_div\_2d} -\end{figure} - -\textbf{Algorithm mp\_div\_2d.} -This algorithm will divide an input $a$ by $2^b$ and produce the quotient and remainder. The algorithm is designed much like algorithm -mp\_mul\_2d by first using whole digit shifts then single precision shifts. This algorithm will also produce the remainder of the division -by using algorithm mp\_mod\_2d. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_2d.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The implementation of algorithm mp\_div\_2d is slightly different than the algorithm specifies. The remainder $d$ may be optionally -ignored by passing \textbf{NULL} as the pointer to the mp\_int variable. The temporary mp\_int variable $t$ is used to hold the -result of the remainder operation until the end. This allows $d$ and $a$ to represent the same mp\_int without modifying $a$ before -the quotient is obtained. - -The remainder of the source code is essentially the same as the source code for mp\_mul\_2d. The only significant difference is -the direction of the shifts. - -\subsection{Remainder of Division by Power of Two} - -The last algorithm in the series of polynomial basis power of two algorithms is calculating the remainder of division by $2^b$. This -algorithm benefits from the fact that in twos complement arithmetic $a \mbox{ (mod }2^b\mbox{)}$ is the same as $a$ AND $2^b - 1$. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_mod\_2d}. \\ -\textbf{Input}. One mp\_int $a$ and an integer $b$ \\ -\textbf{Output}. $c \leftarrow a \mbox{ (mod }2^b\mbox{)}$. \\ -\hline \\ -1. If $b \le 0$ then do \\ -\hspace{3mm}1.1 $c \leftarrow 0$ (\textit{mp\_zero}) \\ -\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ -2. If $b > a.used \cdot lg(\beta)$ then do \\ -\hspace{3mm}2.1 $c \leftarrow a$ (\textit{mp\_copy}) \\ -\hspace{3mm}2.2 Return the result of step 2.1. \\ -3. $c \leftarrow a$ \\ -4. If step 3 failed return(\textit{MP\_MEM}). \\ -5. for $n$ from $\lceil b / lg(\beta) \rceil$ to $c.used$ do \\ -\hspace{3mm}5.1 $c_n \leftarrow 0$ \\ -6. $k \leftarrow b \mbox{ (mod }lg(\beta)\mbox{)}$ \\ -7. $c_{\lfloor b / lg(\beta) \rfloor} \leftarrow c_{\lfloor b / lg(\beta) \rfloor} \mbox{ (mod }2^{k}\mbox{)}$. \\ -8. Clamp excess digits of $c$. (\textit{mp\_clamp}) \\ -9. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_mod\_2d} -\end{figure} - -\textbf{Algorithm mp\_mod\_2d.} -This algorithm will quickly calculate the value of $a \mbox{ (mod }2^b\mbox{)}$. First if $b$ is less than or equal to zero the -result is set to zero. If $b$ is greater than the number of bits in $a$ then it simply copies $a$ to $c$ and returns. Otherwise, $a$ -is copied to $b$, leading digits are removed and the remaining leading digit is trimed to the exact bit count. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_mod\_2d.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -We first avoid cases of $b \le 0$ by simply mp\_zero()'ing the destination in such cases. Next if $2^b$ is larger -than the input we just mp\_copy() the input and return right away. After this point we know we must actually -perform some work to produce the remainder. - -Recalling that reducing modulo $2^k$ and a binary ``and'' with $2^k - 1$ are numerically equivalent we can quickly reduce -the number. First we zero any digits above the last digit in $2^b$ (line 42). Next we reduce the -leading digit of both (line 46) and then mp\_clamp(). - -\section*{Exercises} -\begin{tabular}{cl} -$\left [ 3 \right ] $ & Devise an algorithm that performs $a \cdot 2^b$ for generic values of $b$ \\ - & in $O(n)$ time. \\ - &\\ -$\left [ 3 \right ] $ & Devise an efficient algorithm to multiply by small low hamming \\ - & weight values such as $3$, $5$ and $9$. Extend it to handle all values \\ - & upto $64$ with a hamming weight less than three. \\ - &\\ -$\left [ 2 \right ] $ & Modify the preceding algorithm to handle values of the form \\ - & $2^k - 1$ as well. \\ - &\\ -$\left [ 3 \right ] $ & Using only algorithms mp\_mul\_2, mp\_div\_2 and mp\_add create an \\ - & algorithm to multiply two integers in roughly $O(2n^2)$ time for \\ - & any $n$-bit input. Note that the time of addition is ignored in the \\ - & calculation. \\ - & \\ -$\left [ 5 \right ] $ & Improve the previous algorithm to have a working time of at most \\ - & $O \left (2^{(k-1)}n + \left ({2n^2 \over k} \right ) \right )$ for an appropriate choice of $k$. Again ignore \\ - & the cost of addition. \\ - & \\ -$\left [ 2 \right ] $ & Devise a chart to find optimal values of $k$ for the previous problem \\ - & for $n = 64 \ldots 1024$ in steps of $64$. \\ - & \\ -$\left [ 2 \right ] $ & Using only algorithms mp\_abs and mp\_sub devise another method for \\ - & calculating the result of a signed comparison. \\ - & -\end{tabular} - -\chapter{Multiplication and Squaring} -\section{The Multipliers} -For most number theoretic problems including certain public key cryptographic algorithms, the ``multipliers'' form the most important subset of -algorithms of any multiple precision integer package. The set of multiplier algorithms include integer multiplication, squaring and modular reduction -where in each of the algorithms single precision multiplication is the dominant operation performed. This chapter will discuss integer multiplication -and squaring, leaving modular reductions for the subsequent chapter. - -The importance of the multiplier algorithms is for the most part driven by the fact that certain popular public key algorithms are based on modular -exponentiation, that is computing $d \equiv a^b \mbox{ (mod }c\mbox{)}$ for some arbitrary choice of $a$, $b$, $c$ and $d$. During a modular -exponentiation the majority\footnote{Roughly speaking a modular exponentiation will spend about 40\% of the time performing modular reductions, -35\% of the time performing squaring and 25\% of the time performing multiplications.} of the processor time is spent performing single precision -multiplications. - -For centuries general purpose multiplication has required a lengthly $O(n^2)$ process, whereby each digit of one multiplicand has to be multiplied -against every digit of the other multiplicand. Traditional long-hand multiplication is based on this process; while the techniques can differ the -overall algorithm used is essentially the same. Only ``recently'' have faster algorithms been studied. First Karatsuba multiplication was discovered in -1962. This algorithm can multiply two numbers with considerably fewer single precision multiplications when compared to the long-hand approach. -This technique led to the discovery of polynomial basis algorithms (\textit{good reference?}) and subquently Fourier Transform based solutions. - -\section{Multiplication} -\subsection{The Baseline Multiplication} -\label{sec:basemult} -\index{baseline multiplication} -Computing the product of two integers in software can be achieved using a trivial adaptation of the standard $O(n^2)$ long-hand multiplication -algorithm that school children are taught. The algorithm is considered an $O(n^2)$ algorithm since for two $n$-digit inputs $n^2$ single precision -multiplications are required. More specifically for a $m$ and $n$ digit input $m \cdot n$ single precision multiplications are required. To -simplify most discussions, it will be assumed that the inputs have comparable number of digits. - -The ``baseline multiplication'' algorithm is designed to act as the ``catch-all'' algorithm, only to be used when the faster algorithms cannot be -used. This algorithm does not use any particularly interesting optimizations and should ideally be avoided if possible. One important -facet of this algorithm, is that it has been modified to only produce a certain amount of output digits as resolution. The importance of this -modification will become evident during the discussion of Barrett modular reduction. Recall that for a $n$ and $m$ digit input the product -will be at most $n + m$ digits. Therefore, this algorithm can be reduced to a full multiplier by having it produce $n + m$ digits of the product. - -Recall from sub-section 4.2.2 the definition of $\gamma$ as the number of bits in the type \textbf{mp\_digit}. We shall now extend the variable set to -include $\alpha$ which shall represent the number of bits in the type \textbf{mp\_word}. This implies that $2^{\alpha} > 2 \cdot \beta^2$. The -constant $\delta = 2^{\alpha - 2lg(\beta)}$ will represent the maximal weight of any column in a product (\textit{see sub-section 5.2.2 for more information}). - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_mul\_digs}. \\ -\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\ -\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\ -\hline \\ -1. If min$(a.used, b.used) < \delta$ then do \\ -\hspace{3mm}1.1 Calculate $c = \vert a \vert \cdot \vert b \vert$ by the Comba method (\textit{see algorithm~\ref{fig:COMBAMULT}}). \\ -\hspace{3mm}1.2 Return the result of step 1.1 \\ -\\ -Allocate and initialize a temporary mp\_int. \\ -2. Init $t$ to be of size $digs$ \\ -3. If step 2 failed return(\textit{MP\_MEM}). \\ -4. $t.used \leftarrow digs$ \\ -\\ -Compute the product. \\ -5. for $ix$ from $0$ to $a.used - 1$ do \\ -\hspace{3mm}5.1 $u \leftarrow 0$ \\ -\hspace{3mm}5.2 $pb \leftarrow \mbox{min}(b.used, digs - ix)$ \\ -\hspace{3mm}5.3 If $pb < 1$ then goto step 6. \\ -\hspace{3mm}5.4 for $iy$ from $0$ to $pb - 1$ do \\ -\hspace{6mm}5.4.1 $\hat r \leftarrow t_{iy + ix} + a_{ix} \cdot b_{iy} + u$ \\ -\hspace{6mm}5.4.2 $t_{iy + ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{6mm}5.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -\hspace{3mm}5.5 if $ix + pb < digs$ then do \\ -\hspace{6mm}5.5.1 $t_{ix + pb} \leftarrow u$ \\ -6. Clamp excess digits of $t$. \\ -7. Swap $c$ with $t$ \\ -8. Clear $t$ \\ -9. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm s\_mp\_mul\_digs} -\end{figure} - -\textbf{Algorithm s\_mp\_mul\_digs.} -This algorithm computes the unsigned product of two inputs $a$ and $b$, limited to an output precision of $digs$ digits. While it may seem -a bit awkward to modify the function from its simple $O(n^2)$ description, the usefulness of partial multipliers will arise in a subsequent -algorithm. The algorithm is loosely based on algorithm 14.12 from \cite[pp. 595]{HAC} and is similar to Algorithm M of Knuth \cite[pp. 268]{TAOCPV2}. -Algorithm s\_mp\_mul\_digs differs from these cited references since it can produce a variable output precision regardless of the precision of the -inputs. - -The first thing this algorithm checks for is whether a Comba multiplier can be used instead. If the minimum digit count of either -input is less than $\delta$, then the Comba method may be used instead. After the Comba method is ruled out, the baseline algorithm begins. A -temporary mp\_int variable $t$ is used to hold the intermediate result of the product. This allows the algorithm to be used to -compute products when either $a = c$ or $b = c$ without overwriting the inputs. - -All of step 5 is the infamous $O(n^2)$ multiplication loop slightly modified to only produce upto $digs$ digits of output. The $pb$ variable -is given the count of digits to read from $b$ inside the nested loop. If $pb \le 1$ then no more output digits can be produced and the algorithm -will exit the loop. The best way to think of the loops are as a series of $pb \times 1$ multiplications. That is, in each pass of the -innermost loop $a_{ix}$ is multiplied against $b$ and the result is added (\textit{with an appropriate shift}) to $t$. - -For example, consider multiplying $576$ by $241$. That is equivalent to computing $10^0(1)(576) + 10^1(4)(576) + 10^2(2)(576)$ which is best -visualized in the following table. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{|c|c|c|c|c|c|l|} -\hline && & 5 & 7 & 6 & \\ -\hline $\times$&& & 2 & 4 & 1 & \\ -\hline &&&&&&\\ - && & 5 & 7 & 6 & $10^0(1)(576)$ \\ - &2 & 3 & 6 & 1 & 6 & $10^1(4)(576) + 10^0(1)(576)$ \\ - 1 & 3 & 8 & 8 & 1 & 6 & $10^2(2)(576) + 10^1(4)(576) + 10^0(1)(576)$ \\ -\hline -\end{tabular} -\end{center} -\caption{Long-Hand Multiplication Diagram} -\end{figure} - -Each row of the product is added to the result after being shifted to the left (\textit{multiplied by a power of the radix}) by the appropriate -count. That is in pass $ix$ of the inner loop the product is added starting at the $ix$'th digit of the reult. - -Step 5.4.1 introduces the hat symbol (\textit{e.g. $\hat r$}) which represents a double precision variable. The multiplication on that step -is assumed to be a double wide output single precision multiplication. That is, two single precision variables are multiplied to produce a -double precision result. The step is somewhat optimized from a long-hand multiplication algorithm because the carry from the addition in step -5.4.1 is propagated through the nested loop. If the carry was not propagated immediately it would overflow the single precision digit -$t_{ix+iy}$ and the result would be lost. - -At step 5.5 the nested loop is finished and any carry that was left over should be forwarded. The carry does not have to be added to the $ix+pb$'th -digit since that digit is assumed to be zero at this point. However, if $ix + pb \ge digs$ the carry is not set as it would make the result -exceed the precision requested. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_mul\_digs.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -First we determine (line 31) if the Comba method can be used first since it's faster. The conditions for -sing the Comba routine are that min$(a.used, b.used) < \delta$ and the number of digits of output is less than -\textbf{MP\_WARRAY}. This new constant is used to control the stack usage in the Comba routines. By default it is -set to $\delta$ but can be reduced when memory is at a premium. - -If we cannot use the Comba method we proceed to setup the baseline routine. We allocate the the destination mp\_int -$t$ (line 37) to the exact size of the output to avoid further re--allocations. At this point we now -begin the $O(n^2)$ loop. - -This implementation of multiplication has the caveat that it can be trimmed to only produce a variable number of -digits as output. In each iteration of the outer loop the $pb$ variable is set (line 49) to the maximum -number of inner loop iterations. - -Inside the inner loop we calculate $\hat r$ as the mp\_word product of the two mp\_digits and the addition of the -carry from the previous iteration. A particularly important observation is that most modern optimizing -C compilers (GCC for instance) can recognize that a $N \times N \rightarrow 2N$ multiplication is all that -is required for the product. In x86 terms for example, this means using the MUL instruction. - -Each digit of the product is stored in turn (line 69) and the carry propagated (line 72) to the -next iteration. - -\subsection{Faster Multiplication by the ``Comba'' Method} - -One of the huge drawbacks of the ``baseline'' algorithms is that at the $O(n^2)$ level the carry must be -computed and propagated upwards. This makes the nested loop very sequential and hard to unroll and implement -in parallel. The ``Comba'' \cite{COMBA} method is named after little known (\textit{in cryptographic venues}) Paul G. -Comba who described a method of implementing fast multipliers that do not require nested carry fixup operations. As an -interesting aside it seems that Paul Barrett describes a similar technique in his 1986 paper \cite{BARRETT} written -five years before. - -At the heart of the Comba technique is once again the long-hand algorithm. Except in this case a slight -twist is placed on how the columns of the result are produced. In the standard long-hand algorithm rows of products -are produced then added together to form the final result. In the baseline algorithm the columns are added together -after each iteration to get the result instantaneously. - -In the Comba algorithm the columns of the result are produced entirely independently of each other. That is at -the $O(n^2)$ level a simple multiplication and addition step is performed. The carries of the columns are propagated -after the nested loop to reduce the amount of work requiored. Succintly the first step of the algorithm is to compute -the product vector $\vec x$ as follows. - -\begin{equation} -\vec x_n = \sum_{i+j = n} a_ib_j, \forall n \in \lbrace 0, 1, 2, \ldots, i + j \rbrace -\end{equation} - -Where $\vec x_n$ is the $n'th$ column of the output vector. Consider the following example which computes the vector $\vec x$ for the multiplication -of $576$ and $241$. - -\newpage\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{|c|c|c|c|c|c|} - \hline & & 5 & 7 & 6 & First Input\\ - \hline $\times$ & & 2 & 4 & 1 & Second Input\\ -\hline & & $1 \cdot 5 = 5$ & $1 \cdot 7 = 7$ & $1 \cdot 6 = 6$ & First pass \\ - & $4 \cdot 5 = 20$ & $4 \cdot 7+5=33$ & $4 \cdot 6+7=31$ & 6 & Second pass \\ - $2 \cdot 5 = 10$ & $2 \cdot 7 + 20 = 34$ & $2 \cdot 6+33=45$ & 31 & 6 & Third pass \\ -\hline 10 & 34 & 45 & 31 & 6 & Final Result \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Comba Multiplication Diagram} -\end{figure} - -At this point the vector $x = \left < 10, 34, 45, 31, 6 \right >$ is the result of the first step of the Comba multipler. -Now the columns must be fixed by propagating the carry upwards. The resultant vector will have one extra dimension over the input vector which is -congruent to adding a leading zero digit. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Comba Fixup}. \\ -\textbf{Input}. Vector $\vec x$ of dimension $k$ \\ -\textbf{Output}. Vector $\vec x$ such that the carries have been propagated. \\ -\hline \\ -1. for $n$ from $0$ to $k - 1$ do \\ -\hspace{3mm}1.1 $\vec x_{n+1} \leftarrow \vec x_{n+1} + \lfloor \vec x_{n}/\beta \rfloor$ \\ -\hspace{3mm}1.2 $\vec x_{n} \leftarrow \vec x_{n} \mbox{ (mod }\beta\mbox{)}$ \\ -2. Return($\vec x$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Comba Fixup} -\end{figure} - -With that algorithm and $k = 5$ and $\beta = 10$ the following vector is produced $\vec x= \left < 1, 3, 8, 8, 1, 6 \right >$. In this case -$241 \cdot 576$ is in fact $138816$ and the procedure succeeded. If the algorithm is correct and as will be demonstrated shortly more -efficient than the baseline algorithm why not simply always use this algorithm? - -\subsubsection{Column Weight.} -At the nested $O(n^2)$ level the Comba method adds the product of two single precision variables to each column of the output -independently. A serious obstacle is if the carry is lost, due to lack of precision before the algorithm has a chance to fix -the carries. For example, in the multiplication of two three-digit numbers the third column of output will be the sum of -three single precision multiplications. If the precision of the accumulator for the output digits is less then $3 \cdot (\beta - 1)^2$ then -an overflow can occur and the carry information will be lost. For any $m$ and $n$ digit inputs the maximum weight of any column is -min$(m, n)$ which is fairly obvious. - -The maximum number of terms in any column of a product is known as the ``column weight'' and strictly governs when the algorithm can be used. Recall -from earlier that a double precision type has $\alpha$ bits of resolution and a single precision digit has $lg(\beta)$ bits of precision. Given these -two quantities we must not violate the following - -\begin{equation} -k \cdot \left (\beta - 1 \right )^2 < 2^{\alpha} -\end{equation} - -Which reduces to - -\begin{equation} -k \cdot \left ( \beta^2 - 2\beta + 1 \right ) < 2^{\alpha} -\end{equation} - -Let $\rho = lg(\beta)$ represent the number of bits in a single precision digit. By further re-arrangement of the equation the final solution is -found. - -\begin{equation} -k < {{2^{\alpha}} \over {\left (2^{2\rho} - 2^{\rho + 1} + 1 \right )}} -\end{equation} - -The defaults for LibTomMath are $\beta = 2^{28}$ and $\alpha = 2^{64}$ which means that $k$ is bounded by $k < 257$. In this configuration -the smaller input may not have more than $256$ digits if the Comba method is to be used. This is quite satisfactory for most applications since -$256$ digits would allow for numbers in the range of $0 \le x < 2^{7168}$ which, is much larger than most public key cryptographic algorithms require. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{fast\_s\_mp\_mul\_digs}. \\ -\textbf{Input}. mp\_int $a$, mp\_int $b$ and an integer $digs$ \\ -\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert \mbox{ (mod }\beta^{digs}\mbox{)}$. \\ -\hline \\ -Place an array of \textbf{MP\_WARRAY} single precision digits named $W$ on the stack. \\ -1. If $c.alloc < digs$ then grow $c$ to $digs$ digits. (\textit{mp\_grow}) \\ -2. If step 1 failed return(\textit{MP\_MEM}).\\ -\\ -3. $pa \leftarrow \mbox{MIN}(digs, a.used + b.used)$ \\ -\\ -4. $\_ \hat W \leftarrow 0$ \\ -5. for $ix$ from 0 to $pa - 1$ do \\ -\hspace{3mm}5.1 $ty \leftarrow \mbox{MIN}(b.used - 1, ix)$ \\ -\hspace{3mm}5.2 $tx \leftarrow ix - ty$ \\ -\hspace{3mm}5.3 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\ -\hspace{3mm}5.4 for $iz$ from 0 to $iy - 1$ do \\ -\hspace{6mm}5.4.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx+iy}b_{ty-iy}$ \\ -\hspace{3mm}5.5 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$\\ -\hspace{3mm}5.6 $\_ \hat W \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\ -\\ -6. $oldused \leftarrow c.used$ \\ -7. $c.used \leftarrow digs$ \\ -8. for $ix$ from $0$ to $pa$ do \\ -\hspace{3mm}8.1 $c_{ix} \leftarrow W_{ix}$ \\ -9. for $ix$ from $pa + 1$ to $oldused - 1$ do \\ -\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\ -\\ -10. Clamp $c$. \\ -11. Return MP\_OKAY. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm fast\_s\_mp\_mul\_digs} -\label{fig:COMBAMULT} -\end{figure} - -\textbf{Algorithm fast\_s\_mp\_mul\_digs.} -This algorithm performs the unsigned multiplication of $a$ and $b$ using the Comba method limited to $digs$ digits of precision. - -The outer loop of this algorithm is more complicated than that of the baseline multiplier. This is because on the inside of the -loop we want to produce one column per pass. This allows the accumulator $\_ \hat W$ to be placed in CPU registers and -reduce the memory bandwidth to two \textbf{mp\_digit} reads per iteration. - -The $ty$ variable is set to the minimum count of $ix$ or the number of digits in $b$. That way if $a$ has more digits than -$b$ this will be limited to $b.used - 1$. The $tx$ variable is set to the to the distance past $b.used$ the variable -$ix$ is. This is used for the immediately subsequent statement where we find $iy$. - -The variable $iy$ is the minimum digits we can read from either $a$ or $b$ before running out. Computing one column at a time -means we have to scan one integer upwards and the other downwards. $a$ starts at $tx$ and $b$ starts at $ty$. In each -pass we are producing the $ix$'th output column and we note that $tx + ty = ix$. As we move $tx$ upwards we have to -move $ty$ downards so the equality remains valid. The $iy$ variable is the number of iterations until -$tx \ge a.used$ or $ty < 0$ occurs. - -After every inner pass we store the lower half of the accumulator into $W_{ix}$ and then propagate the carry of the accumulator -into the next round by dividing $\_ \hat W$ by $\beta$. - -To measure the benefits of the Comba method over the baseline method consider the number of operations that are required. If the -cost in terms of time of a multiply and addition is $p$ and the cost of a carry propagation is $q$ then a baseline multiplication would require -$O \left ((p + q)n^2 \right )$ time to multiply two $n$-digit numbers. The Comba method requires only $O(pn^2 + qn)$ time, however in practice, -the speed increase is actually much more. With $O(n)$ space the algorithm can be reduced to $O(pn + qn)$ time by implementing the $n$ multiply -and addition operations in the nested loop in parallel. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_mul\_digs.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -As per the pseudo--code we first calculate $pa$ (line 48) as the number of digits to output. Next we begin the outer loop -to produce the individual columns of the product. We use the two aliases $tmpx$ and $tmpy$ (lines 62, 63) to point -inside the two multiplicands quickly. - -The inner loop (lines 71 to 74) of this implementation is where the tradeoff come into play. Originally this comba -implementation was ``row--major'' which means it adds to each of the columns in each pass. After the outer loop it would then fix -the carries. This was very fast except it had an annoying drawback. You had to read a mp\_word and two mp\_digits and write -one mp\_word per iteration. On processors such as the Athlon XP and P4 this did not matter much since the cache bandwidth -is very high and it can keep the ALU fed with data. It did, however, matter on older and embedded cpus where cache is often -slower and also often doesn't exist. This new algorithm only performs two reads per iteration under the assumption that the -compiler has aliased $\_ \hat W$ to a CPU register. - -After the inner loop we store the current accumulator in $W$ and shift $\_ \hat W$ (lines 77, 80) to forward it as -a carry for the next pass. After the outer loop we use the final carry (line 77) as the last digit of the product. - -\subsection{Polynomial Basis Multiplication} -To break the $O(n^2)$ barrier in multiplication requires a completely different look at integer multiplication. In the following algorithms -the use of polynomial basis representation for two integers $a$ and $b$ as $f(x) = \sum_{i=0}^{n} a_i x^i$ and -$g(x) = \sum_{i=0}^{n} b_i x^i$ respectively, is required. In this system both $f(x)$ and $g(x)$ have $n + 1$ terms and are of the $n$'th degree. - -The product $a \cdot b \equiv f(x)g(x)$ is the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$. The coefficients $w_i$ will -directly yield the desired product when $\beta$ is substituted for $x$. The direct solution to solve for the $2n + 1$ coefficients -requires $O(n^2)$ time and would in practice be slower than the Comba technique. - -However, numerical analysis theory indicates that only $2n + 1$ distinct points in $W(x)$ are required to determine the values of the $2n + 1$ unknown -coefficients. This means by finding $\zeta_y = W(y)$ for $2n + 1$ small values of $y$ the coefficients of $W(x)$ can be found with -Gaussian elimination. This technique is also occasionally refered to as the \textit{interpolation technique} (\textit{references please...}) since in -effect an interpolation based on $2n + 1$ points will yield a polynomial equivalent to $W(x)$. - -The coefficients of the polynomial $W(x)$ are unknown which makes finding $W(y)$ for any value of $y$ impossible. However, since -$W(x) = f(x)g(x)$ the equivalent $\zeta_y = f(y) g(y)$ can be used in its place. The benefit of this technique stems from the -fact that $f(y)$ and $g(y)$ are much smaller than either $a$ or $b$ respectively. As a result finding the $2n + 1$ relations required -by multiplying $f(y)g(y)$ involves multiplying integers that are much smaller than either of the inputs. - -When picking points to gather relations there are always three obvious points to choose, $y = 0, 1$ and $ \infty$. The $\zeta_0$ term -is simply the product $W(0) = w_0 = a_0 \cdot b_0$. The $\zeta_1$ term is the product -$W(1) = \left (\sum_{i = 0}^{n} a_i \right ) \left (\sum_{i = 0}^{n} b_i \right )$. The third point $\zeta_{\infty}$ is less obvious but rather -simple to explain. The $2n + 1$'th coefficient of $W(x)$ is numerically equivalent to the most significant column in an integer multiplication. -The point at $\infty$ is used symbolically to represent the most significant column, that is $W(\infty) = w_{2n} = a_nb_n$. Note that the -points at $y = 0$ and $\infty$ yield the coefficients $w_0$ and $w_{2n}$ directly. - -If more points are required they should be of small values and powers of two such as $2^q$ and the related \textit{mirror points} -$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ for small values of $q$. The term ``mirror point'' stems from the fact that -$\left (2^q \right )^{2n} \cdot \zeta_{2^{-q}}$ can be calculated in the exact opposite fashion as $\zeta_{2^q}$. For -example, when $n = 2$ and $q = 1$ then following two equations are equivalent to the point $\zeta_{2}$ and its mirror. - -\begin{eqnarray} -\zeta_{2} = f(2)g(2) = (4a_2 + 2a_1 + a_0)(4b_2 + 2b_1 + b_0) \nonumber \\ -16 \cdot \zeta_{1 \over 2} = 4f({1\over 2}) \cdot 4g({1 \over 2}) = (a_2 + 2a_1 + 4a_0)(b_2 + 2b_1 + 4b_0) -\end{eqnarray} - -Using such points will allow the values of $f(y)$ and $g(y)$ to be independently calculated using only left shifts. For example, when $n = 2$ the -polynomial $f(2^q)$ is equal to $2^q((2^qa_2) + a_1) + a_0$. This technique of polynomial representation is known as Horner's method. - -As a general rule of the algorithm when the inputs are split into $n$ parts each there are $2n - 1$ multiplications. Each multiplication is of -multiplicands that have $n$ times fewer digits than the inputs. The asymptotic running time of this algorithm is -$O \left ( k^{lg_n(2n - 1)} \right )$ for $k$ digit inputs (\textit{assuming they have the same number of digits}). Figure~\ref{fig:exponent} -summarizes the exponents for various values of $n$. - -\begin{figure} -\begin{center} -\begin{tabular}{|c|c|c|} -\hline \textbf{Split into $n$ Parts} & \textbf{Exponent} & \textbf{Notes}\\ -\hline $2$ & $1.584962501$ & This is Karatsuba Multiplication. \\ -\hline $3$ & $1.464973520$ & This is Toom-Cook Multiplication. \\ -\hline $4$ & $1.403677461$ &\\ -\hline $5$ & $1.365212389$ &\\ -\hline $10$ & $1.278753601$ &\\ -\hline $100$ & $1.149426538$ &\\ -\hline $1000$ & $1.100270931$ &\\ -\hline $10000$ & $1.075252070$ &\\ -\hline -\end{tabular} -\end{center} -\caption{Asymptotic Running Time of Polynomial Basis Multiplication} -\label{fig:exponent} -\end{figure} - -At first it may seem like a good idea to choose $n = 1000$ since the exponent is approximately $1.1$. However, the overhead -of solving for the 2001 terms of $W(x)$ will certainly consume any savings the algorithm could offer for all but exceedingly large -numbers. - -\subsubsection{Cutoff Point} -The polynomial basis multiplication algorithms all require fewer single precision multiplications than a straight Comba approach. However, -the algorithms incur an overhead (\textit{at the $O(n)$ work level}) since they require a system of equations to be solved. This makes the -polynomial basis approach more costly to use with small inputs. - -Let $m$ represent the number of digits in the multiplicands (\textit{assume both multiplicands have the same number of digits}). There exists a -point $y$ such that when $m < y$ the polynomial basis algorithms are more costly than Comba, when $m = y$ they are roughly the same cost and -when $m > y$ the Comba methods are slower than the polynomial basis algorithms. - -The exact location of $y$ depends on several key architectural elements of the computer platform in question. - -\begin{enumerate} -\item The ratio of clock cycles for single precision multiplication versus other simpler operations such as addition, shifting, etc. For example -on the AMD Athlon the ratio is roughly $17 : 1$ while on the Intel P4 it is $29 : 1$. The higher the ratio in favour of multiplication the lower -the cutoff point $y$ will be. - -\item The complexity of the linear system of equations (\textit{for the coefficients of $W(x)$}) is. Generally speaking as the number of splits -grows the complexity grows substantially. Ideally solving the system will only involve addition, subtraction and shifting of integers. This -directly reflects on the ratio previous mentioned. - -\item To a lesser extent memory bandwidth and function call overheads. Provided the values are in the processor cache this is less of an -influence over the cutoff point. - -\end{enumerate} - -A clean cutoff point separation occurs when a point $y$ is found such that all of the cutoff point conditions are met. For example, if the point -is too low then there will be values of $m$ such that $m > y$ and the Comba method is still faster. Finding the cutoff points is fairly simple when -a high resolution timer is available. - -\subsection{Karatsuba Multiplication} -Karatsuba \cite{KARA} multiplication when originally proposed in 1962 was among the first set of algorithms to break the $O(n^2)$ barrier for -general purpose multiplication. Given two polynomial basis representations $f(x) = ax + b$ and $g(x) = cx + d$, Karatsuba proved with -light algebra \cite{KARAP} that the following polynomial is equivalent to multiplication of the two integers the polynomials represent. - -\begin{equation} -f(x) \cdot g(x) = acx^2 + ((a + b)(c + d) - (ac + bd))x + bd -\end{equation} - -Using the observation that $ac$ and $bd$ could be re-used only three half sized multiplications would be required to produce the product. Applying -this algorithm recursively, the work factor becomes $O(n^{lg(3)})$ which is substantially better than the work factor $O(n^2)$ of the Comba technique. It turns -out what Karatsuba did not know or at least did not publish was that this is simply polynomial basis multiplication with the points -$\zeta_0$, $\zeta_{\infty}$ and $\zeta_{1}$. Consider the resultant system of equations. - -\begin{center} -\begin{tabular}{rcrcrcrc} -$\zeta_{0}$ & $=$ & & & & & $w_0$ \\ -$\zeta_{1}$ & $=$ & $w_2$ & $+$ & $w_1$ & $+$ & $w_0$ \\ -$\zeta_{\infty}$ & $=$ & $w_2$ & & & & \\ -\end{tabular} -\end{center} - -By adding the first and last equation to the equation in the middle the term $w_1$ can be isolated and all three coefficients solved for. The simplicity -of this system of equations has made Karatsuba fairly popular. In fact the cutoff point is often fairly low\footnote{With LibTomMath 0.18 it is 70 and 109 digits for the Intel P4 and AMD Athlon respectively.} -making it an ideal algorithm to speed up certain public key cryptosystems such as RSA and Diffie-Hellman. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_karatsuba\_mul}. \\ -\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ -\textbf{Output}. $c \leftarrow \vert a \vert \cdot \vert b \vert$ \\ -\hline \\ -1. Init the following mp\_int variables: $x0$, $x1$, $y0$, $y1$, $t1$, $x0y0$, $x1y1$.\\ -2. If step 2 failed then return(\textit{MP\_MEM}). \\ -\\ -Split the input. e.g. $a = x1 \cdot \beta^B + x0$ \\ -3. $B \leftarrow \mbox{min}(a.used, b.used)/2$ \\ -4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\ -5. $y0 \leftarrow b \mbox{ (mod }\beta^B\mbox{)}$ \\ -6. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_rshd}) \\ -7. $y1 \leftarrow \lfloor b / \beta^B \rfloor$ \\ -\\ -Calculate the three products. \\ -8. $x0y0 \leftarrow x0 \cdot y0$ (\textit{mp\_mul}) \\ -9. $x1y1 \leftarrow x1 \cdot y1$ \\ -10. $t1 \leftarrow x1 + x0$ (\textit{mp\_add}) \\ -11. $x0 \leftarrow y1 + y0$ \\ -12. $t1 \leftarrow t1 \cdot x0$ \\ -\\ -Calculate the middle term. \\ -13. $x0 \leftarrow x0y0 + x1y1$ \\ -14. $t1 \leftarrow t1 - x0$ (\textit{s\_mp\_sub}) \\ -\\ -Calculate the final product. \\ -15. $t1 \leftarrow t1 \cdot \beta^B$ (\textit{mp\_lshd}) \\ -16. $x1y1 \leftarrow x1y1 \cdot \beta^{2B}$ \\ -17. $t1 \leftarrow x0y0 + t1$ \\ -18. $c \leftarrow t1 + x1y1$ \\ -19. Clear all of the temporary variables. \\ -20. Return(\textit{MP\_OKAY}).\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_karatsuba\_mul} -\end{figure} - -\textbf{Algorithm mp\_karatsuba\_mul.} -This algorithm computes the unsigned product of two inputs using the Karatsuba multiplication algorithm. It is loosely based on the description -from Knuth \cite[pp. 294-295]{TAOCPV2}. - -\index{radix point} -In order to split the two inputs into their respective halves, a suitable \textit{radix point} must be chosen. The radix point chosen must -be used for both of the inputs meaning that it must be smaller than the smallest input. Step 3 chooses the radix point $B$ as half of the -smallest input \textbf{used} count. After the radix point is chosen the inputs are split into lower and upper halves. Step 4 and 5 -compute the lower halves. Step 6 and 7 computer the upper halves. - -After the halves have been computed the three intermediate half-size products must be computed. Step 8 and 9 compute the trivial products -$x0 \cdot y0$ and $x1 \cdot y1$. The mp\_int $x0$ is used as a temporary variable after $x1 + x0$ has been computed. By using $x0$ instead -of an additional temporary variable, the algorithm can avoid an addition memory allocation operation. - -The remaining steps 13 through 18 compute the Karatsuba polynomial through a variety of digit shifting and addition operations. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_mul.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The new coding element in this routine, not seen in previous routines, is the usage of goto statements. The conventional -wisdom is that goto statements should be avoided. This is generally true, however when every single function call can fail, it makes sense -to handle error recovery with a single piece of code. Lines 62 to 76 handle initializing all of the temporary variables -required. Note how each of the if statements goes to a different label in case of failure. This allows the routine to correctly free only -the temporaries that have been successfully allocated so far. - -The temporary variables are all initialized using the mp\_init\_size routine since they are expected to be large. This saves the -additional reallocation that would have been necessary. Also $x0$, $x1$, $y0$ and $y1$ have to be able to hold at least their respective -number of digits for the next section of code. - -The first algebraic portion of the algorithm is to split the two inputs into their halves. However, instead of using mp\_mod\_2d and mp\_rshd -to extract the halves, the respective code has been placed inline within the body of the function. To initialize the halves, the \textbf{used} and -\textbf{sign} members are copied first. The first for loop on line 96 copies the lower halves. Since they are both the same magnitude it -is simpler to calculate both lower halves in a single loop. The for loop on lines 102 and 107 calculate the upper halves $x1$ and -$y1$ respectively. - -By inlining the calculation of the halves, the Karatsuba multiplier has a slightly lower overhead and can be used for smaller magnitude inputs. - -When line 151 is reached, the algorithm has completed succesfully. The ``error status'' variable $err$ is set to \textbf{MP\_OKAY} so that -the same code that handles errors can be used to clear the temporary variables and return. - -\subsection{Toom-Cook $3$-Way Multiplication} -Toom-Cook $3$-Way \cite{TOOM} multiplication is essentially the polynomial basis algorithm for $n = 2$ except that the points are -chosen such that $\zeta$ is easy to compute and the resulting system of equations easy to reduce. Here, the points $\zeta_{0}$, -$16 \cdot \zeta_{1 \over 2}$, $\zeta_1$, $\zeta_2$ and $\zeta_{\infty}$ make up the five required points to solve for the coefficients -of the $W(x)$. - -With the five relations that Toom-Cook specifies, the following system of equations is formed. - -\begin{center} -\begin{tabular}{rcrcrcrcrcr} -$\zeta_0$ & $=$ & $0w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $1w_0$ \\ -$16 \cdot \zeta_{1 \over 2}$ & $=$ & $1w_4$ & $+$ & $2w_3$ & $+$ & $4w_2$ & $+$ & $8w_1$ & $+$ & $16w_0$ \\ -$\zeta_1$ & $=$ & $1w_4$ & $+$ & $1w_3$ & $+$ & $1w_2$ & $+$ & $1w_1$ & $+$ & $1w_0$ \\ -$\zeta_2$ & $=$ & $16w_4$ & $+$ & $8w_3$ & $+$ & $4w_2$ & $+$ & $2w_1$ & $+$ & $1w_0$ \\ -$\zeta_{\infty}$ & $=$ & $1w_4$ & $+$ & $0w_3$ & $+$ & $0w_2$ & $+$ & $0w_1$ & $+$ & $0w_0$ \\ -\end{tabular} -\end{center} - -A trivial solution to this matrix requires $12$ subtractions, two multiplications by a small power of two, two divisions by a small power -of two, two divisions by three and one multiplication by three. All of these $19$ sub-operations require less than quadratic time, meaning that -the algorithm can be faster than a baseline multiplication. However, the greater complexity of this algorithm places the cutoff point -(\textbf{TOOM\_MUL\_CUTOFF}) where Toom-Cook becomes more efficient much higher than the Karatsuba cutoff point. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_toom\_mul}. \\ -\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ -\textbf{Output}. $c \leftarrow a \cdot b $ \\ -\hline \\ -Split $a$ and $b$ into three pieces. E.g. $a = a_2 \beta^{2k} + a_1 \beta^{k} + a_0$ \\ -1. $k \leftarrow \lfloor \mbox{min}(a.used, b.used) / 3 \rfloor$ \\ -2. $a_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -3. $a_1 \leftarrow \lfloor a / \beta^k \rfloor$, $a_1 \leftarrow a_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -4. $a_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $a_2 \leftarrow a_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -5. $b_0 \leftarrow a \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -6. $b_1 \leftarrow \lfloor a / \beta^k \rfloor$, $b_1 \leftarrow b_1 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -7. $b_2 \leftarrow \lfloor a / \beta^{2k} \rfloor$, $b_2 \leftarrow b_2 \mbox{ (mod }\beta^{k}\mbox{)}$ \\ -\\ -Find the five equations for $w_0, w_1, ..., w_4$. \\ -8. $w_0 \leftarrow a_0 \cdot b_0$ \\ -9. $w_4 \leftarrow a_2 \cdot b_2$ \\ -10. $tmp_1 \leftarrow 2 \cdot a_0$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_2$ \\ -11. $tmp_2 \leftarrow 2 \cdot b_0$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_2$ \\ -12. $w_1 \leftarrow tmp_1 \cdot tmp_2$ \\ -13. $tmp_1 \leftarrow 2 \cdot a_2$, $tmp_1 \leftarrow a_1 + tmp_1$, $tmp_1 \leftarrow 2 \cdot tmp_1$, $tmp_1 \leftarrow tmp_1 + a_0$ \\ -14. $tmp_2 \leftarrow 2 \cdot b_2$, $tmp_2 \leftarrow b_1 + tmp_2$, $tmp_2 \leftarrow 2 \cdot tmp_2$, $tmp_2 \leftarrow tmp_2 + b_0$ \\ -15. $w_3 \leftarrow tmp_1 \cdot tmp_2$ \\ -16. $tmp_1 \leftarrow a_0 + a_1$, $tmp_1 \leftarrow tmp_1 + a_2$, $tmp_2 \leftarrow b_0 + b_1$, $tmp_2 \leftarrow tmp_2 + b_2$ \\ -17. $w_2 \leftarrow tmp_1 \cdot tmp_2$ \\ -\\ -Continued on the next page.\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_toom\_mul} -\end{figure} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_toom\_mul} (continued). \\ -\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ -\textbf{Output}. $c \leftarrow a \cdot b $ \\ -\hline \\ -Now solve the system of equations. \\ -18. $w_1 \leftarrow w_4 - w_1$, $w_3 \leftarrow w_3 - w_0$ \\ -19. $w_1 \leftarrow \lfloor w_1 / 2 \rfloor$, $w_3 \leftarrow \lfloor w_3 / 2 \rfloor$ \\ -20. $w_2 \leftarrow w_2 - w_0$, $w_2 \leftarrow w_2 - w_4$ \\ -21. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\ -22. $tmp_1 \leftarrow 8 \cdot w_0$, $w_1 \leftarrow w_1 - tmp_1$, $tmp_1 \leftarrow 8 \cdot w_4$, $w_3 \leftarrow w_3 - tmp_1$ \\ -23. $w_2 \leftarrow 3 \cdot w_2$, $w_2 \leftarrow w_2 - w_1$, $w_2 \leftarrow w_2 - w_3$ \\ -24. $w_1 \leftarrow w_1 - w_2$, $w_3 \leftarrow w_3 - w_2$ \\ -25. $w_1 \leftarrow \lfloor w_1 / 3 \rfloor, w_3 \leftarrow \lfloor w_3 / 3 \rfloor$ \\ -\\ -Now substitute $\beta^k$ for $x$ by shifting $w_0, w_1, ..., w_4$. \\ -26. for $n$ from $1$ to $4$ do \\ -\hspace{3mm}26.1 $w_n \leftarrow w_n \cdot \beta^{nk}$ \\ -27. $c \leftarrow w_0 + w_1$, $c \leftarrow c + w_2$, $c \leftarrow c + w_3$, $c \leftarrow c + w_4$ \\ -28. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_toom\_mul (continued)} -\end{figure} - -\textbf{Algorithm mp\_toom\_mul.} -This algorithm computes the product of two mp\_int variables $a$ and $b$ using the Toom-Cook approach. Compared to the Karatsuba multiplication, this -algorithm has a lower asymptotic running time of approximately $O(n^{1.464})$ but at an obvious cost in overhead. In this -description, several statements have been compounded to save space. The intention is that the statements are executed from left to right across -any given step. - -The two inputs $a$ and $b$ are first split into three $k$-digit integers $a_0, a_1, a_2$ and $b_0, b_1, b_2$ respectively. From these smaller -integers the coefficients of the polynomial basis representations $f(x)$ and $g(x)$ are known and can be used to find the relations required. - -The first two relations $w_0$ and $w_4$ are the points $\zeta_{0}$ and $\zeta_{\infty}$ respectively. The relation $w_1, w_2$ and $w_3$ correspond -to the points $16 \cdot \zeta_{1 \over 2}, \zeta_{2}$ and $\zeta_{1}$ respectively. These are found using logical shifts to independently find -$f(y)$ and $g(y)$ which significantly speeds up the algorithm. - -After the five relations $w_0, w_1, \ldots, w_4$ have been computed, the system they represent must be solved in order for the unknown coefficients -$w_1, w_2$ and $w_3$ to be isolated. The steps 18 through 25 perform the system reduction required as previously described. Each step of -the reduction represents the comparable matrix operation that would be performed had this been performed by pencil. For example, step 18 indicates -that row $1$ must be subtracted from row $4$ and simultaneously row $0$ subtracted from row $3$. - -Once the coeffients have been isolated, the polynomial $W(x) = \sum_{i=0}^{2n} w_i x^i$ is known. By substituting $\beta^{k}$ for $x$, the integer -result $a \cdot b$ is produced. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_toom\_mul.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The first obvious thing to note is that this algorithm is complicated. The complexity is worth it if you are multiplying very -large numbers. For example, a 10,000 digit multiplication takes approximaly 99,282,205 fewer single precision multiplications with -Toom--Cook than a Comba or baseline approach (this is a savings of more than 99$\%$). For most ``crypto'' sized numbers this -algorithm is not practical as Karatsuba has a much lower cutoff point. - -First we split $a$ and $b$ into three roughly equal portions. This has been accomplished (lines 41 to 70) with -combinations of mp\_rshd() and mp\_mod\_2d() function calls. At this point $a = a2 \cdot \beta^2 + a1 \cdot \beta + a0$ and similiarly -for $b$. - -Next we compute the five points $w0, w1, w2, w3$ and $w4$. Recall that $w0$ and $w4$ can be computed directly from the portions so -we get those out of the way first (lines 73 and 78). Next we compute $w1, w2$ and $w3$ using Horners method. - -After this point we solve for the actual values of $w1, w2$ and $w3$ by reducing the $5 \times 5$ system which is relatively -straight forward. - -\subsection{Signed Multiplication} -Now that algorithms to handle multiplications of every useful dimensions have been developed, a rather simple finishing touch is required. So far all -of the multiplication algorithms have been unsigned multiplications which leaves only a signed multiplication algorithm to be established. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_mul}. \\ -\textbf{Input}. mp\_int $a$ and mp\_int $b$ \\ -\textbf{Output}. $c \leftarrow a \cdot b$ \\ -\hline \\ -1. If $a.sign = b.sign$ then \\ -\hspace{3mm}1.1 $sign = MP\_ZPOS$ \\ -2. else \\ -\hspace{3mm}2.1 $sign = MP\_ZNEG$ \\ -3. If min$(a.used, b.used) \ge TOOM\_MUL\_CUTOFF$ then \\ -\hspace{3mm}3.1 $c \leftarrow a \cdot b$ using algorithm mp\_toom\_mul \\ -4. else if min$(a.used, b.used) \ge KARATSUBA\_MUL\_CUTOFF$ then \\ -\hspace{3mm}4.1 $c \leftarrow a \cdot b$ using algorithm mp\_karatsuba\_mul \\ -5. else \\ -\hspace{3mm}5.1 $digs \leftarrow a.used + b.used + 1$ \\ -\hspace{3mm}5.2 If $digs < MP\_ARRAY$ and min$(a.used, b.used) \le \delta$ then \\ -\hspace{6mm}5.2.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm fast\_s\_mp\_mul\_digs. \\ -\hspace{3mm}5.3 else \\ -\hspace{6mm}5.3.1 $c \leftarrow a \cdot b \mbox{ (mod }\beta^{digs}\mbox{)}$ using algorithm s\_mp\_mul\_digs. \\ -6. $c.sign \leftarrow sign$ \\ -7. Return the result of the unsigned multiplication performed. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_mul} -\end{figure} - -\textbf{Algorithm mp\_mul.} -This algorithm performs the signed multiplication of two inputs. It will make use of any of the three unsigned multiplication algorithms -available when the input is of appropriate size. The \textbf{sign} of the result is not set until the end of the algorithm since algorithm -s\_mp\_mul\_digs will clear it. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_mul.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The implementation is rather simplistic and is not particularly noteworthy. Line 22 computes the sign of the result using the ``?'' -operator from the C programming language. Line 48 computes $\delta$ using the fact that $1 << k$ is equal to $2^k$. - -\section{Squaring} -\label{sec:basesquare} - -Squaring is a special case of multiplication where both multiplicands are equal. At first it may seem like there is no significant optimization -available but in fact there is. Consider the multiplication of $576$ against $241$. In total there will be nine single precision multiplications -performed which are $1\cdot 6$, $1 \cdot 7$, $1 \cdot 5$, $4 \cdot 6$, $4 \cdot 7$, $4 \cdot 5$, $2 \cdot 6$, $2 \cdot 7$ and $2 \cdot 5$. Now consider -the multiplication of $123$ against $123$. The nine products are $3 \cdot 3$, $3 \cdot 2$, $3 \cdot 1$, $2 \cdot 3$, $2 \cdot 2$, $2 \cdot 1$, -$1 \cdot 3$, $1 \cdot 2$ and $1 \cdot 1$. On closer inspection some of the products are equivalent. For example, $3 \cdot 2 = 2 \cdot 3$ -and $3 \cdot 1 = 1 \cdot 3$. - -For any $n$-digit input, there are ${{\left (n^2 + n \right)}\over 2}$ possible unique single precision multiplications required compared to the $n^2$ -required for multiplication. The following diagram gives an example of the operations required. - -\begin{figure}[here] -\begin{center} -\begin{tabular}{ccccc|c} -&&1&2&3&\\ -$\times$ &&1&2&3&\\ -\hline && $3 \cdot 1$ & $3 \cdot 2$ & $3 \cdot 3$ & Row 0\\ - & $2 \cdot 1$ & $2 \cdot 2$ & $2 \cdot 3$ && Row 1 \\ - $1 \cdot 1$ & $1 \cdot 2$ & $1 \cdot 3$ &&& Row 2 \\ -\end{tabular} -\end{center} -\caption{Squaring Optimization Diagram} -\end{figure} - -Starting from zero and numbering the columns from right to left a very simple pattern becomes obvious. For the purposes of this discussion let $x$ -represent the number being squared. The first observation is that in row $k$ the $2k$'th column of the product has a $\left (x_k \right)^2$ term in it. - -The second observation is that every column $j$ in row $k$ where $j \ne 2k$ is part of a double product. Every non-square term of a column will -appear twice hence the name ``double product''. Every odd column is made up entirely of double products. In fact every column is made up of double -products and at most one square (\textit{see the exercise section}). - -The third and final observation is that for row $k$ the first unique non-square term, that is, one that hasn't already appeared in an earlier row, -occurs at column $2k + 1$. For example, on row $1$ of the previous squaring, column one is part of the double product with column one from row zero. -Column two of row one is a square and column three is the first unique column. - -\subsection{The Baseline Squaring Algorithm} -The baseline squaring algorithm is meant to be a catch-all squaring algorithm. It will handle any of the input sizes that the faster routines -will not handle. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_sqr}. \\ -\textbf{Input}. mp\_int $a$ \\ -\textbf{Output}. $b \leftarrow a^2$ \\ -\hline \\ -1. Init a temporary mp\_int of at least $2 \cdot a.used +1$ digits. (\textit{mp\_init\_size}) \\ -2. If step 1 failed return(\textit{MP\_MEM}) \\ -3. $t.used \leftarrow 2 \cdot a.used + 1$ \\ -4. For $ix$ from 0 to $a.used - 1$ do \\ -\hspace{3mm}Calculate the square. \\ -\hspace{3mm}4.1 $\hat r \leftarrow t_{2ix} + \left (a_{ix} \right )^2$ \\ -\hspace{3mm}4.2 $t_{2ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}Calculate the double products after the square. \\ -\hspace{3mm}4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -\hspace{3mm}4.4 For $iy$ from $ix + 1$ to $a.used - 1$ do \\ -\hspace{6mm}4.4.1 $\hat r \leftarrow 2 \cdot a_{ix}a_{iy} + t_{ix + iy} + u$ \\ -\hspace{6mm}4.4.2 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{6mm}4.4.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -\hspace{3mm}Set the last carry. \\ -\hspace{3mm}4.5 While $u > 0$ do \\ -\hspace{6mm}4.5.1 $iy \leftarrow iy + 1$ \\ -\hspace{6mm}4.5.2 $\hat r \leftarrow t_{ix + iy} + u$ \\ -\hspace{6mm}4.5.3 $t_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{6mm}4.5.4 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -5. Clamp excess digits of $t$. (\textit{mp\_clamp}) \\ -6. Exchange $b$ and $t$. \\ -7. Clear $t$ (\textit{mp\_clear}) \\ -8. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm s\_mp\_sqr} -\end{figure} - -\textbf{Algorithm s\_mp\_sqr.} -This algorithm computes the square of an input using the three observations on squaring. It is based fairly faithfully on algorithm 14.16 of HAC -\cite[pp.596-597]{HAC}. Similar to algorithm s\_mp\_mul\_digs, a temporary mp\_int is allocated to hold the result of the squaring. This allows the -destination mp\_int to be the same as the source mp\_int. - -The outer loop of this algorithm begins on step 4. It is best to think of the outer loop as walking down the rows of the partial results, while -the inner loop computes the columns of the partial result. Step 4.1 and 4.2 compute the square term for each row, and step 4.3 and 4.4 propagate -the carry and compute the double products. - -The requirement that a mp\_word be able to represent the range $0 \le x < 2 \beta^2$ arises from this -very algorithm. The product $a_{ix}a_{iy}$ will lie in the range $0 \le x \le \beta^2 - 2\beta + 1$ which is obviously less than $\beta^2$ meaning that -when it is multiplied by two, it can be properly represented by a mp\_word. - -Similar to algorithm s\_mp\_mul\_digs, after every pass of the inner loop, the destination is correctly set to the sum of all of the partial -results calculated so far. This involves expensive carry propagation which will be eliminated in the next algorithm. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_sqr.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Inside the outer loop (line 34) the square term is calculated on line 37. The carry (line 44) has been -extracted from the mp\_word accumulator using a right shift. Aliases for $a_{ix}$ and $t_{ix+iy}$ are initialized -(lines 47 and 50) to simplify the inner loop. The doubling is performed using two -additions (line 59) since it is usually faster than shifting, if not at least as fast. - -The important observation is that the inner loop does not begin at $iy = 0$ like for multiplication. As such the inner loops -get progressively shorter as the algorithm proceeds. This is what leads to the savings compared to using a multiplication to -square a number. - -\subsection{Faster Squaring by the ``Comba'' Method} -A major drawback to the baseline method is the requirement for single precision shifting inside the $O(n^2)$ nested loop. Squaring has an additional -drawback that it must double the product inside the inner loop as well. As for multiplication, the Comba technique can be used to eliminate these -performance hazards. - -The first obvious solution is to make an array of mp\_words which will hold all of the columns. This will indeed eliminate all of the carry -propagation operations from the inner loop. However, the inner product must still be doubled $O(n^2)$ times. The solution stems from the simple fact -that $2a + 2b + 2c = 2(a + b + c)$. That is the sum of all of the double products is equal to double the sum of all the products. For example, -$ab + ba + ac + ca = 2ab + 2ac = 2(ab + ac)$. - -However, we cannot simply double all of the columns, since the squares appear only once per row. The most practical solution is to have two -mp\_word arrays. One array will hold the squares and the other array will hold the double products. With both arrays the doubling and -carry propagation can be moved to a $O(n)$ work level outside the $O(n^2)$ level. In this case, we have an even simpler solution in mind. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{fast\_s\_mp\_sqr}. \\ -\textbf{Input}. mp\_int $a$ \\ -\textbf{Output}. $b \leftarrow a^2$ \\ -\hline \\ -Place an array of \textbf{MP\_WARRAY} mp\_digits named $W$ on the stack. \\ -1. If $b.alloc < 2a.used + 1$ then grow $b$ to $2a.used + 1$ digits. (\textit{mp\_grow}). \\ -2. If step 1 failed return(\textit{MP\_MEM}). \\ -\\ -3. $pa \leftarrow 2 \cdot a.used$ \\ -4. $\hat W1 \leftarrow 0$ \\ -5. for $ix$ from $0$ to $pa - 1$ do \\ -\hspace{3mm}5.1 $\_ \hat W \leftarrow 0$ \\ -\hspace{3mm}5.2 $ty \leftarrow \mbox{MIN}(a.used - 1, ix)$ \\ -\hspace{3mm}5.3 $tx \leftarrow ix - ty$ \\ -\hspace{3mm}5.4 $iy \leftarrow \mbox{MIN}(a.used - tx, ty + 1)$ \\ -\hspace{3mm}5.5 $iy \leftarrow \mbox{MIN}(iy, \lfloor \left (ty - tx + 1 \right )/2 \rfloor)$ \\ -\hspace{3mm}5.6 for $iz$ from $0$ to $iz - 1$ do \\ -\hspace{6mm}5.6.1 $\_ \hat W \leftarrow \_ \hat W + a_{tx + iz}a_{ty - iz}$ \\ -\hspace{3mm}5.7 $\_ \hat W \leftarrow 2 \cdot \_ \hat W + \hat W1$ \\ -\hspace{3mm}5.8 if $ix$ is even then \\ -\hspace{6mm}5.8.1 $\_ \hat W \leftarrow \_ \hat W + \left ( a_{\lfloor ix/2 \rfloor}\right )^2$ \\ -\hspace{3mm}5.9 $W_{ix} \leftarrow \_ \hat W (\mbox{mod }\beta)$ \\ -\hspace{3mm}5.10 $\hat W1 \leftarrow \lfloor \_ \hat W / \beta \rfloor$ \\ -\\ -6. $oldused \leftarrow b.used$ \\ -7. $b.used \leftarrow 2 \cdot a.used$ \\ -8. for $ix$ from $0$ to $pa - 1$ do \\ -\hspace{3mm}8.1 $b_{ix} \leftarrow W_{ix}$ \\ -9. for $ix$ from $pa$ to $oldused - 1$ do \\ -\hspace{3mm}9.1 $b_{ix} \leftarrow 0$ \\ -10. Clamp excess digits from $b$. (\textit{mp\_clamp}) \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm fast\_s\_mp\_sqr} -\end{figure} - -\textbf{Algorithm fast\_s\_mp\_sqr.} -This algorithm computes the square of an input using the Comba technique. It is designed to be a replacement for algorithm -s\_mp\_sqr when the number of input digits is less than \textbf{MP\_WARRAY} and less than $\delta \over 2$. -This algorithm is very similar to the Comba multiplier except with a few key differences we shall make note of. - -First, we have an accumulator and carry variables $\_ \hat W$ and $\hat W1$ respectively. This is because the inner loop -products are to be doubled. If we had added the previous carry in we would be doubling too much. Next we perform an -addition MIN condition on $iy$ (step 5.5) to prevent overlapping digits. For example, $a_3 \cdot a_5$ is equal -$a_5 \cdot a_3$. Whereas in the multiplication case we would have $5 < a.used$ and $3 \ge 0$ is maintained since we double the sum -of the products just outside the inner loop we have to avoid doing this. This is also a good thing since we perform -fewer multiplications and the routine ends up being faster. - -Finally the last difference is the addition of the ``square'' term outside the inner loop (step 5.8). We add in the square -only to even outputs and it is the square of the term at the $\lfloor ix / 2 \rfloor$ position. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_fast\_s\_mp\_sqr.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This implementation is essentially a copy of Comba multiplication with the appropriate changes added to make it faster for -the special case of squaring. - -\subsection{Polynomial Basis Squaring} -The same algorithm that performs optimal polynomial basis multiplication can be used to perform polynomial basis squaring. The minor exception -is that $\zeta_y = f(y)g(y)$ is actually equivalent to $\zeta_y = f(y)^2$ since $f(y) = g(y)$. Instead of performing $2n + 1$ -multiplications to find the $\zeta$ relations, squaring operations are performed instead. - -\subsection{Karatsuba Squaring} -Let $f(x) = ax + b$ represent the polynomial basis representation of a number to square. -Let $h(x) = \left ( f(x) \right )^2$ represent the square of the polynomial. The Karatsuba equation can be modified to square a -number with the following equation. - -\begin{equation} -h(x) = a^2x^2 + \left ((a + b)^2 - (a^2 + b^2) \right )x + b^2 -\end{equation} - -Upon closer inspection this equation only requires the calculation of three half-sized squares: $a^2$, $b^2$ and $(a + b)^2$. As in -Karatsuba multiplication, this algorithm can be applied recursively on the input and will achieve an asymptotic running time of -$O \left ( n^{lg(3)} \right )$. - -If the asymptotic times of Karatsuba squaring and multiplication are the same, why not simply use the multiplication algorithm -instead? The answer to this arises from the cutoff point for squaring. As in multiplication there exists a cutoff point, at which the -time required for a Comba based squaring and a Karatsuba based squaring meet. Due to the overhead inherent in the Karatsuba method, the cutoff -point is fairly high. For example, on an AMD Athlon XP processor with $\beta = 2^{28}$, the cutoff point is around 127 digits. - -Consider squaring a 200 digit number with this technique. It will be split into two 100 digit halves which are subsequently squared. -The 100 digit halves will not be squared using Karatsuba, but instead using the faster Comba based squaring algorithm. If Karatsuba multiplication -were used instead, the 100 digit numbers would be squared with a slower Comba based multiplication. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_karatsuba\_sqr}. \\ -\textbf{Input}. mp\_int $a$ \\ -\textbf{Output}. $b \leftarrow a^2$ \\ -\hline \\ -1. Initialize the following temporary mp\_ints: $x0$, $x1$, $t1$, $t2$, $x0x0$ and $x1x1$. \\ -2. If any of the initializations on step 1 failed return(\textit{MP\_MEM}). \\ -\\ -Split the input. e.g. $a = x1\beta^B + x0$ \\ -3. $B \leftarrow \lfloor a.used / 2 \rfloor$ \\ -4. $x0 \leftarrow a \mbox{ (mod }\beta^B\mbox{)}$ (\textit{mp\_mod\_2d}) \\ -5. $x1 \leftarrow \lfloor a / \beta^B \rfloor$ (\textit{mp\_lshd}) \\ -\\ -Calculate the three squares. \\ -6. $x0x0 \leftarrow x0^2$ (\textit{mp\_sqr}) \\ -7. $x1x1 \leftarrow x1^2$ \\ -8. $t1 \leftarrow x1 + x0$ (\textit{s\_mp\_add}) \\ -9. $t1 \leftarrow t1^2$ \\ -\\ -Compute the middle term. \\ -10. $t2 \leftarrow x0x0 + x1x1$ (\textit{s\_mp\_add}) \\ -11. $t1 \leftarrow t1 - t2$ \\ -\\ -Compute final product. \\ -12. $t1 \leftarrow t1\beta^B$ (\textit{mp\_lshd}) \\ -13. $x1x1 \leftarrow x1x1\beta^{2B}$ \\ -14. $t1 \leftarrow t1 + x0x0$ \\ -15. $b \leftarrow t1 + x1x1$ \\ -16. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_karatsuba\_sqr} -\end{figure} - -\textbf{Algorithm mp\_karatsuba\_sqr.} -This algorithm computes the square of an input $a$ using the Karatsuba technique. This algorithm is very similar to the Karatsuba based -multiplication algorithm with the exception that the three half-size multiplications have been replaced with three half-size squarings. - -The radix point for squaring is simply placed exactly in the middle of the digits when the input has an odd number of digits, otherwise it is -placed just below the middle. Step 3, 4 and 5 compute the two halves required using $B$ -as the radix point. The first two squares in steps 6 and 7 are rather straightforward while the last square is of a more compact form. - -By expanding $\left (x1 + x0 \right )^2$, the $x1^2$ and $x0^2$ terms in the middle disappear, that is $(x0 - x1)^2 - (x1^2 + x0^2) = 2 \cdot x0 \cdot x1$. -Now if $5n$ single precision additions and a squaring of $n$-digits is faster than multiplying two $n$-digit numbers and doubling then -this method is faster. Assuming no further recursions occur, the difference can be estimated with the following inequality. - -Let $p$ represent the cost of a single precision addition and $q$ the cost of a single precision multiplication both in terms of time\footnote{Or -machine clock cycles.}. - -\begin{equation} -5pn +{{q(n^2 + n)} \over 2} \le pn + qn^2 -\end{equation} - -For example, on an AMD Athlon XP processor $p = {1 \over 3}$ and $q = 6$. This implies that the following inequality should hold. -\begin{center} -\begin{tabular}{rcl} -${5n \over 3} + 3n^2 + 3n$ & $<$ & ${n \over 3} + 6n^2$ \\ -${5 \over 3} + 3n + 3$ & $<$ & ${1 \over 3} + 6n$ \\ -${13 \over 9}$ & $<$ & $n$ \\ -\end{tabular} -\end{center} - -This results in a cutoff point around $n = 2$. As a consequence it is actually faster to compute the middle term the ``long way'' on processors -where multiplication is substantially slower\footnote{On the Athlon there is a 1:17 ratio between clock cycles for addition and multiplication. On -the Intel P4 processor this ratio is 1:29 making this method even more beneficial. The only common exception is the ARMv4 processor which has a -ratio of 1:7. } than simpler operations such as addition. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_karatsuba\_sqr.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This implementation is largely based on the implementation of algorithm mp\_karatsuba\_mul. It uses the same inline style to copy and -shift the input into the two halves. The loop from line 54 to line 70 has been modified since only one input exists. The \textbf{used} -count of both $x0$ and $x1$ is fixed up and $x0$ is clamped before the calculations begin. At this point $x1$ and $x0$ are valid equivalents -to the respective halves as if mp\_rshd and mp\_mod\_2d had been used. - -By inlining the copy and shift operations the cutoff point for Karatsuba multiplication can be lowered. On the Athlon the cutoff point -is exactly at the point where Comba squaring can no longer be used (\textit{128 digits}). On slower processors such as the Intel P4 -it is actually below the Comba limit (\textit{at 110 digits}). - -This routine uses the same error trap coding style as mp\_karatsuba\_sqr. As the temporary variables are initialized errors are -redirected to the error trap higher up. If the algorithm completes without error the error code is set to \textbf{MP\_OKAY} and -mp\_clears are executed normally. - -\subsection{Toom-Cook Squaring} -The Toom-Cook squaring algorithm mp\_toom\_sqr is heavily based on the algorithm mp\_toom\_mul with the exception that squarings are used -instead of multiplication to find the five relations. The reader is encouraged to read the description of the latter algorithm and try to -derive their own Toom-Cook squaring algorithm. - -\subsection{High Level Squaring} -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_sqr}. \\ -\textbf{Input}. mp\_int $a$ \\ -\textbf{Output}. $b \leftarrow a^2$ \\ -\hline \\ -1. If $a.used \ge TOOM\_SQR\_CUTOFF$ then \\ -\hspace{3mm}1.1 $b \leftarrow a^2$ using algorithm mp\_toom\_sqr \\ -2. else if $a.used \ge KARATSUBA\_SQR\_CUTOFF$ then \\ -\hspace{3mm}2.1 $b \leftarrow a^2$ using algorithm mp\_karatsuba\_sqr \\ -3. else \\ -\hspace{3mm}3.1 $digs \leftarrow a.used + b.used + 1$ \\ -\hspace{3mm}3.2 If $digs < MP\_ARRAY$ and $a.used \le \delta$ then \\ -\hspace{6mm}3.2.1 $b \leftarrow a^2$ using algorithm fast\_s\_mp\_sqr. \\ -\hspace{3mm}3.3 else \\ -\hspace{6mm}3.3.1 $b \leftarrow a^2$ using algorithm s\_mp\_sqr. \\ -4. $b.sign \leftarrow MP\_ZPOS$ \\ -5. Return the result of the unsigned squaring performed. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_sqr} -\end{figure} - -\textbf{Algorithm mp\_sqr.} -This algorithm computes the square of the input using one of four different algorithms. If the input is very large and has at least -\textbf{TOOM\_SQR\_CUTOFF} or \textbf{KARATSUBA\_SQR\_CUTOFF} digits then either the Toom-Cook or the Karatsuba Squaring algorithm is used. If -neither of the polynomial basis algorithms should be used then either the Comba or baseline algorithm is used. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_sqr.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\section*{Exercises} -\begin{tabular}{cl} -$\left [ 3 \right ] $ & Devise an efficient algorithm for selection of the radix point to handle inputs \\ - & that have different number of digits in Karatsuba multiplication. \\ - & \\ -$\left [ 2 \right ] $ & In section 5.3 the fact that every column of a squaring is made up \\ - & of double products and at most one square is stated. Prove this statement. \\ - & \\ -$\left [ 3 \right ] $ & Prove the equation for Karatsuba squaring. \\ - & \\ -$\left [ 1 \right ] $ & Prove that Karatsuba squaring requires $O \left (n^{lg(3)} \right )$ time. \\ - & \\ -$\left [ 2 \right ] $ & Determine the minimal ratio between addition and multiplication clock cycles \\ - & required for equation $6.7$ to be true. \\ - & \\ -$\left [ 3 \right ] $ & Implement a threaded version of Comba multiplication (and squaring) where you \\ - & compute subsets of the columns in each thread. Determine a cutoff point where \\ - & it is effective and add the logic to mp\_mul() and mp\_sqr(). \\ - &\\ -$\left [ 4 \right ] $ & Same as the previous but also modify the Karatsuba and Toom-Cook. You must \\ - & increase the throughput of mp\_exptmod() for random odd moduli in the range \\ - & $512 \ldots 4096$ bits significantly ($> 2x$) to complete this challenge. \\ - & \\ -\end{tabular} - -\chapter{Modular Reduction} -\section{Basics of Modular Reduction} -\index{modular residue} -Modular reduction is an operation that arises quite often within public key cryptography algorithms and various number theoretic algorithms, -such as factoring. Modular reduction algorithms are the third class of algorithms of the ``multipliers'' set. A number $a$ is said to be \textit{reduced} -modulo another number $b$ by finding the remainder of the division $a/b$. Full integer division with remainder is a topic to be covered -in~\ref{sec:division}. - -Modular reduction is equivalent to solving for $r$ in the following equation. $a = bq + r$ where $q = \lfloor a/b \rfloor$. The result -$r$ is said to be ``congruent to $a$ modulo $b$'' which is also written as $r \equiv a \mbox{ (mod }b\mbox{)}$. In other vernacular $r$ is known as the -``modular residue'' which leads to ``quadratic residue''\footnote{That's fancy talk for $b \equiv a^2 \mbox{ (mod }p\mbox{)}$.} and -other forms of residues. - -Modular reductions are normally used to create either finite groups, rings or fields. The most common usage for performance driven modular reductions -is in modular exponentiation algorithms. That is to compute $d = a^b \mbox{ (mod }c\mbox{)}$ as fast as possible. This operation is used in the -RSA and Diffie-Hellman public key algorithms, for example. Modular multiplication and squaring also appears as a fundamental operation in -elliptic curve cryptographic algorithms. As will be discussed in the subsequent chapter there exist fast algorithms for computing modular -exponentiations without having to perform (\textit{in this example}) $b - 1$ multiplications. These algorithms will produce partial results in the -range $0 \le x < c^2$ which can be taken advantage of to create several efficient algorithms. They have also been used to create redundancy check -algorithms known as CRCs, error correction codes such as Reed-Solomon and solve a variety of number theoeretic problems. - -\section{The Barrett Reduction} -The Barrett reduction algorithm \cite{BARRETT} was inspired by fast division algorithms which multiply by the reciprocal to emulate -division. Barretts observation was that the residue $c$ of $a$ modulo $b$ is equal to - -\begin{equation} -c = a - b \cdot \lfloor a/b \rfloor -\end{equation} - -Since algorithms such as modular exponentiation would be using the same modulus extensively, typical DSP\footnote{It is worth noting that Barrett's paper -targeted the DSP56K processor.} intuition would indicate the next step would be to replace $a/b$ by a multiplication by the reciprocal. However, -DSP intuition on its own will not work as these numbers are considerably larger than the precision of common DSP floating point data types. -It would take another common optimization to optimize the algorithm. - -\subsection{Fixed Point Arithmetic} -The trick used to optimize the above equation is based on a technique of emulating floating point data types with fixed precision integers. Fixed -point arithmetic would become very popular as it greatly optimize the ``3d-shooter'' genre of games in the mid 1990s when floating point units were -fairly slow if not unavailable. The idea behind fixed point arithmetic is to take a normal $k$-bit integer data type and break it into $p$-bit -integer and a $q$-bit fraction part (\textit{where $p+q = k$}). - -In this system a $k$-bit integer $n$ would actually represent $n/2^q$. For example, with $q = 4$ the integer $n = 37$ would actually represent the -value $2.3125$. To multiply two fixed point numbers the integers are multiplied using traditional arithmetic and subsequently normalized by -moving the implied decimal point back to where it should be. For example, with $q = 4$ to multiply the integers $9$ and $5$ they must be converted -to fixed point first by multiplying by $2^q$. Let $a = 9(2^q)$ represent the fixed point representation of $9$ and $b = 5(2^q)$ represent the -fixed point representation of $5$. The product $ab$ is equal to $45(2^{2q})$ which when normalized by dividing by $2^q$ produces $45(2^q)$. - -This technique became popular since a normal integer multiplication and logical shift right are the only required operations to perform a multiplication -of two fixed point numbers. Using fixed point arithmetic, division can be easily approximated by multiplying by the reciprocal. If $2^q$ is -equivalent to one than $2^q/b$ is equivalent to the fixed point approximation of $1/b$ using real arithmetic. Using this fact dividing an integer -$a$ by another integer $b$ can be achieved with the following expression. - -\begin{equation} -\lfloor a / b \rfloor \mbox{ }\approx\mbox{ } \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor -\end{equation} - -The precision of the division is proportional to the value of $q$. If the divisor $b$ is used frequently as is the case with -modular exponentiation pre-computing $2^q/b$ will allow a division to be performed with a multiplication and a right shift. Both operations -are considerably faster than division on most processors. - -Consider dividing $19$ by $5$. The correct result is $\lfloor 19/5 \rfloor = 3$. With $q = 3$ the reciprocal is $\lfloor 2^q/5 \rfloor = 1$ which -leads to a product of $19$ which when divided by $2^q$ produces $2$. However, with $q = 4$ the reciprocal is $\lfloor 2^q/5 \rfloor = 3$ and -the result of the emulated division is $\lfloor 3 \cdot 19 / 2^q \rfloor = 3$ which is correct. The value of $2^q$ must be close to or ideally -larger than the dividend. In effect if $a$ is the dividend then $q$ should allow $0 \le \lfloor a/2^q \rfloor \le 1$ in order for this approach -to work correctly. Plugging this form of divison into the original equation the following modular residue equation arises. - -\begin{equation} -c = a - b \cdot \lfloor (a \cdot \lfloor 2^q / b \rfloor)/2^q \rfloor -\end{equation} - -Using the notation from \cite{BARRETT} the value of $\lfloor 2^q / b \rfloor$ will be represented by the $\mu$ symbol. Using the $\mu$ -variable also helps re-inforce the idea that it is meant to be computed once and re-used. - -\begin{equation} -c = a - b \cdot \lfloor (a \cdot \mu)/2^q \rfloor -\end{equation} - -Provided that $2^q \ge a$ this algorithm will produce a quotient that is either exactly correct or off by a value of one. In the context of Barrett -reduction the value of $a$ is bound by $0 \le a \le (b - 1)^2$ meaning that $2^q \ge b^2$ is sufficient to ensure the reciprocal will have enough -precision. - -Let $n$ represent the number of digits in $b$. This algorithm requires approximately $2n^2$ single precision multiplications to produce the quotient and -another $n^2$ single precision multiplications to find the residue. In total $3n^2$ single precision multiplications are required to -reduce the number. - -For example, if $b = 1179677$ and $q = 41$ ($2^q > b^2$), then the reciprocal $\mu$ is equal to $\lfloor 2^q / b \rfloor = 1864089$. Consider reducing -$a = 180388626447$ modulo $b$ using the above reduction equation. The quotient using the new formula is $\lfloor (a \cdot \mu) / 2^q \rfloor = 152913$. -By subtracting $152913b$ from $a$ the correct residue $a \equiv 677346 \mbox{ (mod }b\mbox{)}$ is found. - -\subsection{Choosing a Radix Point} -Using the fixed point representation a modular reduction can be performed with $3n^2$ single precision multiplications. If that were the best -that could be achieved a full division\footnote{A division requires approximately $O(2cn^2)$ single precision multiplications for a small value of $c$. -See~\ref{sec:division} for further details.} might as well be used in its place. The key to optimizing the reduction is to reduce the precision of -the initial multiplication that finds the quotient. - -Let $a$ represent the number of which the residue is sought. Let $b$ represent the modulus used to find the residue. Let $m$ represent -the number of digits in $b$. For the purposes of this discussion we will assume that the number of digits in $a$ is $2m$, which is generally true if -two $m$-digit numbers have been multiplied. Dividing $a$ by $b$ is the same as dividing a $2m$ digit integer by a $m$ digit integer. Digits below the -$m - 1$'th digit of $a$ will contribute at most a value of $1$ to the quotient because $\beta^k < b$ for any $0 \le k \le m - 1$. Another way to -express this is by re-writing $a$ as two parts. If $a' \equiv a \mbox{ (mod }b^m\mbox{)}$ and $a'' = a - a'$ then -${a \over b} \equiv {{a' + a''} \over b}$ which is equivalent to ${a' \over b} + {a'' \over b}$. Since $a'$ is bound to be less than $b$ the quotient -is bound by $0 \le {a' \over b} < 1$. - -Since the digits of $a'$ do not contribute much to the quotient the observation is that they might as well be zero. However, if the digits -``might as well be zero'' they might as well not be there in the first place. Let $q_0 = \lfloor a/\beta^{m-1} \rfloor$ represent the input -with the irrelevant digits trimmed. Now the modular reduction is trimmed to the almost equivalent equation - -\begin{equation} -c = a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor -\end{equation} - -Note that the original divisor $2^q$ has been replaced with $\beta^{m+1}$ where in this case $q$ is a multiple of $lg(\beta)$. Also note that the -exponent on the divisor when added to the amount $q_0$ was shifted by equals $2m$. If the optimization had not been performed the divisor -would have the exponent $2m$ so in the end the exponents do ``add up''. Using the above equation the quotient -$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ can be off from the true quotient by at most two. The original fixed point quotient can be off -by as much as one (\textit{provided the radix point is chosen suitably}) and now that the lower irrelevent digits have been trimmed the quotient -can be off by an additional value of one for a total of at most two. This implies that -$0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. By first subtracting $b$ times the quotient and then conditionally subtracting -$b$ once or twice the residue is found. - -The quotient is now found using $(m + 1)(m) = m^2 + m$ single precision multiplications and the residue with an additional $m^2$ single -precision multiplications, ignoring the subtractions required. In total $2m^2 + m$ single precision multiplications are required to find the residue. -This is considerably faster than the original attempt. - -For example, let $\beta = 10$ represent the radix of the digits. Let $b = 9999$ represent the modulus which implies $m = 4$. Let $a = 99929878$ -represent the value of which the residue is desired. In this case $q = 8$ since $10^7 < 9999^2$ meaning that $\mu = \lfloor \beta^{q}/b \rfloor = 10001$. -With the new observation the multiplicand for the quotient is equal to $q_0 = \lfloor a / \beta^{m - 1} \rfloor = 99929$. The quotient is then -$\lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor = 9993$. Subtracting $9993b$ from $a$ and the correct residue $a \equiv 9871 \mbox{ (mod }b\mbox{)}$ -is found. - -\subsection{Trimming the Quotient} -So far the reduction algorithm has been optimized from $3m^2$ single precision multiplications down to $2m^2 + m$ single precision multiplications. As -it stands now the algorithm is already fairly fast compared to a full integer division algorithm. However, there is still room for -optimization. - -After the first multiplication inside the quotient ($q_0 \cdot \mu$) the value is shifted right by $m + 1$ places effectively nullifying the lower -half of the product. It would be nice to be able to remove those digits from the product to effectively cut down the number of single precision -multiplications. If the number of digits in the modulus $m$ is far less than $\beta$ a full product is not required for the algorithm to work properly. -In fact the lower $m - 2$ digits will not affect the upper half of the product at all and do not need to be computed. - -The value of $\mu$ is a $m$-digit number and $q_0$ is a $m + 1$ digit number. Using a full multiplier $(m + 1)(m) = m^2 + m$ single precision -multiplications would be required. Using a multiplier that will only produce digits at and above the $m - 1$'th digit reduces the number -of single precision multiplications to ${m^2 + m} \over 2$ single precision multiplications. - -\subsection{Trimming the Residue} -After the quotient has been calculated it is used to reduce the input. As previously noted the algorithm is not exact and it can be off by a small -multiple of the modulus, that is $0 \le a - b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor < 3b$. If $b$ is $m$ digits than the -result of reduction equation is a value of at most $m + 1$ digits (\textit{provided $3 < \beta$}) implying that the upper $m - 1$ digits are -implicitly zero. - -The next optimization arises from this very fact. Instead of computing $b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ using a full -$O(m^2)$ multiplication algorithm only the lower $m+1$ digits of the product have to be computed. Similarly the value of $a$ can -be reduced modulo $\beta^{m+1}$ before the multiple of $b$ is subtracted which simplifes the subtraction as well. A multiplication that produces -only the lower $m+1$ digits requires ${m^2 + 3m - 2} \over 2$ single precision multiplications. - -With both optimizations in place the algorithm is the algorithm Barrett proposed. It requires $m^2 + 2m - 1$ single precision multiplications which -is considerably faster than the straightforward $3m^2$ method. - -\subsection{The Barrett Algorithm} -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_reduce}. \\ -\textbf{Input}. mp\_int $a$, mp\_int $b$ and $\mu = \lfloor \beta^{2m}/b \rfloor, m = \lceil lg_{\beta}(b) \rceil, (0 \le a < b^2, b > 1)$ \\ -\textbf{Output}. $a \mbox{ (mod }b\mbox{)}$ \\ -\hline \\ -Let $m$ represent the number of digits in $b$. \\ -1. Make a copy of $a$ and store it in $q$. (\textit{mp\_init\_copy}) \\ -2. $q \leftarrow \lfloor q / \beta^{m - 1} \rfloor$ (\textit{mp\_rshd}) \\ -\\ -Produce the quotient. \\ -3. $q \leftarrow q \cdot \mu$ (\textit{note: only produce digits at or above $m-1$}) \\ -4. $q \leftarrow \lfloor q / \beta^{m + 1} \rfloor$ \\ -\\ -Subtract the multiple of modulus from the input. \\ -5. $a \leftarrow a \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{mp\_mod\_2d}) \\ -6. $q \leftarrow q \cdot b \mbox{ (mod }\beta^{m+1}\mbox{)}$ (\textit{s\_mp\_mul\_digs}) \\ -7. $a \leftarrow a - q$ (\textit{mp\_sub}) \\ -\\ -Add $\beta^{m+1}$ if a carry occured. \\ -8. If $a < 0$ then (\textit{mp\_cmp\_d}) \\ -\hspace{3mm}8.1 $q \leftarrow 1$ (\textit{mp\_set}) \\ -\hspace{3mm}8.2 $q \leftarrow q \cdot \beta^{m+1}$ (\textit{mp\_lshd}) \\ -\hspace{3mm}8.3 $a \leftarrow a + q$ \\ -\\ -Now subtract the modulus if the residue is too large (e.g. quotient too small). \\ -9. While $a \ge b$ do (\textit{mp\_cmp}) \\ -\hspace{3mm}9.1 $c \leftarrow a - b$ \\ -10. Clear $q$. \\ -11. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_reduce} -\end{figure} - -\textbf{Algorithm mp\_reduce.} -This algorithm will reduce the input $a$ modulo $b$ in place using the Barrett algorithm. It is loosely based on algorithm 14.42 of HAC -\cite[pp. 602]{HAC} which is based on the paper from Paul Barrett \cite{BARRETT}. The algorithm has several restrictions and assumptions which must -be adhered to for the algorithm to work. - -First the modulus $b$ is assumed to be positive and greater than one. If the modulus were less than or equal to one than subtracting -a multiple of it would either accomplish nothing or actually enlarge the input. The input $a$ must be in the range $0 \le a < b^2$ in order -for the quotient to have enough precision. If $a$ is the product of two numbers that were already reduced modulo $b$, this will not be a problem. -Technically the algorithm will still work if $a \ge b^2$ but it will take much longer to finish. The value of $\mu$ is passed as an argument to this -algorithm and is assumed to be calculated and stored before the algorithm is used. - -Recall that the multiplication for the quotient on step 3 must only produce digits at or above the $m-1$'th position. An algorithm called -$s\_mp\_mul\_high\_digs$ which has not been presented is used to accomplish this task. The algorithm is based on $s\_mp\_mul\_digs$ except that -instead of stopping at a given level of precision it starts at a given level of precision. This optimal algorithm can only be used if the number -of digits in $b$ is very much smaller than $\beta$. - -While it is known that -$a \ge b \cdot \lfloor (q_0 \cdot \mu) / \beta^{m+1} \rfloor$ only the lower $m+1$ digits are being used to compute the residue, so an implied -``borrow'' from the higher digits might leave a negative result. After the multiple of the modulus has been subtracted from $a$ the residue must be -fixed up in case it is negative. The invariant $\beta^{m+1}$ must be added to the residue to make it positive again. - -The while loop at step 9 will subtract $b$ until the residue is less than $b$. If the algorithm is performed correctly this step is -performed at most twice, and on average once. However, if $a \ge b^2$ than it will iterate substantially more times than it should. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The first multiplication that determines the quotient can be performed by only producing the digits from $m - 1$ and up. This essentially halves -the number of single precision multiplications required. However, the optimization is only safe if $\beta$ is much larger than the number of digits -in the modulus. In the source code this is evaluated on lines 36 to 44 where algorithm s\_mp\_mul\_high\_digs is used when it is -safe to do so. - -\subsection{The Barrett Setup Algorithm} -In order to use algorithm mp\_reduce the value of $\mu$ must be calculated in advance. Ideally this value should be computed once and stored for -future use so that the Barrett algorithm can be used without delay. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_reduce\_setup}. \\ -\textbf{Input}. mp\_int $a$ ($a > 1$) \\ -\textbf{Output}. $\mu \leftarrow \lfloor \beta^{2m}/a \rfloor$ \\ -\hline \\ -1. $\mu \leftarrow 2^{2 \cdot lg(\beta) \cdot m}$ (\textit{mp\_2expt}) \\ -2. $\mu \leftarrow \lfloor \mu / b \rfloor$ (\textit{mp\_div}) \\ -3. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_reduce\_setup} -\end{figure} - -\textbf{Algorithm mp\_reduce\_setup.} -This algorithm computes the reciprocal $\mu$ required for Barrett reduction. First $\beta^{2m}$ is calculated as $2^{2 \cdot lg(\beta) \cdot m}$ which -is equivalent and much faster. The final value is computed by taking the integer quotient of $\lfloor \mu / b \rfloor$. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_setup.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This simple routine calculates the reciprocal $\mu$ required by Barrett reduction. Note the extended usage of algorithm mp\_div where the variable -which would received the remainder is passed as NULL. As will be discussed in~\ref{sec:division} the division routine allows both the quotient and the -remainder to be passed as NULL meaning to ignore the value. - -\section{The Montgomery Reduction} -Montgomery reduction\footnote{Thanks to Niels Ferguson for his insightful explanation of the algorithm.} \cite{MONT} is by far the most interesting -form of reduction in common use. It computes a modular residue which is not actually equal to the residue of the input yet instead equal to a -residue times a constant. However, as perplexing as this may sound the algorithm is relatively simple and very efficient. - -Throughout this entire section the variable $n$ will represent the modulus used to form the residue. As will be discussed shortly the value of -$n$ must be odd. The variable $x$ will represent the quantity of which the residue is sought. Similar to the Barrett algorithm the input -is restricted to $0 \le x < n^2$. To begin the description some simple number theory facts must be established. - -\textbf{Fact 1.} Adding $n$ to $x$ does not change the residue since in effect it adds one to the quotient $\lfloor x / n \rfloor$. Another way -to explain this is that $n$ is (\textit{or multiples of $n$ are}) congruent to zero modulo $n$. Adding zero will not change the value of the residue. - -\textbf{Fact 2.} If $x$ is even then performing a division by two in $\Z$ is congruent to $x \cdot 2^{-1} \mbox{ (mod }n\mbox{)}$. Actually -this is an application of the fact that if $x$ is evenly divisible by any $k \in \Z$ then division in $\Z$ will be congruent to -multiplication by $k^{-1}$ modulo $n$. - -From these two simple facts the following simple algorithm can be derived. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Montgomery Reduction}. \\ -\textbf{Input}. Integer $x$, $n$ and $k$ \\ -\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\ -\hline \\ -1. for $t$ from $1$ to $k$ do \\ -\hspace{3mm}1.1 If $x$ is odd then \\ -\hspace{6mm}1.1.1 $x \leftarrow x + n$ \\ -\hspace{3mm}1.2 $x \leftarrow x/2$ \\ -2. Return $x$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Montgomery Reduction} -\end{figure} - -The algorithm reduces the input one bit at a time using the two congruencies stated previously. Inside the loop $n$, which is odd, is -added to $x$ if $x$ is odd. This forces $x$ to be even which allows the division by two in $\Z$ to be congruent to a modular division by two. Since -$x$ is assumed to be initially much larger than $n$ the addition of $n$ will contribute an insignificant magnitude to $x$. Let $r$ represent the -final result of the Montgomery algorithm. If $k > lg(n)$ and $0 \le x < n^2$ then the final result is limited to -$0 \le r < \lfloor x/2^k \rfloor + n$. As a result at most a single subtraction is required to get the residue desired. - -\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{|c|l|} -\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} \\ -\hline $1$ & $x + n = 5812$, $x/2 = 2906$ \\ -\hline $2$ & $x/2 = 1453$ \\ -\hline $3$ & $x + n = 1710$, $x/2 = 855$ \\ -\hline $4$ & $x + n = 1112$, $x/2 = 556$ \\ -\hline $5$ & $x/2 = 278$ \\ -\hline $6$ & $x/2 = 139$ \\ -\hline $7$ & $x + n = 396$, $x/2 = 198$ \\ -\hline $8$ & $x/2 = 99$ \\ -\hline $9$ & $x + n = 356$, $x/2 = 178$ \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Example of Montgomery Reduction (I)} -\label{fig:MONT1} -\end{figure} - -Consider the example in figure~\ref{fig:MONT1} which reduces $x = 5555$ modulo $n = 257$ when $k = 9$ (note $\beta^k = 512$ which is larger than $n$). The result of -the algorithm $r = 178$ is congruent to the value of $2^{-9} \cdot 5555 \mbox{ (mod }257\mbox{)}$. When $r$ is multiplied by $2^9$ modulo $257$ the correct residue -$r \equiv 158$ is produced. - -Let $k = \lfloor lg(n) \rfloor + 1$ represent the number of bits in $n$. The current algorithm requires $2k^2$ single precision shifts -and $k^2$ single precision additions. At this rate the algorithm is most certainly slower than Barrett reduction and not terribly useful. -Fortunately there exists an alternative representation of the algorithm. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Montgomery Reduction} (modified I). \\ -\textbf{Input}. Integer $x$, $n$ and $k$ ($2^k > n$) \\ -\textbf{Output}. $2^{-k}x \mbox{ (mod }n\mbox{)}$ \\ -\hline \\ -1. for $t$ from $1$ to $k$ do \\ -\hspace{3mm}1.1 If the $t$'th bit of $x$ is one then \\ -\hspace{6mm}1.1.1 $x \leftarrow x + 2^tn$ \\ -2. Return $x/2^k$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Montgomery Reduction (modified I)} -\end{figure} - -This algorithm is equivalent since $2^tn$ is a multiple of $n$ and the lower $k$ bits of $x$ are zero by step 2. The number of single -precision shifts has now been reduced from $2k^2$ to $k^2 + k$ which is only a small improvement. - -\begin{figure}[here] -\begin{small} -\begin{center} -\begin{tabular}{|c|l|r|} -\hline \textbf{Step number ($t$)} & \textbf{Result ($x$)} & \textbf{Result ($x$) in Binary} \\ -\hline -- & $5555$ & $1010110110011$ \\ -\hline $1$ & $x + 2^{0}n = 5812$ & $1011010110100$ \\ -\hline $2$ & $5812$ & $1011010110100$ \\ -\hline $3$ & $x + 2^{2}n = 6840$ & $1101010111000$ \\ -\hline $4$ & $x + 2^{3}n = 8896$ & $10001011000000$ \\ -\hline $5$ & $8896$ & $10001011000000$ \\ -\hline $6$ & $8896$ & $10001011000000$ \\ -\hline $7$ & $x + 2^{6}n = 25344$ & $110001100000000$ \\ -\hline $8$ & $25344$ & $110001100000000$ \\ -\hline $9$ & $x + 2^{7}n = 91136$ & $10110010000000000$ \\ -\hline -- & $x/2^k = 178$ & \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Example of Montgomery Reduction (II)} -\label{fig:MONT2} -\end{figure} - -Figure~\ref{fig:MONT2} demonstrates the modified algorithm reducing $x = 5555$ modulo $n = 257$ with $k = 9$. -With this algorithm a single shift right at the end is the only right shift required to reduce the input instead of $k$ right shifts inside the -loop. Note that for the iterations $t = 2, 5, 6$ and $8$ where the result $x$ is not changed. In those iterations the $t$'th bit of $x$ is -zero and the appropriate multiple of $n$ does not need to be added to force the $t$'th bit of the result to zero. - -\subsection{Digit Based Montgomery Reduction} -Instead of computing the reduction on a bit-by-bit basis it is actually much faster to compute it on digit-by-digit basis. Consider the -previous algorithm re-written to compute the Montgomery reduction in this new fashion. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Montgomery Reduction} (modified II). \\ -\textbf{Input}. Integer $x$, $n$ and $k$ ($\beta^k > n$) \\ -\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ -\hline \\ -1. for $t$ from $0$ to $k - 1$ do \\ -\hspace{3mm}1.1 $x \leftarrow x + \mu n \beta^t$ \\ -2. Return $x/\beta^k$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Montgomery Reduction (modified II)} -\end{figure} - -The value $\mu n \beta^t$ is a multiple of the modulus $n$ meaning that it will not change the residue. If the first digit of -the value $\mu n \beta^t$ equals the negative (modulo $\beta$) of the $t$'th digit of $x$ then the addition will result in a zero digit. This -problem breaks down to solving the following congruency. - -\begin{center} -\begin{tabular}{rcl} -$x_t + \mu n_0$ & $\equiv$ & $0 \mbox{ (mod }\beta\mbox{)}$ \\ -$\mu n_0$ & $\equiv$ & $-x_t \mbox{ (mod }\beta\mbox{)}$ \\ -$\mu$ & $\equiv$ & $-x_t/n_0 \mbox{ (mod }\beta\mbox{)}$ \\ -\end{tabular} -\end{center} - -In each iteration of the loop on step 1 a new value of $\mu$ must be calculated. The value of $-1/n_0 \mbox{ (mod }\beta\mbox{)}$ is used -extensively in this algorithm and should be precomputed. Let $\rho$ represent the negative of the modular inverse of $n_0$ modulo $\beta$. - -For example, let $\beta = 10$ represent the radix. Let $n = 17$ represent the modulus which implies $k = 2$ and $\rho \equiv 7$. Let $x = 33$ -represent the value to reduce. - -\newpage\begin{figure} -\begin{center} -\begin{tabular}{|c|c|c|} -\hline \textbf{Step ($t$)} & \textbf{Value of $x$} & \textbf{Value of $\mu$} \\ -\hline -- & $33$ & --\\ -\hline $0$ & $33 + \mu n = 50$ & $1$ \\ -\hline $1$ & $50 + \mu n \beta = 900$ & $5$ \\ -\hline -\end{tabular} -\end{center} -\caption{Example of Montgomery Reduction} -\end{figure} - -The final result $900$ is then divided by $\beta^k$ to produce the final result $9$. The first observation is that $9 \nequiv x \mbox{ (mod }n\mbox{)}$ -which implies the result is not the modular residue of $x$ modulo $n$. However, recall that the residue is actually multiplied by $\beta^{-k}$ in -the algorithm. To get the true residue the value must be multiplied by $\beta^k$. In this case $\beta^k \equiv 15 \mbox{ (mod }n\mbox{)}$ and -the correct residue is $9 \cdot 15 \equiv 16 \mbox{ (mod }n\mbox{)}$. - -\subsection{Baseline Montgomery Reduction} -The baseline Montgomery reduction algorithm will produce the residue for any size input. It is designed to be a catch-all algororithm for -Montgomery reductions. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_montgomery\_reduce}. \\ -\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\ -\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\ -\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ -\hline \\ -1. $digs \leftarrow 2n.used + 1$ \\ -2. If $digs < MP\_ARRAY$ and $m.used < \delta$ then \\ -\hspace{3mm}2.1 Use algorithm fast\_mp\_montgomery\_reduce instead. \\ -\\ -Setup $x$ for the reduction. \\ -3. If $x.alloc < digs$ then grow $x$ to $digs$ digits. \\ -4. $x.used \leftarrow digs$ \\ -\\ -Eliminate the lower $k$ digits. \\ -5. For $ix$ from $0$ to $k - 1$ do \\ -\hspace{3mm}5.1 $\mu \leftarrow x_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}5.2 $u \leftarrow 0$ \\ -\hspace{3mm}5.3 For $iy$ from $0$ to $k - 1$ do \\ -\hspace{6mm}5.3.1 $\hat r \leftarrow \mu n_{iy} + x_{ix + iy} + u$ \\ -\hspace{6mm}5.3.2 $x_{ix + iy} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{6mm}5.3.3 $u \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -\hspace{3mm}5.4 While $u > 0$ do \\ -\hspace{6mm}5.4.1 $iy \leftarrow iy + 1$ \\ -\hspace{6mm}5.4.2 $x_{ix + iy} \leftarrow x_{ix + iy} + u$ \\ -\hspace{6mm}5.4.3 $u \leftarrow \lfloor x_{ix+iy} / \beta \rfloor$ \\ -\hspace{6mm}5.4.4 $x_{ix + iy} \leftarrow x_{ix+iy} \mbox{ (mod }\beta\mbox{)}$ \\ -\\ -Divide by $\beta^k$ and fix up as required. \\ -6. $x \leftarrow \lfloor x / \beta^k \rfloor$ \\ -7. If $x \ge n$ then \\ -\hspace{3mm}7.1 $x \leftarrow x - n$ \\ -8. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_montgomery\_reduce} -\end{figure} - -\textbf{Algorithm mp\_montgomery\_reduce.} -This algorithm reduces the input $x$ modulo $n$ in place using the Montgomery reduction algorithm. The algorithm is loosely based -on algorithm 14.32 of \cite[pp.601]{HAC} except it merges the multiplication of $\mu n \beta^t$ with the addition in the inner loop. The -restrictions on this algorithm are fairly easy to adapt to. First $0 \le x < n^2$ bounds the input to numbers in the same range as -for the Barrett algorithm. Additionally if $n > 1$ and $n$ is odd there will exist a modular inverse $\rho$. $\rho$ must be calculated in -advance of this algorithm. Finally the variable $k$ is fixed and a pseudonym for $n.used$. - -Step 2 decides whether a faster Montgomery algorithm can be used. It is based on the Comba technique meaning that there are limits on -the size of the input. This algorithm is discussed in sub-section 6.3.3. - -Step 5 is the main reduction loop of the algorithm. The value of $\mu$ is calculated once per iteration in the outer loop. The inner loop -calculates $x + \mu n \beta^{ix}$ by multiplying $\mu n$ and adding the result to $x$ shifted by $ix$ digits. Both the addition and -multiplication are performed in the same loop to save time and memory. Step 5.4 will handle any additional carries that escape the inner loop. - -Using a quick inspection this algorithm requires $n$ single precision multiplications for the outer loop and $n^2$ single precision multiplications -in the inner loop. In total $n^2 + n$ single precision multiplications which compares favourably to Barrett at $n^2 + 2n - 1$ single precision -multiplications. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_reduce.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This is the baseline implementation of the Montgomery reduction algorithm. Lines 31 to 36 determine if the Comba based -routine can be used instead. Line 47 computes the value of $\mu$ for that particular iteration of the outer loop. - -The multiplication $\mu n \beta^{ix}$ is performed in one step in the inner loop. The alias $tmpx$ refers to the $ix$'th digit of $x$ and -the alias $tmpn$ refers to the modulus $n$. - -\subsection{Faster ``Comba'' Montgomery Reduction} - -The Montgomery reduction requires fewer single precision multiplications than a Barrett reduction, however it is much slower due to the serial -nature of the inner loop. The Barrett reduction algorithm requires two slightly modified multipliers which can be implemented with the Comba -technique. The Montgomery reduction algorithm cannot directly use the Comba technique to any significant advantage since the inner loop calculates -a $k \times 1$ product $k$ times. - -The biggest obstacle is that at the $ix$'th iteration of the outer loop the value of $x_{ix}$ is required to calculate $\mu$. This means the -carries from $0$ to $ix - 1$ must have been propagated upwards to form a valid $ix$'th digit. The solution as it turns out is very simple. -Perform a Comba like multiplier and inside the outer loop just after the inner loop fix up the $ix + 1$'th digit by forwarding the carry. - -With this change in place the Montgomery reduction algorithm can be performed with a Comba style multiplication loop which substantially increases -the speed of the algorithm. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{fast\_mp\_montgomery\_reduce}. \\ -\textbf{Input}. mp\_int $x$, mp\_int $n$ and a digit $\rho \equiv -1/n_0 \mbox{ (mod }n\mbox{)}$. \\ -\hspace{11.5mm}($0 \le x < n^2, n > 1, (n, \beta) = 1, \beta^k > n$) \\ -\textbf{Output}. $\beta^{-k}x \mbox{ (mod }n\mbox{)}$ \\ -\hline \\ -Place an array of \textbf{MP\_WARRAY} mp\_word variables called $\hat W$ on the stack. \\ -1. if $x.alloc < n.used + 1$ then grow $x$ to $n.used + 1$ digits. \\ -Copy the digits of $x$ into the array $\hat W$ \\ -2. For $ix$ from $0$ to $x.used - 1$ do \\ -\hspace{3mm}2.1 $\hat W_{ix} \leftarrow x_{ix}$ \\ -3. For $ix$ from $x.used$ to $2n.used - 1$ do \\ -\hspace{3mm}3.1 $\hat W_{ix} \leftarrow 0$ \\ -Elimiate the lower $k$ digits. \\ -4. for $ix$ from $0$ to $n.used - 1$ do \\ -\hspace{3mm}4.1 $\mu \leftarrow \hat W_{ix} \cdot \rho \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}4.2 For $iy$ from $0$ to $n.used - 1$ do \\ -\hspace{6mm}4.2.1 $\hat W_{iy + ix} \leftarrow \hat W_{iy + ix} + \mu \cdot n_{iy}$ \\ -\hspace{3mm}4.3 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\ -Propagate carries upwards. \\ -5. for $ix$ from $n.used$ to $2n.used + 1$ do \\ -\hspace{3mm}5.1 $\hat W_{ix + 1} \leftarrow \hat W_{ix + 1} + \lfloor \hat W_{ix} / \beta \rfloor$ \\ -Shift right and reduce modulo $\beta$ simultaneously. \\ -6. for $ix$ from $0$ to $n.used + 1$ do \\ -\hspace{3mm}6.1 $x_{ix} \leftarrow \hat W_{ix + n.used} \mbox{ (mod }\beta\mbox{)}$ \\ -Zero excess digits and fixup $x$. \\ -7. if $x.used > n.used + 1$ then do \\ -\hspace{3mm}7.1 for $ix$ from $n.used + 1$ to $x.used - 1$ do \\ -\hspace{6mm}7.1.1 $x_{ix} \leftarrow 0$ \\ -8. $x.used \leftarrow n.used + 1$ \\ -9. Clamp excessive digits of $x$. \\ -10. If $x \ge n$ then \\ -\hspace{3mm}10.1 $x \leftarrow x - n$ \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm fast\_mp\_montgomery\_reduce} -\end{figure} - -\textbf{Algorithm fast\_mp\_montgomery\_reduce.} -This algorithm will compute the Montgomery reduction of $x$ modulo $n$ using the Comba technique. It is on most computer platforms significantly -faster than algorithm mp\_montgomery\_reduce and algorithm mp\_reduce (\textit{Barrett reduction}). The algorithm has the same restrictions -on the input as the baseline reduction algorithm. An additional two restrictions are imposed on this algorithm. The number of digits $k$ in the -the modulus $n$ must not violate $MP\_WARRAY > 2k +1$ and $n < \delta$. When $\beta = 2^{28}$ this algorithm can be used to reduce modulo -a modulus of at most $3,556$ bits in length. - -As in the other Comba reduction algorithms there is a $\hat W$ array which stores the columns of the product. It is initially filled with the -contents of $x$ with the excess digits zeroed. The reduction loop is very similar the to the baseline loop at heart. The multiplication on step -4.1 can be single precision only since $ab \mbox{ (mod }\beta\mbox{)} \equiv (a \mbox{ mod }\beta)(b \mbox{ mod }\beta)$. Some multipliers such -as those on the ARM processors take a variable length time to complete depending on the number of bytes of result it must produce. By performing -a single precision multiplication instead half the amount of time is spent. - -Also note that digit $\hat W_{ix}$ must have the carry from the $ix - 1$'th digit propagated upwards in order for this to work. That is what step -4.3 will do. In effect over the $n.used$ iterations of the outer loop the $n.used$'th lower columns all have the their carries propagated forwards. Note -how the upper bits of those same words are not reduced modulo $\beta$. This is because those values will be discarded shortly and there is no -point. - -Step 5 will propagate the remainder of the carries upwards. On step 6 the columns are reduced modulo $\beta$ and shifted simultaneously as they are -stored in the destination $x$. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_fast\_mp\_montgomery\_reduce.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The $\hat W$ array is first filled with digits of $x$ on line 48 then the rest of the digits are zeroed on line 55. Both loops share -the same alias variables to make the code easier to read. - -The value of $\mu$ is calculated in an interesting fashion. First the value $\hat W_{ix}$ is reduced modulo $\beta$ and cast to a mp\_digit. This -forces the compiler to use a single precision multiplication and prevents any concerns about loss of precision. Line 110 fixes the carry -for the next iteration of the loop by propagating the carry from $\hat W_{ix}$ to $\hat W_{ix+1}$. - -The for loop on line 109 propagates the rest of the carries upwards through the columns. The for loop on line 126 reduces the columns -modulo $\beta$ and shifts them $k$ places at the same time. The alias $\_ \hat W$ actually refers to the array $\hat W$ starting at the $n.used$'th -digit, that is $\_ \hat W_{t} = \hat W_{n.used + t}$. - -\subsection{Montgomery Setup} -To calculate the variable $\rho$ a relatively simple algorithm will be required. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_montgomery\_setup}. \\ -\textbf{Input}. mp\_int $n$ ($n > 1$ and $(n, 2) = 1$) \\ -\textbf{Output}. $\rho \equiv -1/n_0 \mbox{ (mod }\beta\mbox{)}$ \\ -\hline \\ -1. $b \leftarrow n_0$ \\ -2. If $b$ is even return(\textit{MP\_VAL}) \\ -3. $x \leftarrow (((b + 2) \mbox{ AND } 4) << 1) + b$ \\ -4. for $k$ from 0 to $\lceil lg(lg(\beta)) \rceil - 2$ do \\ -\hspace{3mm}4.1 $x \leftarrow x \cdot (2 - bx)$ \\ -5. $\rho \leftarrow \beta - x \mbox{ (mod }\beta\mbox{)}$ \\ -6. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_montgomery\_setup} -\end{figure} - -\textbf{Algorithm mp\_montgomery\_setup.} -This algorithm will calculate the value of $\rho$ required within the Montgomery reduction algorithms. It uses a very interesting trick -to calculate $1/n_0$ when $\beta$ is a power of two. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_montgomery\_setup.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This source code computes the value of $\rho$ required to perform Montgomery reduction. It has been modified to avoid performing excess -multiplications when $\beta$ is not the default 28-bits. - -\section{The Diminished Radix Algorithm} -The Diminished Radix method of modular reduction \cite{DRMET} is a fairly clever technique which can be more efficient than either the Barrett -or Montgomery methods for certain forms of moduli. The technique is based on the following simple congruence. - -\begin{equation} -(x \mbox{ mod } n) + k \lfloor x / n \rfloor \equiv x \mbox{ (mod }(n - k)\mbox{)} -\end{equation} - -This observation was used in the MMB \cite{MMB} block cipher to create a diffusion primitive. It used the fact that if $n = 2^{31}$ and $k=1$ that -then a x86 multiplier could produce the 62-bit product and use the ``shrd'' instruction to perform a double-precision right shift. The proof -of the above equation is very simple. First write $x$ in the product form. - -\begin{equation} -x = qn + r -\end{equation} - -Now reduce both sides modulo $(n - k)$. - -\begin{equation} -x \equiv qk + r \mbox{ (mod }(n-k)\mbox{)} -\end{equation} - -The variable $n$ reduces modulo $n - k$ to $k$. By putting $q = \lfloor x/n \rfloor$ and $r = x \mbox{ mod } n$ -into the equation the original congruence is reproduced, thus concluding the proof. The following algorithm is based on this observation. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Diminished Radix Reduction}. \\ -\textbf{Input}. Integer $x$, $n$, $k$ \\ -\textbf{Output}. $x \mbox{ mod } (n - k)$ \\ -\hline \\ -1. $q \leftarrow \lfloor x / n \rfloor$ \\ -2. $q \leftarrow k \cdot q$ \\ -3. $x \leftarrow x \mbox{ (mod }n\mbox{)}$ \\ -4. $x \leftarrow x + q$ \\ -5. If $x \ge (n - k)$ then \\ -\hspace{3mm}5.1 $x \leftarrow x - (n - k)$ \\ -\hspace{3mm}5.2 Goto step 1. \\ -6. Return $x$ \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Diminished Radix Reduction} -\label{fig:DR} -\end{figure} - -This algorithm will reduce $x$ modulo $n - k$ and return the residue. If $0 \le x < (n - k)^2$ then the algorithm will loop almost always -once or twice and occasionally three times. For simplicity sake the value of $x$ is bounded by the following simple polynomial. - -\begin{equation} -0 \le x < n^2 + k^2 - 2nk -\end{equation} - -The true bound is $0 \le x < (n - k - 1)^2$ but this has quite a few more terms. The value of $q$ after step 1 is bounded by the following. - -\begin{equation} -q < n - 2k - k^2/n -\end{equation} - -Since $k^2$ is going to be considerably smaller than $n$ that term will always be zero. The value of $x$ after step 3 is bounded trivially as -$0 \le x < n$. By step four the sum $x + q$ is bounded by - -\begin{equation} -0 \le q + x < (k + 1)n - 2k^2 - 1 -\end{equation} - -With a second pass $q$ will be loosely bounded by $0 \le q < k^2$ after step 2 while $x$ will still be loosely bounded by $0 \le x < n$ after step 3. After the second pass it is highly unlike that the -sum in step 4 will exceed $n - k$. In practice fewer than three passes of the algorithm are required to reduce virtually every input in the -range $0 \le x < (n - k - 1)^2$. - -\begin{figure} -\begin{small} -\begin{center} -\begin{tabular}{|l|} -\hline -$x = 123456789, n = 256, k = 3$ \\ -\hline $q \leftarrow \lfloor x/n \rfloor = 482253$ \\ -$q \leftarrow q*k = 1446759$ \\ -$x \leftarrow x \mbox{ mod } n = 21$ \\ -$x \leftarrow x + q = 1446780$ \\ -$x \leftarrow x - (n - k) = 1446527$ \\ -\hline -$q \leftarrow \lfloor x/n \rfloor = 5650$ \\ -$q \leftarrow q*k = 16950$ \\ -$x \leftarrow x \mbox{ mod } n = 127$ \\ -$x \leftarrow x + q = 17077$ \\ -$x \leftarrow x - (n - k) = 16824$ \\ -\hline -$q \leftarrow \lfloor x/n \rfloor = 65$ \\ -$q \leftarrow q*k = 195$ \\ -$x \leftarrow x \mbox{ mod } n = 184$ \\ -$x \leftarrow x + q = 379$ \\ -$x \leftarrow x - (n - k) = 126$ \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Example Diminished Radix Reduction} -\label{fig:EXDR} -\end{figure} - -Figure~\ref{fig:EXDR} demonstrates the reduction of $x = 123456789$ modulo $n - k = 253$ when $n = 256$ and $k = 3$. Note that even while $x$ -is considerably larger than $(n - k - 1)^2 = 63504$ the algorithm still converges on the modular residue exceedingly fast. In this case only -three passes were required to find the residue $x \equiv 126$. - - -\subsection{Choice of Moduli} -On the surface this algorithm looks like a very expensive algorithm. It requires a couple of subtractions followed by multiplication and other -modular reductions. The usefulness of this algorithm becomes exceedingly clear when an appropriate modulus is chosen. - -Division in general is a very expensive operation to perform. The one exception is when the division is by a power of the radix of representation used. -Division by ten for example is simple for pencil and paper mathematics since it amounts to shifting the decimal place to the right. Similarly division -by two (\textit{or powers of two}) is very simple for binary computers to perform. It would therefore seem logical to choose $n$ of the form $2^p$ -which would imply that $\lfloor x / n \rfloor$ is a simple shift of $x$ right $p$ bits. - -However, there is one operation related to division of power of twos that is even faster than this. If $n = \beta^p$ then the division may be -performed by moving whole digits to the right $p$ places. In practice division by $\beta^p$ is much faster than division by $2^p$ for any $p$. -Also with the choice of $n = \beta^p$ reducing $x$ modulo $n$ merely requires zeroing the digits above the $p-1$'th digit of $x$. - -Throughout the next section the term ``restricted modulus'' will refer to a modulus of the form $\beta^p - k$ whereas the term ``unrestricted -modulus'' will refer to a modulus of the form $2^p - k$. The word ``restricted'' in this case refers to the fact that it is based on the -$2^p$ logic except $p$ must be a multiple of $lg(\beta)$. - -\subsection{Choice of $k$} -Now that division and reduction (\textit{step 1 and 3 of figure~\ref{fig:DR}}) have been optimized to simple digit operations the multiplication by $k$ -in step 2 is the most expensive operation. Fortunately the choice of $k$ is not terribly limited. For all intents and purposes it might -as well be a single digit. The smaller the value of $k$ is the faster the algorithm will be. - -\subsection{Restricted Diminished Radix Reduction} -The restricted Diminished Radix algorithm can quickly reduce an input modulo a modulus of the form $n = \beta^p - k$. This algorithm can reduce -an input $x$ within the range $0 \le x < n^2$ using only a couple passes of the algorithm demonstrated in figure~\ref{fig:DR}. The implementation -of this algorithm has been optimized to avoid additional overhead associated with a division by $\beta^p$, the multiplication by $k$ or the addition -of $x$ and $q$. The resulting algorithm is very efficient and can lead to substantial improvements over Barrett and Montgomery reduction when modular -exponentiations are performed. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_dr\_reduce}. \\ -\textbf{Input}. mp\_int $x$, $n$ and a mp\_digit $k = \beta - n_0$ \\ -\hspace{11.5mm}($0 \le x < n^2$, $n > 1$, $0 < k < \beta$) \\ -\textbf{Output}. $x \mbox{ mod } n$ \\ -\hline \\ -1. $m \leftarrow n.used$ \\ -2. If $x.alloc < 2m$ then grow $x$ to $2m$ digits. \\ -3. $\mu \leftarrow 0$ \\ -4. for $i$ from $0$ to $m - 1$ do \\ -\hspace{3mm}4.1 $\hat r \leftarrow k \cdot x_{m+i} + x_{i} + \mu$ \\ -\hspace{3mm}4.2 $x_{i} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}4.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -5. $x_{m} \leftarrow \mu$ \\ -6. for $i$ from $m + 1$ to $x.used - 1$ do \\ -\hspace{3mm}6.1 $x_{i} \leftarrow 0$ \\ -7. Clamp excess digits of $x$. \\ -8. If $x \ge n$ then \\ -\hspace{3mm}8.1 $x \leftarrow x - n$ \\ -\hspace{3mm}8.2 Goto step 3. \\ -9. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_dr\_reduce} -\end{figure} - -\textbf{Algorithm mp\_dr\_reduce.} -This algorithm will perform the Dimished Radix reduction of $x$ modulo $n$. It has similar restrictions to that of the Barrett reduction -with the addition that $n$ must be of the form $n = \beta^m - k$ where $0 < k <\beta$. - -This algorithm essentially implements the pseudo-code in figure~\ref{fig:DR} except with a slight optimization. The division by $\beta^m$, multiplication by $k$ -and addition of $x \mbox{ mod }\beta^m$ are all performed simultaneously inside the loop on step 4. The division by $\beta^m$ is emulated by accessing -the term at the $m+i$'th position which is subsequently multiplied by $k$ and added to the term at the $i$'th position. After the loop the $m$'th -digit is set to the carry and the upper digits are zeroed. Steps 5 and 6 emulate the reduction modulo $\beta^m$ that should have happend to -$x$ before the addition of the multiple of the upper half. - -At step 8 if $x$ is still larger than $n$ another pass of the algorithm is required. First $n$ is subtracted from $x$ and then the algorithm resumes -at step 3. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_reduce.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The first step is to grow $x$ as required to $2m$ digits since the reduction is performed in place on $x$. The label on line 52 is where -the algorithm will resume if further reduction passes are required. In theory it could be placed at the top of the function however, the size of -the modulus and question of whether $x$ is large enough are invariant after the first pass meaning that it would be a waste of time. - -The aliases $tmpx1$ and $tmpx2$ refer to the digits of $x$ where the latter is offset by $m$ digits. By reading digits from $x$ offset by $m$ digits -a division by $\beta^m$ can be simulated virtually for free. The loop on line 64 performs the bulk of the work (\textit{corresponds to step 4 of algorithm 7.11}) -in this algorithm. - -By line 67 the pointer $tmpx1$ points to the $m$'th digit of $x$ which is where the final carry will be placed. Similarly by line 74 the -same pointer will point to the $m+1$'th digit where the zeroes will be placed. - -Since the algorithm is only valid if both $x$ and $n$ are greater than zero an unsigned comparison suffices to determine if another pass is required. -With the same logic at line 81 the value of $x$ is known to be greater than or equal to $n$ meaning that an unsigned subtraction can be used -as well. Since the destination of the subtraction is the larger of the inputs the call to algorithm s\_mp\_sub cannot fail and the return code -does not need to be checked. - -\subsubsection{Setup} -To setup the restricted Diminished Radix algorithm the value $k = \beta - n_0$ is required. This algorithm is not really complicated but provided for -completeness. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_dr\_setup}. \\ -\textbf{Input}. mp\_int $n$ \\ -\textbf{Output}. $k = \beta - n_0$ \\ -\hline \\ -1. $k \leftarrow \beta - n_0$ \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_dr\_setup} -\end{figure} - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_setup.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\subsubsection{Modulus Detection} -Another algorithm which will be useful is the ability to detect a restricted Diminished Radix modulus. An integer is said to be -of restricted Diminished Radix form if all of the digits are equal to $\beta - 1$ except the trailing digit which may be any value. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_dr\_is\_modulus}. \\ -\textbf{Input}. mp\_int $n$ \\ -\textbf{Output}. $1$ if $n$ is in D.R form, $0$ otherwise \\ -\hline -1. If $n.used < 2$ then return($0$). \\ -2. for $ix$ from $1$ to $n.used - 1$ do \\ -\hspace{3mm}2.1 If $n_{ix} \ne \beta - 1$ return($0$). \\ -3. Return($1$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_dr\_is\_modulus} -\end{figure} - -\textbf{Algorithm mp\_dr\_is\_modulus.} -This algorithm determines if a value is in Diminished Radix form. Step 1 rejects obvious cases where fewer than two digits are -in the mp\_int. Step 2 tests all but the first digit to see if they are equal to $\beta - 1$. If the algorithm manages to get to -step 3 then $n$ must be of Diminished Radix form. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_dr\_is\_modulus.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\subsection{Unrestricted Diminished Radix Reduction} -The unrestricted Diminished Radix algorithm allows modular reductions to be performed when the modulus is of the form $2^p - k$. This algorithm -is a straightforward adaptation of algorithm~\ref{fig:DR}. - -In general the restricted Diminished Radix reduction algorithm is much faster since it has considerably lower overhead. However, this new -algorithm is much faster than either Montgomery or Barrett reduction when the moduli are of the appropriate form. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_reduce\_2k}. \\ -\textbf{Input}. mp\_int $a$ and $n$. mp\_digit $k$ \\ -\hspace{11.5mm}($a \ge 0$, $n > 1$, $0 < k < \beta$, $n + k$ is a power of two) \\ -\textbf{Output}. $a \mbox{ (mod }n\mbox{)}$ \\ -\hline -1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ -2. While $a \ge n$ do \\ -\hspace{3mm}2.1 $q \leftarrow \lfloor a / 2^p \rfloor$ (\textit{mp\_div\_2d}) \\ -\hspace{3mm}2.2 $a \leftarrow a \mbox{ (mod }2^p\mbox{)}$ (\textit{mp\_mod\_2d}) \\ -\hspace{3mm}2.3 $q \leftarrow q \cdot k$ (\textit{mp\_mul\_d}) \\ -\hspace{3mm}2.4 $a \leftarrow a - q$ (\textit{s\_mp\_sub}) \\ -\hspace{3mm}2.5 If $a \ge n$ then do \\ -\hspace{6mm}2.5.1 $a \leftarrow a - n$ \\ -3. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_reduce\_2k} -\end{figure} - -\textbf{Algorithm mp\_reduce\_2k.} -This algorithm quickly reduces an input $a$ modulo an unrestricted Diminished Radix modulus $n$. Division by $2^p$ is emulated with a right -shift which makes the algorithm fairly inexpensive to use. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The algorithm mp\_count\_bits calculates the number of bits in an mp\_int which is used to find the initial value of $p$. The call to mp\_div\_2d -on line 31 calculates both the quotient $q$ and the remainder $a$ required. By doing both in a single function call the code size -is kept fairly small. The multiplication by $k$ is only performed if $k > 1$. This allows reductions modulo $2^p - 1$ to be performed without -any multiplications. - -The unsigned s\_mp\_add, mp\_cmp\_mag and s\_mp\_sub are used in place of their full sign counterparts since the inputs are only valid if they are -positive. By using the unsigned versions the overhead is kept to a minimum. - -\subsubsection{Unrestricted Setup} -To setup this reduction algorithm the value of $k = 2^p - n$ is required. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_reduce\_2k\_setup}. \\ -\textbf{Input}. mp\_int $n$ \\ -\textbf{Output}. $k = 2^p - n$ \\ -\hline -1. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ -2. $x \leftarrow 2^p$ (\textit{mp\_2expt}) \\ -3. $x \leftarrow x - n$ (\textit{mp\_sub}) \\ -4. $k \leftarrow x_0$ \\ -5. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_reduce\_2k\_setup} -\end{figure} - -\textbf{Algorithm mp\_reduce\_2k\_setup.} -This algorithm computes the value of $k$ required for the algorithm mp\_reduce\_2k. By making a temporary variable $x$ equal to $2^p$ a subtraction -is sufficient to solve for $k$. Alternatively if $n$ has more than one digit the value of $k$ is simply $\beta - n_0$. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_2k\_setup.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\subsubsection{Unrestricted Detection} -An integer $n$ is a valid unrestricted Diminished Radix modulus if either of the following are true. - -\begin{enumerate} -\item The number has only one digit. -\item The number has more than one digit and every bit from the $\beta$'th to the most significant is one. -\end{enumerate} - -If either condition is true than there is a power of two $2^p$ such that $0 < 2^p - n < \beta$. If the input is only -one digit than it will always be of the correct form. Otherwise all of the bits above the first digit must be one. This arises from the fact -that there will be value of $k$ that when added to the modulus causes a carry in the first digit which propagates all the way to the most -significant bit. The resulting sum will be a power of two. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_reduce\_is\_2k}. \\ -\textbf{Input}. mp\_int $n$ \\ -\textbf{Output}. $1$ if of proper form, $0$ otherwise \\ -\hline -1. If $n.used = 0$ then return($0$). \\ -2. If $n.used = 1$ then return($1$). \\ -3. $p \leftarrow \lceil lg(n) \rceil$ (\textit{mp\_count\_bits}) \\ -4. for $x$ from $lg(\beta)$ to $p$ do \\ -\hspace{3mm}4.1 If the ($x \mbox{ mod }lg(\beta)$)'th bit of the $\lfloor x / lg(\beta) \rfloor$ of $n$ is zero then return($0$). \\ -5. Return($1$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_reduce\_is\_2k} -\end{figure} - -\textbf{Algorithm mp\_reduce\_is\_2k.} -This algorithm quickly determines if a modulus is of the form required for algorithm mp\_reduce\_2k to function properly. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_reduce\_is\_2k.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - - - -\section{Algorithm Comparison} -So far three very different algorithms for modular reduction have been discussed. Each of the algorithms have their own strengths and weaknesses -that makes having such a selection very useful. The following table sumarizes the three algorithms along with comparisons of work factors. Since -all three algorithms have the restriction that $0 \le x < n^2$ and $n > 1$ those limitations are not included in the table. - -\begin{center} -\begin{small} -\begin{tabular}{|c|c|c|c|c|c|} -\hline \textbf{Method} & \textbf{Work Required} & \textbf{Limitations} & \textbf{$m = 8$} & \textbf{$m = 32$} & \textbf{$m = 64$} \\ -\hline Barrett & $m^2 + 2m - 1$ & None & $79$ & $1087$ & $4223$ \\ -\hline Montgomery & $m^2 + m$ & $n$ must be odd & $72$ & $1056$ & $4160$ \\ -\hline D.R. & $2m$ & $n = \beta^m - k$ & $16$ & $64$ & $128$ \\ -\hline -\end{tabular} -\end{small} -\end{center} - -In theory Montgomery and Barrett reductions would require roughly the same amount of time to complete. However, in practice since Montgomery -reduction can be written as a single function with the Comba technique it is much faster. Barrett reduction suffers from the overhead of -calling the half precision multipliers, addition and division by $\beta$ algorithms. - -For almost every cryptographic algorithm Montgomery reduction is the algorithm of choice. The one set of algorithms where Diminished Radix reduction truly -shines are based on the discrete logarithm problem such as Diffie-Hellman \cite{DH} and ElGamal \cite{ELGAMAL}. In these algorithms -primes of the form $\beta^m - k$ can be found and shared amongst users. These primes will allow the Diminished Radix algorithm to be used in -modular exponentiation to greatly speed up the operation. - - - -\section*{Exercises} -\begin{tabular}{cl} -$\left [ 3 \right ]$ & Prove that the ``trick'' in algorithm mp\_montgomery\_setup actually \\ - & calculates the correct value of $\rho$. \\ - & \\ -$\left [ 2 \right ]$ & Devise an algorithm to reduce modulo $n + k$ for small $k$ quickly. \\ - & \\ -$\left [ 4 \right ]$ & Prove that the pseudo-code algorithm ``Diminished Radix Reduction'' \\ - & (\textit{figure~\ref{fig:DR}}) terminates. Also prove the probability that it will \\ - & terminate within $1 \le k \le 10$ iterations. \\ - & \\ -\end{tabular} - - -\chapter{Exponentiation} -Exponentiation is the operation of raising one variable to the power of another, for example, $a^b$. A variant of exponentiation, computed -in a finite field or ring, is called modular exponentiation. This latter style of operation is typically used in public key -cryptosystems such as RSA and Diffie-Hellman. The ability to quickly compute modular exponentiations is of great benefit to any -such cryptosystem and many methods have been sought to speed it up. - -\section{Exponentiation Basics} -A trivial algorithm would simply multiply $a$ against itself $b - 1$ times to compute the exponentiation desired. However, as $b$ grows in size -the number of multiplications becomes prohibitive. Imagine what would happen if $b$ $\approx$ $2^{1024}$ as is the case when computing an RSA signature -with a $1024$-bit key. Such a calculation could never be completed as it would take simply far too long. - -Fortunately there is a very simple algorithm based on the laws of exponents. Recall that $lg_a(a^b) = b$ and that $lg_a(a^ba^c) = b + c$ which -are two trivial relationships between the base and the exponent. Let $b_i$ represent the $i$'th bit of $b$ starting from the least -significant bit. If $b$ is a $k$-bit integer than the following equation is true. - -\begin{equation} -a^b = \prod_{i=0}^{k-1} a^{2^i \cdot b_i} -\end{equation} - -By taking the base $a$ logarithm of both sides of the equation the following equation is the result. - -\begin{equation} -b = \sum_{i=0}^{k-1}2^i \cdot b_i -\end{equation} - -The term $a^{2^i}$ can be found from the $i - 1$'th term by squaring the term since $\left ( a^{2^i} \right )^2$ is equal to -$a^{2^{i+1}}$. This observation forms the basis of essentially all fast exponentiation algorithms. It requires $k$ squarings and on average -$k \over 2$ multiplications to compute the result. This is indeed quite an improvement over simply multiplying by $a$ a total of $b-1$ times. - -While this current method is a considerable speed up there are further improvements to be made. For example, the $a^{2^i}$ term does not need to -be computed in an auxilary variable. Consider the following equivalent algorithm. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Left to Right Exponentiation}. \\ -\textbf{Input}. Integer $a$, $b$ and $k$ \\ -\textbf{Output}. $c = a^b$ \\ -\hline \\ -1. $c \leftarrow 1$ \\ -2. for $i$ from $k - 1$ to $0$ do \\ -\hspace{3mm}2.1 $c \leftarrow c^2$ \\ -\hspace{3mm}2.2 $c \leftarrow c \cdot a^{b_i}$ \\ -3. Return $c$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Left to Right Exponentiation} -\label{fig:LTOR} -\end{figure} - -This algorithm starts from the most significant bit and works towards the least significant bit. When the $i$'th bit of $b$ is set $a$ is -multiplied against the current product. In each iteration the product is squared which doubles the exponent of the individual terms of the -product. - -For example, let $b = 101100_2 \equiv 44_{10}$. The following chart demonstrates the actions of the algorithm. - -\newpage\begin{figure} -\begin{center} -\begin{tabular}{|c|c|} -\hline \textbf{Value of $i$} & \textbf{Value of $c$} \\ -\hline - & $1$ \\ -\hline $5$ & $a$ \\ -\hline $4$ & $a^2$ \\ -\hline $3$ & $a^4 \cdot a$ \\ -\hline $2$ & $a^8 \cdot a^2 \cdot a$ \\ -\hline $1$ & $a^{16} \cdot a^4 \cdot a^2$ \\ -\hline $0$ & $a^{32} \cdot a^8 \cdot a^4$ \\ -\hline -\end{tabular} -\end{center} -\caption{Example of Left to Right Exponentiation} -\end{figure} - -When the product $a^{32} \cdot a^8 \cdot a^4$ is simplified it is equal $a^{44}$ which is the desired exponentiation. This particular algorithm is -called ``Left to Right'' because it reads the exponent in that order. All of the exponentiation algorithms that will be presented are of this nature. - -\subsection{Single Digit Exponentiation} -The first algorithm in the series of exponentiation algorithms will be an unbounded algorithm where the exponent is a single digit. It is intended -to be used when a small power of an input is required (\textit{e.g. $a^5$}). It is faster than simply multiplying $b - 1$ times for all values of -$b$ that are greater than three. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_expt\_d}. \\ -\textbf{Input}. mp\_int $a$ and mp\_digit $b$ \\ -\textbf{Output}. $c = a^b$ \\ -\hline \\ -1. $g \leftarrow a$ (\textit{mp\_init\_copy}) \\ -2. $c \leftarrow 1$ (\textit{mp\_set}) \\ -3. for $x$ from 1 to $lg(\beta)$ do \\ -\hspace{3mm}3.1 $c \leftarrow c^2$ (\textit{mp\_sqr}) \\ -\hspace{3mm}3.2 If $b$ AND $2^{lg(\beta) - 1} \ne 0$ then \\ -\hspace{6mm}3.2.1 $c \leftarrow c \cdot g$ (\textit{mp\_mul}) \\ -\hspace{3mm}3.3 $b \leftarrow b << 1$ \\ -4. Clear $g$. \\ -5. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_expt\_d} -\end{figure} - -\textbf{Algorithm mp\_expt\_d.} -This algorithm computes the value of $a$ raised to the power of a single digit $b$. It uses the left to right exponentiation algorithm to -quickly compute the exponentiation. It is loosely based on algorithm 14.79 of HAC \cite[pp. 615]{HAC} with the difference that the -exponent is a fixed width. - -A copy of $a$ is made first to allow destination variable $c$ be the same as the source variable $a$. The result is set to the initial value of -$1$ in the subsequent step. - -Inside the loop the exponent is read from the most significant bit first down to the least significant bit. First $c$ is invariably squared -on step 3.1. In the following step if the most significant bit of $b$ is one the copy of $a$ is multiplied against $c$. The value -of $b$ is shifted left one bit to make the next bit down from the most signficant bit the new most significant bit. In effect each -iteration of the loop moves the bits of the exponent $b$ upwards to the most significant location. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_expt\_d.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Line 29 sets the initial value of the result to $1$. Next the loop on line 31 steps through each bit of the exponent starting from -the most significant down towards the least significant. The invariant squaring operation placed on line 33 is performed first. After -the squaring the result $c$ is multiplied by the base $g$ if and only if the most significant bit of the exponent is set. The shift on line -47 moves all of the bits of the exponent upwards towards the most significant location. - -\section{$k$-ary Exponentiation} -When calculating an exponentiation the most time consuming bottleneck is the multiplications which are in general a small factor -slower than squaring. Recall from the previous algorithm that $b_{i}$ refers to the $i$'th bit of the exponent $b$. Suppose instead it referred to -the $i$'th $k$-bit digit of the exponent of $b$. For $k = 1$ the definitions are synonymous and for $k > 1$ algorithm~\ref{fig:KARY} -computes the same exponentiation. A group of $k$ bits from the exponent is called a \textit{window}. That is it is a small window on only a -portion of the entire exponent. Consider the following modification to the basic left to right exponentiation algorithm. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{$k$-ary Exponentiation}. \\ -\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\ -\textbf{Output}. $c = a^b$ \\ -\hline \\ -1. $c \leftarrow 1$ \\ -2. for $i$ from $t - 1$ to $0$ do \\ -\hspace{3mm}2.1 $c \leftarrow c^{2^k} $ \\ -\hspace{3mm}2.2 Extract the $i$'th $k$-bit word from $b$ and store it in $g$. \\ -\hspace{3mm}2.3 $c \leftarrow c \cdot a^g$ \\ -3. Return $c$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{$k$-ary Exponentiation} -\label{fig:KARY} -\end{figure} - -The squaring on step 2.1 can be calculated by squaring the value $c$ successively $k$ times. If the values of $a^g$ for $0 < g < 2^k$ have been -precomputed this algorithm requires only $t$ multiplications and $tk$ squarings. The table can be generated with $2^{k - 1} - 1$ squarings and -$2^{k - 1} + 1$ multiplications. This algorithm assumes that the number of bits in the exponent is evenly divisible by $k$. -However, when it is not the remaining $0 < x \le k - 1$ bits can be handled with algorithm~\ref{fig:LTOR}. - -Suppose $k = 4$ and $t = 100$. This modified algorithm will require $109$ multiplications and $408$ squarings to compute the exponentiation. The -original algorithm would on average have required $200$ multiplications and $400$ squrings to compute the same value. The total number of squarings -has increased slightly but the number of multiplications has nearly halved. - -\subsection{Optimal Values of $k$} -An optimal value of $k$ will minimize $2^{k} + \lceil n / k \rceil + n - 1$ for a fixed number of bits in the exponent $n$. The simplest -approach is to brute force search amongst the values $k = 2, 3, \ldots, 8$ for the lowest result. Table~\ref{fig:OPTK} lists optimal values of $k$ -for various exponent sizes and compares the number of multiplication and squarings required against algorithm~\ref{fig:LTOR}. - -\begin{figure}[here] -\begin{center} -\begin{small} -\begin{tabular}{|c|c|c|c|c|c|} -\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:LTOR}} \\ -\hline $16$ & $2$ & $27$ & $24$ \\ -\hline $32$ & $3$ & $49$ & $48$ \\ -\hline $64$ & $3$ & $92$ & $96$ \\ -\hline $128$ & $4$ & $175$ & $192$ \\ -\hline $256$ & $4$ & $335$ & $384$ \\ -\hline $512$ & $5$ & $645$ & $768$ \\ -\hline $1024$ & $6$ & $1257$ & $1536$ \\ -\hline $2048$ & $6$ & $2452$ & $3072$ \\ -\hline $4096$ & $7$ & $4808$ & $6144$ \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Optimal Values of $k$ for $k$-ary Exponentiation} -\label{fig:OPTK} -\end{figure} - -\subsection{Sliding-Window Exponentiation} -A simple modification to the previous algorithm is only generate the upper half of the table in the range $2^{k-1} \le g < 2^k$. Essentially -this is a table for all values of $g$ where the most significant bit of $g$ is a one. However, in order for this to be allowed in the -algorithm values of $g$ in the range $0 \le g < 2^{k-1}$ must be avoided. - -Table~\ref{fig:OPTK2} lists optimal values of $k$ for various exponent sizes and compares the work required against algorithm~\ref{fig:KARY}. - -\begin{figure}[here] -\begin{center} -\begin{small} -\begin{tabular}{|c|c|c|c|c|c|} -\hline \textbf{Exponent (bits)} & \textbf{Optimal $k$} & \textbf{Work at $k$} & \textbf{Work with ~\ref{fig:KARY}} \\ -\hline $16$ & $3$ & $24$ & $27$ \\ -\hline $32$ & $3$ & $45$ & $49$ \\ -\hline $64$ & $4$ & $87$ & $92$ \\ -\hline $128$ & $4$ & $167$ & $175$ \\ -\hline $256$ & $5$ & $322$ & $335$ \\ -\hline $512$ & $6$ & $628$ & $645$ \\ -\hline $1024$ & $6$ & $1225$ & $1257$ \\ -\hline $2048$ & $7$ & $2403$ & $2452$ \\ -\hline $4096$ & $8$ & $4735$ & $4808$ \\ -\hline -\end{tabular} -\end{small} -\end{center} -\caption{Optimal Values of $k$ for Sliding Window Exponentiation} -\label{fig:OPTK2} -\end{figure} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Sliding Window $k$-ary Exponentiation}. \\ -\textbf{Input}. Integer $a$, $b$, $k$ and $t$ \\ -\textbf{Output}. $c = a^b$ \\ -\hline \\ -1. $c \leftarrow 1$ \\ -2. for $i$ from $t - 1$ to $0$ do \\ -\hspace{3mm}2.1 If the $i$'th bit of $b$ is a zero then \\ -\hspace{6mm}2.1.1 $c \leftarrow c^2$ \\ -\hspace{3mm}2.2 else do \\ -\hspace{6mm}2.2.1 $c \leftarrow c^{2^k}$ \\ -\hspace{6mm}2.2.2 Extract the $k$ bits from $(b_{i}b_{i-1}\ldots b_{i-(k-1)})$ and store it in $g$. \\ -\hspace{6mm}2.2.3 $c \leftarrow c \cdot a^g$ \\ -\hspace{6mm}2.2.4 $i \leftarrow i - k$ \\ -3. Return $c$. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Sliding Window $k$-ary Exponentiation} -\end{figure} - -Similar to the previous algorithm this algorithm must have a special handler when fewer than $k$ bits are left in the exponent. While this -algorithm requires the same number of squarings it can potentially have fewer multiplications. The pre-computed table $a^g$ is also half -the size as the previous table. - -Consider the exponent $b = 111101011001000_2 \equiv 31432_{10}$ with $k = 3$ using both algorithms. The first algorithm will divide the exponent up as -the following five $3$-bit words $b \equiv \left ( 111, 101, 011, 001, 000 \right )_{2}$. The second algorithm will break the -exponent as $b \equiv \left ( 111, 101, 0, 110, 0, 100, 0 \right )_{2}$. The single digit $0$ in the second representation are where -a single squaring took place instead of a squaring and multiplication. In total the first method requires $10$ multiplications and $18$ -squarings. The second method requires $8$ multiplications and $18$ squarings. - -In general the sliding window method is never slower than the generic $k$-ary method and often it is slightly faster. - -\section{Modular Exponentiation} - -Modular exponentiation is essentially computing the power of a base within a finite field or ring. For example, computing -$d \equiv a^b \mbox{ (mod }c\mbox{)}$ is a modular exponentiation. Instead of first computing $a^b$ and then reducing it -modulo $c$ the intermediate result is reduced modulo $c$ after every squaring or multiplication operation. - -This guarantees that any intermediate result is bounded by $0 \le d \le c^2 - 2c + 1$ and can be reduced modulo $c$ quickly using -one of the algorithms presented in chapter six. - -Before the actual modular exponentiation algorithm can be written a wrapper algorithm must be written first. This algorithm -will allow the exponent $b$ to be negative which is computed as $c \equiv \left (1 / a \right )^{\vert b \vert} \mbox{(mod }d\mbox{)}$. The -value of $(1/a) \mbox{ mod }c$ is computed using the modular inverse (\textit{see \ref{sec;modinv}}). If no inverse exists the algorithm -terminates with an error. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_exptmod}. \\ -\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ -\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ -\hline \\ -1. If $c.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\ -2. If $b.sign = MP\_NEG$ then \\ -\hspace{3mm}2.1 $g' \leftarrow g^{-1} \mbox{ (mod }c\mbox{)}$ \\ -\hspace{3mm}2.2 $x' \leftarrow \vert x \vert$ \\ -\hspace{3mm}2.3 Compute $d \equiv g'^{x'} \mbox{ (mod }c\mbox{)}$ via recursion. \\ -3. if $p$ is odd \textbf{OR} $p$ is a D.R. modulus then \\ -\hspace{3mm}3.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm mp\_exptmod\_fast. \\ -4. else \\ -\hspace{3mm}4.1 Compute $y \equiv g^{x} \mbox{ (mod }p\mbox{)}$ via algorithm s\_mp\_exptmod. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_exptmod} -\end{figure} - -\textbf{Algorithm mp\_exptmod.} -The first algorithm which actually performs modular exponentiation is algorithm s\_mp\_exptmod. It is a sliding window $k$-ary algorithm -which uses Barrett reduction to reduce the product modulo $p$. The second algorithm mp\_exptmod\_fast performs the same operation -except it uses either Montgomery or Diminished Radix reduction. The two latter reduction algorithms are clumped in the same exponentiation -algorithm since their arguments are essentially the same (\textit{two mp\_ints and one mp\_digit}). - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_exptmod.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -In order to keep the algorithms in a known state the first step on line 29 is to reject any negative modulus as input. If the exponent is -negative the algorithm tries to perform a modular exponentiation with the modular inverse of the base $G$. The temporary variable $tmpG$ is assigned -the modular inverse of $G$ and $tmpX$ is assigned the absolute value of $X$. The algorithm will recuse with these new values with a positive -exponent. - -If the exponent is positive the algorithm resumes the exponentiation. Line 77 determines if the modulus is of the restricted Diminished Radix -form. If it is not line 70 attempts to determine if it is of a unrestricted Diminished Radix form. The integer $dr$ will take on one -of three values. - -\begin{enumerate} -\item $dr = 0$ means that the modulus is not of either restricted or unrestricted Diminished Radix form. -\item $dr = 1$ means that the modulus is of restricted Diminished Radix form. -\item $dr = 2$ means that the modulus is of unrestricted Diminished Radix form. -\end{enumerate} - -Line 69 determines if the fast modular exponentiation algorithm can be used. It is allowed if $dr \ne 0$ or if the modulus is odd. Otherwise, -the slower s\_mp\_exptmod algorithm is used which uses Barrett reduction. - -\subsection{Barrett Modular Exponentiation} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_exptmod}. \\ -\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ -\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ -\hline \\ -1. $k \leftarrow lg(x)$ \\ -2. $winsize \leftarrow \left \lbrace \begin{array}{ll} - 2 & \mbox{if }k \le 7 \\ - 3 & \mbox{if }7 < k \le 36 \\ - 4 & \mbox{if }36 < k \le 140 \\ - 5 & \mbox{if }140 < k \le 450 \\ - 6 & \mbox{if }450 < k \le 1303 \\ - 7 & \mbox{if }1303 < k \le 3529 \\ - 8 & \mbox{if }3529 < k \\ - \end{array} \right .$ \\ -3. Initialize $2^{winsize}$ mp\_ints in an array named $M$ and one mp\_int named $\mu$ \\ -4. Calculate the $\mu$ required for Barrett Reduction (\textit{mp\_reduce\_setup}). \\ -5. $M_1 \leftarrow g \mbox{ (mod }p\mbox{)}$ \\ -\\ -Setup the table of small powers of $g$. First find $g^{2^{winsize}}$ and then all multiples of it. \\ -6. $k \leftarrow 2^{winsize - 1}$ \\ -7. $M_{k} \leftarrow M_1$ \\ -8. for $ix$ from 0 to $winsize - 2$ do \\ -\hspace{3mm}8.1 $M_k \leftarrow \left ( M_k \right )^2$ (\textit{mp\_sqr}) \\ -\hspace{3mm}8.2 $M_k \leftarrow M_k \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\ -9. for $ix$ from $2^{winsize - 1} + 1$ to $2^{winsize} - 1$ do \\ -\hspace{3mm}9.1 $M_{ix} \leftarrow M_{ix - 1} \cdot M_{1}$ (\textit{mp\_mul}) \\ -\hspace{3mm}9.2 $M_{ix} \leftarrow M_{ix} \mbox{ (mod }p\mbox{)}$ (\textit{mp\_reduce}) \\ -10. $res \leftarrow 1$ \\ -\\ -Start Sliding Window. \\ -11. $mode \leftarrow 0, bitcnt \leftarrow 1, buf \leftarrow 0, digidx \leftarrow x.used - 1, bitcpy \leftarrow 0, bitbuf \leftarrow 0$ \\ -12. Loop \\ -\hspace{3mm}12.1 $bitcnt \leftarrow bitcnt - 1$ \\ -\hspace{3mm}12.2 If $bitcnt = 0$ then do \\ -\hspace{6mm}12.2.1 If $digidx = -1$ goto step 13. \\ -\hspace{6mm}12.2.2 $buf \leftarrow x_{digidx}$ \\ -\hspace{6mm}12.2.3 $digidx \leftarrow digidx - 1$ \\ -\hspace{6mm}12.2.4 $bitcnt \leftarrow lg(\beta)$ \\ -Continued on next page. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm s\_mp\_exptmod} -\end{figure} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{s\_mp\_exptmod} (\textit{continued}). \\ -\textbf{Input}. mp\_int $a$, $b$ and $c$ \\ -\textbf{Output}. $y \equiv g^x \mbox{ (mod }p\mbox{)}$ \\ -\hline \\ -\hspace{3mm}12.3 $y \leftarrow (buf >> (lg(\beta) - 1))$ AND $1$ \\ -\hspace{3mm}12.4 $buf \leftarrow buf << 1$ \\ -\hspace{3mm}12.5 if $mode = 0$ and $y = 0$ then goto step 12. \\ -\hspace{3mm}12.6 if $mode = 1$ and $y = 0$ then do \\ -\hspace{6mm}12.6.1 $res \leftarrow res^2$ \\ -\hspace{6mm}12.6.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ -\hspace{6mm}12.6.3 Goto step 12. \\ -\hspace{3mm}12.7 $bitcpy \leftarrow bitcpy + 1$ \\ -\hspace{3mm}12.8 $bitbuf \leftarrow bitbuf + (y << (winsize - bitcpy))$ \\ -\hspace{3mm}12.9 $mode \leftarrow 2$ \\ -\hspace{3mm}12.10 If $bitcpy = winsize$ then do \\ -\hspace{6mm}Window is full so perform the squarings and single multiplication. \\ -\hspace{6mm}12.10.1 for $ix$ from $0$ to $winsize -1$ do \\ -\hspace{9mm}12.10.1.1 $res \leftarrow res^2$ \\ -\hspace{9mm}12.10.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ -\hspace{6mm}12.10.2 $res \leftarrow res \cdot M_{bitbuf}$ \\ -\hspace{6mm}12.10.3 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ -\hspace{6mm}Reset the window. \\ -\hspace{6mm}12.10.4 $bitcpy \leftarrow 0, bitbuf \leftarrow 0, mode \leftarrow 1$ \\ -\\ -No more windows left. Check for residual bits of exponent. \\ -13. If $mode = 2$ and $bitcpy > 0$ then do \\ -\hspace{3mm}13.1 for $ix$ form $0$ to $bitcpy - 1$ do \\ -\hspace{6mm}13.1.1 $res \leftarrow res^2$ \\ -\hspace{6mm}13.1.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ -\hspace{6mm}13.1.3 $bitbuf \leftarrow bitbuf << 1$ \\ -\hspace{6mm}13.1.4 If $bitbuf$ AND $2^{winsize} \ne 0$ then do \\ -\hspace{9mm}13.1.4.1 $res \leftarrow res \cdot M_{1}$ \\ -\hspace{9mm}13.1.4.2 $res \leftarrow res \mbox{ (mod }p\mbox{)}$ \\ -14. $y \leftarrow res$ \\ -15. Clear $res$, $mu$ and the $M$ array. \\ -16. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm s\_mp\_exptmod (continued)} -\end{figure} - -\textbf{Algorithm s\_mp\_exptmod.} -This algorithm computes the $x$'th power of $g$ modulo $p$ and stores the result in $y$. It takes advantage of the Barrett reduction -algorithm to keep the product small throughout the algorithm. - -The first two steps determine the optimal window size based on the number of bits in the exponent. The larger the exponent the -larger the window size becomes. After a window size $winsize$ has been chosen an array of $2^{winsize}$ mp\_int variables is allocated. This -table will hold the values of $g^x \mbox{ (mod }p\mbox{)}$ for $2^{winsize - 1} \le x < 2^{winsize}$. - -After the table is allocated the first power of $g$ is found. Since $g \ge p$ is allowed it must be first reduced modulo $p$ to make -the rest of the algorithm more efficient. The first element of the table at $2^{winsize - 1}$ is found by squaring $M_1$ successively $winsize - 2$ -times. The rest of the table elements are found by multiplying the previous element by $M_1$ modulo $p$. - -Now that the table is available the sliding window may begin. The following list describes the functions of all the variables in the window. -\begin{enumerate} -\item The variable $mode$ dictates how the bits of the exponent are interpreted. -\begin{enumerate} - \item When $mode = 0$ the bits are ignored since no non-zero bit of the exponent has been seen yet. For example, if the exponent were simply - $1$ then there would be $lg(\beta) - 1$ zero bits before the first non-zero bit. In this case bits are ignored until a non-zero bit is found. - \item When $mode = 1$ a non-zero bit has been seen before and a new $winsize$-bit window has not been formed yet. In this mode leading $0$ bits - are read and a single squaring is performed. If a non-zero bit is read a new window is created. - \item When $mode = 2$ the algorithm is in the middle of forming a window and new bits are appended to the window from the most significant bit - downwards. -\end{enumerate} -\item The variable $bitcnt$ indicates how many bits are left in the current digit of the exponent left to be read. When it reaches zero a new digit - is fetched from the exponent. -\item The variable $buf$ holds the currently read digit of the exponent. -\item The variable $digidx$ is an index into the exponents digits. It starts at the leading digit $x.used - 1$ and moves towards the trailing digit. -\item The variable $bitcpy$ indicates how many bits are in the currently formed window. When it reaches $winsize$ the window is flushed and - the appropriate operations performed. -\item The variable $bitbuf$ holds the current bits of the window being formed. -\end{enumerate} - -All of step 12 is the window processing loop. It will iterate while there are digits available form the exponent to read. The first step -inside this loop is to extract a new digit if no more bits are available in the current digit. If there are no bits left a new digit is -read and if there are no digits left than the loop terminates. - -After a digit is made available step 12.3 will extract the most significant bit of the current digit and move all other bits in the digit -upwards. In effect the digit is read from most significant bit to least significant bit and since the digits are read from leading to -trailing edges the entire exponent is read from most significant bit to least significant bit. - -At step 12.5 if the $mode$ and currently extracted bit $y$ are both zero the bit is ignored and the next bit is read. This prevents the -algorithm from having to perform trivial squaring and reduction operations before the first non-zero bit is read. Step 12.6 and 12.7-10 handle -the two cases of $mode = 1$ and $mode = 2$ respectively. - -\begin{center} -\begin{figure}[here] -\includegraphics{pics/expt_state.ps} -\caption{Sliding Window State Diagram} -\label{pic:expt_state} -\end{figure} -\end{center} - -By step 13 there are no more digits left in the exponent. However, there may be partial bits in the window left. If $mode = 2$ then -a Left-to-Right algorithm is used to process the remaining few bits. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_s\_mp\_exptmod.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Lines 32 through 46 determine the optimal window size based on the length of the exponent in bits. The window divisions are sorted -from smallest to greatest so that in each \textbf{if} statement only one condition must be tested. For example, by the \textbf{if} statement -on line 38 the value of $x$ is already known to be greater than $140$. - -The conditional piece of code beginning on line 48 allows the window size to be restricted to five bits. This logic is used to ensure -the table of precomputed powers of $G$ remains relatively small. - -The for loop on line 61 initializes the $M$ array while lines 72 and 77 through 86 initialize the reduction -function that will be used for this modulus. - --- More later. - -\section{Quick Power of Two} -Calculating $b = 2^a$ can be performed much quicker than with any of the previous algorithms. Recall that a logical shift left $m << k$ is -equivalent to $m \cdot 2^k$. By this logic when $m = 1$ a quick power of two can be achieved. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_2expt}. \\ -\textbf{Input}. integer $b$ \\ -\textbf{Output}. $a \leftarrow 2^b$ \\ -\hline \\ -1. $a \leftarrow 0$ \\ -2. If $a.alloc < \lfloor b / lg(\beta) \rfloor + 1$ then grow $a$ appropriately. \\ -3. $a.used \leftarrow \lfloor b / lg(\beta) \rfloor + 1$ \\ -4. $a_{\lfloor b / lg(\beta) \rfloor} \leftarrow 1 << (b \mbox{ mod } lg(\beta))$ \\ -5. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_2expt} -\end{figure} - -\textbf{Algorithm mp\_2expt.} - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_2expt.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\chapter{Higher Level Algorithms} - -This chapter discusses the various higher level algorithms that are required to complete a well rounded multiple precision integer package. These -routines are less performance oriented than the algorithms of chapters five, six and seven but are no less important. - -The first section describes a method of integer division with remainder that is universally well known. It provides the signed division logic -for the package. The subsequent section discusses a set of algorithms which allow a single digit to be the 2nd operand for a variety of operations. -These algorithms serve mostly to simplify other algorithms where small constants are required. The last two sections discuss how to manipulate -various representations of integers. For example, converting from an mp\_int to a string of character. - -\section{Integer Division with Remainder} -\label{sec:division} - -Integer division aside from modular exponentiation is the most intensive algorithm to compute. Like addition, subtraction and multiplication -the basis of this algorithm is the long-hand division algorithm taught to school children. Throughout this discussion several common variables -will be used. Let $x$ represent the divisor and $y$ represent the dividend. Let $q$ represent the integer quotient $\lfloor y / x \rfloor$ and -let $r$ represent the remainder $r = y - x \lfloor y / x \rfloor$. The following simple algorithm will be used to start the discussion. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Radix-$\beta$ Integer Division}. \\ -\textbf{Input}. integer $x$ and $y$ \\ -\textbf{Output}. $q = \lfloor y/x\rfloor, r = y - xq$ \\ -\hline \\ -1. $q \leftarrow 0$ \\ -2. $n \leftarrow \vert \vert y \vert \vert - \vert \vert x \vert \vert$ \\ -3. for $t$ from $n$ down to $0$ do \\ -\hspace{3mm}3.1 Maximize $k$ such that $kx\beta^t$ is less than or equal to $y$ and $(k + 1)x\beta^t$ is greater. \\ -\hspace{3mm}3.2 $q \leftarrow q + k\beta^t$ \\ -\hspace{3mm}3.3 $y \leftarrow y - kx\beta^t$ \\ -4. $r \leftarrow y$ \\ -5. Return($q, r$) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Radix-$\beta$ Integer Division} -\label{fig:raddiv} -\end{figure} - -As children we are taught this very simple algorithm for the case of $\beta = 10$. Almost instinctively several optimizations are taught for which -their reason of existing are never explained. For this example let $y = 5471$ represent the dividend and $x = 23$ represent the divisor. - -To find the first digit of the quotient the value of $k$ must be maximized such that $kx\beta^t$ is less than or equal to $y$ and -simultaneously $(k + 1)x\beta^t$ is greater than $y$. Implicitly $k$ is the maximum value the $t$'th digit of the quotient may have. The habitual method -used to find the maximum is to ``eyeball'' the two numbers, typically only the leading digits and quickly estimate a quotient. By only using leading -digits a much simpler division may be used to form an educated guess at what the value must be. In this case $k = \lfloor 54/23\rfloor = 2$ quickly -arises as a possible solution. Indeed $2x\beta^2 = 4600$ is less than $y = 5471$ and simultaneously $(k + 1)x\beta^2 = 6900$ is larger than $y$. -As a result $k\beta^2$ is added to the quotient which now equals $q = 200$ and $4600$ is subtracted from $y$ to give a remainder of $y = 841$. - -Again this process is repeated to produce the quotient digit $k = 3$ which makes the quotient $q = 200 + 3\beta = 230$ and the remainder -$y = 841 - 3x\beta = 181$. Finally the last iteration of the loop produces $k = 7$ which leads to the quotient $q = 230 + 7 = 237$ and the -remainder $y = 181 - 7x = 20$. The final quotient and remainder found are $q = 237$ and $r = y = 20$ which are indeed correct since -$237 \cdot 23 + 20 = 5471$ is true. - -\subsection{Quotient Estimation} -\label{sec:divest} -As alluded to earlier the quotient digit $k$ can be estimated from only the leading digits of both the divisor and dividend. When $p$ leading -digits are used from both the divisor and dividend to form an estimation the accuracy of the estimation rises as $p$ grows. Technically -speaking the estimation is based on assuming the lower $\vert \vert y \vert \vert - p$ and $\vert \vert x \vert \vert - p$ lower digits of the -dividend and divisor are zero. - -The value of the estimation may off by a few values in either direction and in general is fairly correct. A simplification \cite[pp. 271]{TAOCPV2} -of the estimation technique is to use $t + 1$ digits of the dividend and $t$ digits of the divisor, in particularly when $t = 1$. The estimate -using this technique is never too small. For the following proof let $t = \vert \vert y \vert \vert - 1$ and $s = \vert \vert x \vert \vert - 1$ -represent the most significant digits of the dividend and divisor respectively. - -\textbf{Proof.}\textit{ The quotient $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ is greater than or equal to -$k = \lfloor y / (x \cdot \beta^{\vert \vert y \vert \vert - \vert \vert x \vert \vert - 1}) \rfloor$. } -The first obvious case is when $\hat k = \beta - 1$ in which case the proof is concluded since the real quotient cannot be larger. For all other -cases $\hat k = \lfloor (y_t\beta + y_{t-1}) / x_s \rfloor$ and $\hat k x_s \ge y_t\beta + y_{t-1} - x_s + 1$. The latter portion of the inequalility -$-x_s + 1$ arises from the fact that a truncated integer division will give the same quotient for at most $x_s - 1$ values. Next a series of -inequalities will prove the hypothesis. - -\begin{equation} -y - \hat k x \le y - \hat k x_s\beta^s -\end{equation} - -This is trivially true since $x \ge x_s\beta^s$. Next we replace $\hat kx_s\beta^s$ by the previous inequality for $\hat kx_s$. - -\begin{equation} -y - \hat k x \le y_t\beta^t + \ldots + y_0 - (y_t\beta^t + y_{t-1}\beta^{t-1} - x_s\beta^t + \beta^s) -\end{equation} - -By simplifying the previous inequality the following inequality is formed. - -\begin{equation} -y - \hat k x \le y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s -\end{equation} - -Subsequently, - -\begin{equation} -y_{t-2}\beta^{t-2} + \ldots + y_0 + x_s\beta^s - \beta^s < x_s\beta^s \le x -\end{equation} - -Which proves that $y - \hat kx \le x$ and by consequence $\hat k \ge k$ which concludes the proof. \textbf{QED} - - -\subsection{Normalized Integers} -For the purposes of division a normalized input is when the divisors leading digit $x_n$ is greater than or equal to $\beta / 2$. By multiplying both -$x$ and $y$ by $j = \lfloor (\beta / 2) / x_n \rfloor$ the quotient remains unchanged and the remainder is simply $j$ times the original -remainder. The purpose of normalization is to ensure the leading digit of the divisor is sufficiently large such that the estimated quotient will -lie in the domain of a single digit. Consider the maximum dividend $(\beta - 1) \cdot \beta + (\beta - 1)$ and the minimum divisor $\beta / 2$. - -\begin{equation} -{{\beta^2 - 1} \over { \beta / 2}} \le 2\beta - {2 \over \beta} -\end{equation} - -At most the quotient approaches $2\beta$, however, in practice this will not occur since that would imply the previous quotient digit was too small. - -\subsection{Radix-$\beta$ Division with Remainder} -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_div}. \\ -\textbf{Input}. mp\_int $a, b$ \\ -\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\ -\hline \\ -1. If $b = 0$ return(\textit{MP\_VAL}). \\ -2. If $\vert a \vert < \vert b \vert$ then do \\ -\hspace{3mm}2.1 $d \leftarrow a$ \\ -\hspace{3mm}2.2 $c \leftarrow 0$ \\ -\hspace{3mm}2.3 Return(\textit{MP\_OKAY}). \\ -\\ -Setup the quotient to receive the digits. \\ -3. Grow $q$ to $a.used + 2$ digits. \\ -4. $q \leftarrow 0$ \\ -5. $x \leftarrow \vert a \vert , y \leftarrow \vert b \vert$ \\ -6. $sign \leftarrow \left \lbrace \begin{array}{ll} - MP\_ZPOS & \mbox{if }a.sign = b.sign \\ - MP\_NEG & \mbox{otherwise} \\ - \end{array} \right .$ \\ -\\ -Normalize the inputs such that the leading digit of $y$ is greater than or equal to $\beta / 2$. \\ -7. $norm \leftarrow (lg(\beta) - 1) - (\lceil lg(y) \rceil \mbox{ (mod }lg(\beta)\mbox{)})$ \\ -8. $x \leftarrow x \cdot 2^{norm}, y \leftarrow y \cdot 2^{norm}$ \\ -\\ -Find the leading digit of the quotient. \\ -9. $n \leftarrow x.used - 1, t \leftarrow y.used - 1$ \\ -10. $y \leftarrow y \cdot \beta^{n - t}$ \\ -11. While ($x \ge y$) do \\ -\hspace{3mm}11.1 $q_{n - t} \leftarrow q_{n - t} + 1$ \\ -\hspace{3mm}11.2 $x \leftarrow x - y$ \\ -12. $y \leftarrow \lfloor y / \beta^{n-t} \rfloor$ \\ -\\ -Continued on the next page. \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_div} -\end{figure} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_div} (continued). \\ -\textbf{Input}. mp\_int $a, b$ \\ -\textbf{Output}. $c = \lfloor a/b \rfloor$, $d = a - bc$ \\ -\hline \\ -Now find the remainder fo the digits. \\ -13. for $i$ from $n$ down to $(t + 1)$ do \\ -\hspace{3mm}13.1 If $i > x.used$ then jump to the next iteration of this loop. \\ -\hspace{3mm}13.2 If $x_{i} = y_{t}$ then \\ -\hspace{6mm}13.2.1 $q_{i - t - 1} \leftarrow \beta - 1$ \\ -\hspace{3mm}13.3 else \\ -\hspace{6mm}13.3.1 $\hat r \leftarrow x_{i} \cdot \beta + x_{i - 1}$ \\ -\hspace{6mm}13.3.2 $\hat r \leftarrow \lfloor \hat r / y_{t} \rfloor$ \\ -\hspace{6mm}13.3.3 $q_{i - t - 1} \leftarrow \hat r$ \\ -\hspace{3mm}13.4 $q_{i - t - 1} \leftarrow q_{i - t - 1} + 1$ \\ -\\ -Fixup quotient estimation. \\ -\hspace{3mm}13.5 Loop \\ -\hspace{6mm}13.5.1 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\ -\hspace{6mm}13.5.2 t$1 \leftarrow 0$ \\ -\hspace{6mm}13.5.3 t$1_0 \leftarrow y_{t - 1}, $ t$1_1 \leftarrow y_t,$ t$1.used \leftarrow 2$ \\ -\hspace{6mm}13.5.4 $t1 \leftarrow t1 \cdot q_{i - t - 1}$ \\ -\hspace{6mm}13.5.5 t$2_0 \leftarrow x_{i - 2}, $ t$2_1 \leftarrow x_{i - 1}, $ t$2_2 \leftarrow x_i, $ t$2.used \leftarrow 3$ \\ -\hspace{6mm}13.5.6 If $\vert t1 \vert > \vert t2 \vert$ then goto step 13.5. \\ -\hspace{3mm}13.6 t$1 \leftarrow y \cdot q_{i - t - 1}$ \\ -\hspace{3mm}13.7 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\ -\hspace{3mm}13.8 $x \leftarrow x - $ t$1$ \\ -\hspace{3mm}13.9 If $x.sign = MP\_NEG$ then \\ -\hspace{6mm}13.10 t$1 \leftarrow y$ \\ -\hspace{6mm}13.11 t$1 \leftarrow $ t$1 \cdot \beta^{i - t - 1}$ \\ -\hspace{6mm}13.12 $x \leftarrow x + $ t$1$ \\ -\hspace{6mm}13.13 $q_{i - t - 1} \leftarrow q_{i - t - 1} - 1$ \\ -\\ -Finalize the result. \\ -14. Clamp excess digits of $q$ \\ -15. $c \leftarrow q, c.sign \leftarrow sign$ \\ -16. $x.sign \leftarrow a.sign$ \\ -17. $d \leftarrow \lfloor x / 2^{norm} \rfloor$ \\ -18. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_div (continued)} -\end{figure} -\textbf{Algorithm mp\_div.} -This algorithm will calculate quotient and remainder from an integer division given a dividend and divisor. The algorithm is a signed -division and will produce a fully qualified quotient and remainder. - -First the divisor $b$ must be non-zero which is enforced in step one. If the divisor is larger than the dividend than the quotient is implicitly -zero and the remainder is the dividend. - -After the first two trivial cases of inputs are handled the variable $q$ is setup to receive the digits of the quotient. Two unsigned copies of the -divisor $y$ and dividend $x$ are made as well. The core of the division algorithm is an unsigned division and will only work if the values are -positive. Now the two values $x$ and $y$ must be normalized such that the leading digit of $y$ is greater than or equal to $\beta / 2$. -This is performed by shifting both to the left by enough bits to get the desired normalization. - -At this point the division algorithm can begin producing digits of the quotient. Recall that maximum value of the estimation used is -$2\beta - {2 \over \beta}$ which means that a digit of the quotient must be first produced by another means. In this case $y$ is shifted -to the left (\textit{step ten}) so that it has the same number of digits as $x$. The loop on step eleven will subtract multiples of the -shifted copy of $y$ until $x$ is smaller. Since the leading digit of $y$ is greater than or equal to $\beta/2$ this loop will iterate at most two -times to produce the desired leading digit of the quotient. - -Now the remainder of the digits can be produced. The equation $\hat q = \lfloor {{x_i \beta + x_{i-1}}\over y_t} \rfloor$ is used to fairly -accurately approximate the true quotient digit. The estimation can in theory produce an estimation as high as $2\beta - {2 \over \beta}$ but by -induction the upper quotient digit is correct (\textit{as established on step eleven}) and the estimate must be less than $\beta$. - -Recall from section~\ref{sec:divest} that the estimation is never too low but may be too high. The next step of the estimation process is -to refine the estimation. The loop on step 13.5 uses $x_i\beta^2 + x_{i-1}\beta + x_{i-2}$ and $q_{i - t - 1}(y_t\beta + y_{t-1})$ as a higher -order approximation to adjust the quotient digit. - -After both phases of estimation the quotient digit may still be off by a value of one\footnote{This is similar to the error introduced -by optimizing Barrett reduction.}. Steps 13.6 and 13.7 subtract the multiple of the divisor from the dividend (\textit{Similar to step 3.3 of -algorithm~\ref{fig:raddiv}} and then subsequently add a multiple of the divisor if the quotient was too large. - -Now that the quotient has been determine finializing the result is a matter of clamping the quotient, fixing the sizes and de-normalizing the -remainder. An important aspect of this algorithm seemingly overlooked in other descriptions such as that of Algorithm 14.20 HAC \cite[pp. 598]{HAC} -is that when the estimations are being made (\textit{inside the loop on step 13.5}) that the digits $y_{t-1}$, $x_{i-2}$ and $x_{i-1}$ may lie -outside their respective boundaries. For example, if $t = 0$ or $i \le 1$ then the digits would be undefined. In those cases the digits should -respectively be replaced with a zero. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_div.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The implementation of this algorithm differs slightly from the pseudo code presented previously. In this algorithm either of the quotient $c$ or -remainder $d$ may be passed as a \textbf{NULL} pointer which indicates their value is not desired. For example, the C code to call the division -algorithm with only the quotient is - -\begin{verbatim} -mp_div(&a, &b, &c, NULL); /* c = [a/b] */ -\end{verbatim} - -Lines 109 and 113 handle the two trivial cases of inputs which are division by zero and dividend smaller than the divisor -respectively. After the two trivial cases all of the temporary variables are initialized. Line 148 determines the sign of -the quotient and line 148 ensures that both $x$ and $y$ are positive. - -The number of bits in the leading digit is calculated on line 151. Implictly an mp\_int with $r$ digits will require $lg(\beta)(r-1) + k$ bits -of precision which when reduced modulo $lg(\beta)$ produces the value of $k$. In this case $k$ is the number of bits in the leading digit which is -exactly what is required. For the algorithm to operate $k$ must equal $lg(\beta) - 1$ and when it does not the inputs must be normalized by shifting -them to the left by $lg(\beta) - 1 - k$ bits. - -Throughout the variables $n$ and $t$ will represent the highest digit of $x$ and $y$ respectively. These are first used to produce the -leading digit of the quotient. The loop beginning on line 184 will produce the remainder of the quotient digits. - -The conditional ``continue'' on line 187 is used to prevent the algorithm from reading past the leading edge of $x$ which can occur when the -algorithm eliminates multiple non-zero digits in a single iteration. This ensures that $x_i$ is always non-zero since by definition the digits -above the $i$'th position $x$ must be zero in order for the quotient to be precise\footnote{Precise as far as integer division is concerned.}. - -Lines 214, 216 and 223 through 225 manually construct the high accuracy estimations by setting the digits of the two mp\_int -variables directly. - -\section{Single Digit Helpers} - -This section briefly describes a series of single digit helper algorithms which come in handy when working with small constants. All of -the helper functions assume the single digit input is positive and will treat them as such. - -\subsection{Single Digit Addition and Subtraction} - -Both addition and subtraction are performed by ``cheating'' and using mp\_set followed by the higher level addition or subtraction -algorithms. As a result these algorithms are subtantially simpler with a slight cost in performance. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_add\_d}. \\ -\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ -\textbf{Output}. $c = a + b$ \\ -\hline \\ -1. $t \leftarrow b$ (\textit{mp\_set}) \\ -2. $c \leftarrow a + t$ \\ -3. Return(\textit{MP\_OKAY}) \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_add\_d} -\end{figure} - -\textbf{Algorithm mp\_add\_d.} -This algorithm initiates a temporary mp\_int with the value of the single digit and uses algorithm mp\_add to add the two values together. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_add\_d.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Clever use of the letter 't'. - -\subsubsection{Subtraction} -The single digit subtraction algorithm mp\_sub\_d is essentially the same except it uses mp\_sub to subtract the digit from the mp\_int. - -\subsection{Single Digit Multiplication} -Single digit multiplication arises enough in division and radix conversion that it ought to be implement as a special case of the baseline -multiplication algorithm. Essentially this algorithm is a modified version of algorithm s\_mp\_mul\_digs where one of the multiplicands -only has one digit. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_mul\_d}. \\ -\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ -\textbf{Output}. $c = ab$ \\ -\hline \\ -1. $pa \leftarrow a.used$ \\ -2. Grow $c$ to at least $pa + 1$ digits. \\ -3. $oldused \leftarrow c.used$ \\ -4. $c.used \leftarrow pa + 1$ \\ -5. $c.sign \leftarrow a.sign$ \\ -6. $\mu \leftarrow 0$ \\ -7. for $ix$ from $0$ to $pa - 1$ do \\ -\hspace{3mm}7.1 $\hat r \leftarrow \mu + a_{ix}b$ \\ -\hspace{3mm}7.2 $c_{ix} \leftarrow \hat r \mbox{ (mod }\beta\mbox{)}$ \\ -\hspace{3mm}7.3 $\mu \leftarrow \lfloor \hat r / \beta \rfloor$ \\ -8. $c_{pa} \leftarrow \mu$ \\ -9. for $ix$ from $pa + 1$ to $oldused$ do \\ -\hspace{3mm}9.1 $c_{ix} \leftarrow 0$ \\ -10. Clamp excess digits of $c$. \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_mul\_d} -\end{figure} -\textbf{Algorithm mp\_mul\_d.} -This algorithm quickly multiplies an mp\_int by a small single digit value. It is specially tailored to the job and has a minimal of overhead. -Unlike the full multiplication algorithms this algorithm does not require any significnat temporary storage or memory allocations. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_mul\_d.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -In this implementation the destination $c$ may point to the same mp\_int as the source $a$ since the result is written after the digit is -read from the source. This function uses pointer aliases $tmpa$ and $tmpc$ for the digits of $a$ and $c$ respectively. - -\subsection{Single Digit Division} -Like the single digit multiplication algorithm, single digit division is also a fairly common algorithm used in radix conversion. Since the -divisor is only a single digit a specialized variant of the division algorithm can be used to compute the quotient. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_div\_d}. \\ -\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ -\textbf{Output}. $c = \lfloor a / b \rfloor, d = a - cb$ \\ -\hline \\ -1. If $b = 0$ then return(\textit{MP\_VAL}).\\ -2. If $b = 3$ then use algorithm mp\_div\_3 instead. \\ -3. Init $q$ to $a.used$ digits. \\ -4. $q.used \leftarrow a.used$ \\ -5. $q.sign \leftarrow a.sign$ \\ -6. $\hat w \leftarrow 0$ \\ -7. for $ix$ from $a.used - 1$ down to $0$ do \\ -\hspace{3mm}7.1 $\hat w \leftarrow \hat w \beta + a_{ix}$ \\ -\hspace{3mm}7.2 If $\hat w \ge b$ then \\ -\hspace{6mm}7.2.1 $t \leftarrow \lfloor \hat w / b \rfloor$ \\ -\hspace{6mm}7.2.2 $\hat w \leftarrow \hat w \mbox{ (mod }b\mbox{)}$ \\ -\hspace{3mm}7.3 else\\ -\hspace{6mm}7.3.1 $t \leftarrow 0$ \\ -\hspace{3mm}7.4 $q_{ix} \leftarrow t$ \\ -8. $d \leftarrow \hat w$ \\ -9. Clamp excess digits of $q$. \\ -10. $c \leftarrow q$ \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_div\_d} -\end{figure} -\textbf{Algorithm mp\_div\_d.} -This algorithm divides the mp\_int $a$ by the single mp\_digit $b$ using an optimized approach. Essentially in every iteration of the -algorithm another digit of the dividend is reduced and another digit of quotient produced. Provided $b < \beta$ the value of $\hat w$ -after step 7.1 will be limited such that $0 \le \lfloor \hat w / b \rfloor < \beta$. - -If the divisor $b$ is equal to three a variant of this algorithm is used which is called mp\_div\_3. It replaces the division by three with -a multiplication by $\lfloor \beta / 3 \rfloor$ and the appropriate shift and residual fixup. In essence it is much like the Barrett reduction -from chapter seven. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_div\_d.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Like the implementation of algorithm mp\_div this algorithm allows either of the quotient or remainder to be passed as a \textbf{NULL} pointer to -indicate the respective value is not required. This allows a trivial single digit modular reduction algorithm, mp\_mod\_d to be created. - -The division and remainder on lines 44 and @45,%@ can be replaced often by a single division on most processors. For example, the 32-bit x86 based -processors can divide a 64-bit quantity by a 32-bit quantity and produce the quotient and remainder simultaneously. Unfortunately the GCC -compiler does not recognize that optimization and will actually produce two function calls to find the quotient and remainder respectively. - -\subsection{Single Digit Root Extraction} - -Finding the $n$'th root of an integer is fairly easy as far as numerical analysis is concerned. Algorithms such as the Newton-Raphson approximation -(\ref{eqn:newton}) series will converge very quickly to a root for any continuous function $f(x)$. - -\begin{equation} -x_{i+1} = x_i - {f(x_i) \over f'(x_i)} -\label{eqn:newton} -\end{equation} - -In this case the $n$'th root is desired and $f(x) = x^n - a$ where $a$ is the integer of which the root is desired. The derivative of $f(x)$ is -simply $f'(x) = nx^{n - 1}$. Of particular importance is that this algorithm will be used over the integers not over the a more continuous domain -such as the real numbers. As a result the root found can be above the true root by few and must be manually adjusted. Ideally at the end of the -algorithm the $n$'th root $b$ of an integer $a$ is desired such that $b^n \le a$. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_n\_root}. \\ -\textbf{Input}. mp\_int $a$ and a mp\_digit $b$ \\ -\textbf{Output}. $c^b \le a$ \\ -\hline \\ -1. If $b$ is even and $a.sign = MP\_NEG$ return(\textit{MP\_VAL}). \\ -2. $sign \leftarrow a.sign$ \\ -3. $a.sign \leftarrow MP\_ZPOS$ \\ -4. t$2 \leftarrow 2$ \\ -5. Loop \\ -\hspace{3mm}5.1 t$1 \leftarrow $ t$2$ \\ -\hspace{3mm}5.2 t$3 \leftarrow $ t$1^{b - 1}$ \\ -\hspace{3mm}5.3 t$2 \leftarrow $ t$3 $ $\cdot$ t$1$ \\ -\hspace{3mm}5.4 t$2 \leftarrow $ t$2 - a$ \\ -\hspace{3mm}5.5 t$3 \leftarrow $ t$3 \cdot b$ \\ -\hspace{3mm}5.6 t$3 \leftarrow \lfloor $t$2 / $t$3 \rfloor$ \\ -\hspace{3mm}5.7 t$2 \leftarrow $ t$1 - $ t$3$ \\ -\hspace{3mm}5.8 If t$1 \ne $ t$2$ then goto step 5. \\ -6. Loop \\ -\hspace{3mm}6.1 t$2 \leftarrow $ t$1^b$ \\ -\hspace{3mm}6.2 If t$2 > a$ then \\ -\hspace{6mm}6.2.1 t$1 \leftarrow $ t$1 - 1$ \\ -\hspace{6mm}6.2.2 Goto step 6. \\ -7. $a.sign \leftarrow sign$ \\ -8. $c \leftarrow $ t$1$ \\ -9. $c.sign \leftarrow sign$ \\ -10. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_n\_root} -\end{figure} -\textbf{Algorithm mp\_n\_root.} -This algorithm finds the integer $n$'th root of an input using the Newton-Raphson approach. It is partially optimized based on the observation -that the numerator of ${f(x) \over f'(x)}$ can be derived from a partial denominator. That is at first the denominator is calculated by finding -$x^{b - 1}$. This value can then be multiplied by $x$ and have $a$ subtracted from it to find the numerator. This saves a total of $b - 1$ -multiplications by t$1$ inside the loop. - -The initial value of the approximation is t$2 = 2$ which allows the algorithm to start with very small values and quickly converge on the -root. Ideally this algorithm is meant to find the $n$'th root of an input where $n$ is bounded by $2 \le n \le 5$. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_n\_root.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\section{Random Number Generation} - -Random numbers come up in a variety of activities from public key cryptography to simple simulations and various randomized algorithms. Pollard-Rho -factoring for example, can make use of random values as starting points to find factors of a composite integer. In this case the algorithm presented -is solely for simulations and not intended for cryptographic use. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_rand}. \\ -\textbf{Input}. An integer $b$ \\ -\textbf{Output}. A pseudo-random number of $b$ digits \\ -\hline \\ -1. $a \leftarrow 0$ \\ -2. If $b \le 0$ return(\textit{MP\_OKAY}) \\ -3. Pick a non-zero random digit $d$. \\ -4. $a \leftarrow a + d$ \\ -5. for $ix$ from 1 to $d - 1$ do \\ -\hspace{3mm}5.1 $a \leftarrow a \cdot \beta$ \\ -\hspace{3mm}5.2 Pick a random digit $d$. \\ -\hspace{3mm}5.3 $a \leftarrow a + d$ \\ -6. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_rand} -\end{figure} -\textbf{Algorithm mp\_rand.} -This algorithm produces a pseudo-random integer of $b$ digits. By ensuring that the first digit is non-zero the algorithm also guarantees that the -final result has at least $b$ digits. It relies heavily on a third-part random number generator which should ideally generate uniformly all of -the integers from $0$ to $\beta - 1$. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_rand.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\section{Formatted Representations} -The ability to emit a radix-$n$ textual representation of an integer is useful for interacting with human parties. For example, the ability to -be given a string of characters such as ``114585'' and turn it into the radix-$\beta$ equivalent would make it easier to enter numbers -into a program. - -\subsection{Reading Radix-n Input} -For the purposes of this text we will assume that a simple lower ASCII map (\ref{fig:ASC}) is used for the values of from $0$ to $63$ to -printable characters. For example, when the character ``N'' is read it represents the integer $23$. The first $16$ characters of the -map are for the common representations up to hexadecimal. After that they match the ``base64'' encoding scheme which are suitable chosen -such that they are printable. While outputting as base64 may not be too helpful for human operators it does allow communication via non binary -mediums. - -\newpage\begin{figure}[here] -\begin{center} -\begin{tabular}{cc|cc|cc|cc} -\hline \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} & \textbf{Value} & \textbf{Char} \\ -\hline -0 & 0 & 1 & 1 & 2 & 2 & 3 & 3 \\ -4 & 4 & 5 & 5 & 6 & 6 & 7 & 7 \\ -8 & 8 & 9 & 9 & 10 & A & 11 & B \\ -12 & C & 13 & D & 14 & E & 15 & F \\ -16 & G & 17 & H & 18 & I & 19 & J \\ -20 & K & 21 & L & 22 & M & 23 & N \\ -24 & O & 25 & P & 26 & Q & 27 & R \\ -28 & S & 29 & T & 30 & U & 31 & V \\ -32 & W & 33 & X & 34 & Y & 35 & Z \\ -36 & a & 37 & b & 38 & c & 39 & d \\ -40 & e & 41 & f & 42 & g & 43 & h \\ -44 & i & 45 & j & 46 & k & 47 & l \\ -48 & m & 49 & n & 50 & o & 51 & p \\ -52 & q & 53 & r & 54 & s & 55 & t \\ -56 & u & 57 & v & 58 & w & 59 & x \\ -60 & y & 61 & z & 62 & $+$ & 63 & $/$ \\ -\hline -\end{tabular} -\end{center} -\caption{Lower ASCII Map} -\label{fig:ASC} -\end{figure} - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_read\_radix}. \\ -\textbf{Input}. A string $str$ of length $sn$ and radix $r$. \\ -\textbf{Output}. The radix-$\beta$ equivalent mp\_int. \\ -\hline \\ -1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\ -2. $ix \leftarrow 0$ \\ -3. If $str_0 =$ ``-'' then do \\ -\hspace{3mm}3.1 $ix \leftarrow ix + 1$ \\ -\hspace{3mm}3.2 $sign \leftarrow MP\_NEG$ \\ -4. else \\ -\hspace{3mm}4.1 $sign \leftarrow MP\_ZPOS$ \\ -5. $a \leftarrow 0$ \\ -6. for $iy$ from $ix$ to $sn - 1$ do \\ -\hspace{3mm}6.1 Let $y$ denote the position in the map of $str_{iy}$. \\ -\hspace{3mm}6.2 If $str_{iy}$ is not in the map or $y \ge r$ then goto step 7. \\ -\hspace{3mm}6.3 $a \leftarrow a \cdot r$ \\ -\hspace{3mm}6.4 $a \leftarrow a + y$ \\ -7. If $a \ne 0$ then $a.sign \leftarrow sign$ \\ -8. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_read\_radix} -\end{figure} -\textbf{Algorithm mp\_read\_radix.} -This algorithm will read an ASCII string and produce the radix-$\beta$ mp\_int representation of the same integer. A minus symbol ``-'' may precede the -string to indicate the value is negative, otherwise it is assumed to be positive. The algorithm will read up to $sn$ characters from the input -and will stop when it reads a character it cannot map the algorithm stops reading characters from the string. This allows numbers to be embedded -as part of larger input without any significant problem. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_read\_radix.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\subsection{Generating Radix-$n$ Output} -Generating radix-$n$ output is fairly trivial with a division and remainder algorithm. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_toradix}. \\ -\textbf{Input}. A mp\_int $a$ and an integer $r$\\ -\textbf{Output}. The radix-$r$ representation of $a$ \\ -\hline \\ -1. If $r < 2$ or $r > 64$ return(\textit{MP\_VAL}). \\ -2. If $a = 0$ then $str = $ ``$0$'' and return(\textit{MP\_OKAY}). \\ -3. $t \leftarrow a$ \\ -4. $str \leftarrow$ ``'' \\ -5. if $t.sign = MP\_NEG$ then \\ -\hspace{3mm}5.1 $str \leftarrow str + $ ``-'' \\ -\hspace{3mm}5.2 $t.sign = MP\_ZPOS$ \\ -6. While ($t \ne 0$) do \\ -\hspace{3mm}6.1 $d \leftarrow t \mbox{ (mod }r\mbox{)}$ \\ -\hspace{3mm}6.2 $t \leftarrow \lfloor t / r \rfloor$ \\ -\hspace{3mm}6.3 Look up $d$ in the map and store the equivalent character in $y$. \\ -\hspace{3mm}6.4 $str \leftarrow str + y$ \\ -7. If $str_0 = $``$-$'' then \\ -\hspace{3mm}7.1 Reverse the digits $str_1, str_2, \ldots str_n$. \\ -8. Otherwise \\ -\hspace{3mm}8.1 Reverse the digits $str_0, str_1, \ldots str_n$. \\ -9. Return(\textit{MP\_OKAY}).\\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_toradix} -\end{figure} -\textbf{Algorithm mp\_toradix.} -This algorithm computes the radix-$r$ representation of an mp\_int $a$. The ``digits'' of the representation are extracted by reducing -successive powers of $\lfloor a / r^k \rfloor$ the input modulo $r$ until $r^k > a$. Note that instead of actually dividing by $r^k$ in -each iteration the quotient $\lfloor a / r \rfloor$ is saved for the next iteration. As a result a series of trivial $n \times 1$ divisions -are required instead of a series of $n \times k$ divisions. One design flaw of this approach is that the digits are produced in the reverse order -(see~\ref{fig:mpradix}). To remedy this flaw the digits must be swapped or simply ``reversed''. - -\begin{figure} -\begin{center} -\begin{tabular}{|c|c|c|} -\hline \textbf{Value of $a$} & \textbf{Value of $d$} & \textbf{Value of $str$} \\ -\hline $1234$ & -- & -- \\ -\hline $123$ & $4$ & ``4'' \\ -\hline $12$ & $3$ & ``43'' \\ -\hline $1$ & $2$ & ``432'' \\ -\hline $0$ & $1$ & ``4321'' \\ -\hline -\end{tabular} -\end{center} -\caption{Example of Algorithm mp\_toradix.} -\label{fig:mpradix} -\end{figure} - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_toradix.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\chapter{Number Theoretic Algorithms} -This chapter discusses several fundamental number theoretic algorithms such as the greatest common divisor, least common multiple and Jacobi -symbol computation. These algorithms arise as essential components in several key cryptographic algorithms such as the RSA public key algorithm and -various Sieve based factoring algorithms. - -\section{Greatest Common Divisor} -The greatest common divisor of two integers $a$ and $b$, often denoted as $(a, b)$ is the largest integer $k$ that is a proper divisor of -both $a$ and $b$. That is, $k$ is the largest integer such that $0 \equiv a \mbox{ (mod }k\mbox{)}$ and $0 \equiv b \mbox{ (mod }k\mbox{)}$ occur -simultaneously. - -The most common approach (cite) is to reduce one input modulo another. That is if $a$ and $b$ are divisible by some integer $k$ and if $qa + r = b$ then -$r$ is also divisible by $k$. The reduction pattern follows $\left < a , b \right > \rightarrow \left < b, a \mbox{ mod } b \right >$. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Greatest Common Divisor (I)}. \\ -\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ -\textbf{Output}. The greatest common divisor $(a, b)$. \\ -\hline \\ -1. While ($b > 0$) do \\ -\hspace{3mm}1.1 $r \leftarrow a \mbox{ (mod }b\mbox{)}$ \\ -\hspace{3mm}1.2 $a \leftarrow b$ \\ -\hspace{3mm}1.3 $b \leftarrow r$ \\ -2. Return($a$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Greatest Common Divisor (I)} -\label{fig:gcd1} -\end{figure} - -This algorithm will quickly converge on the greatest common divisor since the residue $r$ tends diminish rapidly. However, divisions are -relatively expensive operations to perform and should ideally be avoided. There is another approach based on a similar relationship of -greatest common divisors. The faster approach is based on the observation that if $k$ divides both $a$ and $b$ it will also divide $a - b$. -In particular, we would like $a - b$ to decrease in magnitude which implies that $b \ge a$. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Greatest Common Divisor (II)}. \\ -\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ -\textbf{Output}. The greatest common divisor $(a, b)$. \\ -\hline \\ -1. While ($b > 0$) do \\ -\hspace{3mm}1.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\ -\hspace{3mm}1.2 $b \leftarrow b - a$ \\ -2. Return($a$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Greatest Common Divisor (II)} -\label{fig:gcd2} -\end{figure} - -\textbf{Proof} \textit{Algorithm~\ref{fig:gcd2} will return the greatest common divisor of $a$ and $b$.} -The algorithm in figure~\ref{fig:gcd2} will eventually terminate since $b \ge a$ the subtraction in step 1.2 will be a value less than $b$. In other -words in every iteration that tuple $\left < a, b \right >$ decrease in magnitude until eventually $a = b$. Since both $a$ and $b$ are always -divisible by the greatest common divisor (\textit{until the last iteration}) and in the last iteration of the algorithm $b = 0$, therefore, in the -second to last iteration of the algorithm $b = a$ and clearly $(a, a) = a$ which concludes the proof. \textbf{QED}. - -As a matter of practicality algorithm \ref{fig:gcd1} decreases far too slowly to be useful. Specially if $b$ is much larger than $a$ such that -$b - a$ is still very much larger than $a$. A simple addition to the algorithm is to divide $b - a$ by a power of some integer $p$ which does -not divide the greatest common divisor but will divide $b - a$. In this case ${b - a} \over p$ is also an integer and still divisible by -the greatest common divisor. - -However, instead of factoring $b - a$ to find a suitable value of $p$ the powers of $p$ can be removed from $a$ and $b$ that are in common first. -Then inside the loop whenever $b - a$ is divisible by some power of $p$ it can be safely removed. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{Greatest Common Divisor (III)}. \\ -\textbf{Input}. Two positive integers $a$ and $b$ greater than zero. \\ -\textbf{Output}. The greatest common divisor $(a, b)$. \\ -\hline \\ -1. $k \leftarrow 0$ \\ -2. While $a$ and $b$ are both divisible by $p$ do \\ -\hspace{3mm}2.1 $a \leftarrow \lfloor a / p \rfloor$ \\ -\hspace{3mm}2.2 $b \leftarrow \lfloor b / p \rfloor$ \\ -\hspace{3mm}2.3 $k \leftarrow k + 1$ \\ -3. While $a$ is divisible by $p$ do \\ -\hspace{3mm}3.1 $a \leftarrow \lfloor a / p \rfloor$ \\ -4. While $b$ is divisible by $p$ do \\ -\hspace{3mm}4.1 $b \leftarrow \lfloor b / p \rfloor$ \\ -5. While ($b > 0$) do \\ -\hspace{3mm}5.1 Swap $a$ and $b$ such that $a$ is the smallest of the two. \\ -\hspace{3mm}5.2 $b \leftarrow b - a$ \\ -\hspace{3mm}5.3 While $b$ is divisible by $p$ do \\ -\hspace{6mm}5.3.1 $b \leftarrow \lfloor b / p \rfloor$ \\ -6. Return($a \cdot p^k$). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm Greatest Common Divisor (III)} -\label{fig:gcd3} -\end{figure} - -This algorithm is based on the first except it removes powers of $p$ first and inside the main loop to ensure the tuple $\left < a, b \right >$ -decreases more rapidly. The first loop on step two removes powers of $p$ that are in common. A count, $k$, is kept which will present a common -divisor of $p^k$. After step two the remaining common divisor of $a$ and $b$ cannot be divisible by $p$. This means that $p$ can be safely -divided out of the difference $b - a$ so long as the division leaves no remainder. - -In particular the value of $p$ should be chosen such that the division on step 5.3.1 occur often. It also helps that division by $p$ be easy -to compute. The ideal choice of $p$ is two since division by two amounts to a right logical shift. Another important observation is that by -step five both $a$ and $b$ are odd. Therefore, the diffrence $b - a$ must be even which means that each iteration removes one bit from the -largest of the pair. - -\subsection{Complete Greatest Common Divisor} -The algorithms presented so far cannot handle inputs which are zero or negative. The following algorithm can handle all input cases properly -and will produce the greatest common divisor. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_gcd}. \\ -\textbf{Input}. mp\_int $a$ and $b$ \\ -\textbf{Output}. The greatest common divisor $c = (a, b)$. \\ -\hline \\ -1. If $a = 0$ then \\ -\hspace{3mm}1.1 $c \leftarrow \vert b \vert $ \\ -\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ -2. If $b = 0$ then \\ -\hspace{3mm}2.1 $c \leftarrow \vert a \vert $ \\ -\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\ -3. $u \leftarrow \vert a \vert, v \leftarrow \vert b \vert$ \\ -4. $k \leftarrow 0$ \\ -5. While $u.used > 0$ and $v.used > 0$ and $u_0 \equiv v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}5.1 $k \leftarrow k + 1$ \\ -\hspace{3mm}5.2 $u \leftarrow \lfloor u / 2 \rfloor$ \\ -\hspace{3mm}5.3 $v \leftarrow \lfloor v / 2 \rfloor$ \\ -6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\ -7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ -8. While $v.used > 0$ \\ -\hspace{3mm}8.1 If $\vert u \vert > \vert v \vert$ then \\ -\hspace{6mm}8.1.1 Swap $u$ and $v$. \\ -\hspace{3mm}8.2 $v \leftarrow \vert v \vert - \vert u \vert$ \\ -\hspace{3mm}8.3 While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{6mm}8.3.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ -9. $c \leftarrow u \cdot 2^k$ \\ -10. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_gcd} -\end{figure} -\textbf{Algorithm mp\_gcd.} -This algorithm will produce the greatest common divisor of two mp\_ints $a$ and $b$. The algorithm was originally based on Algorithm B of -Knuth \cite[pp. 338]{TAOCPV2} but has been modified to be simpler to explain. In theory it achieves the same asymptotic working time as -Algorithm B and in practice this appears to be true. - -The first two steps handle the cases where either one of or both inputs are zero. If either input is zero the greatest common divisor is the -largest input or zero if they are both zero. If the inputs are not trivial than $u$ and $v$ are assigned the absolute values of -$a$ and $b$ respectively and the algorithm will proceed to reduce the pair. - -Step five will divide out any common factors of two and keep track of the count in the variable $k$. After this step, two is no longer a -factor of the remaining greatest common divisor between $u$ and $v$ and can be safely evenly divided out of either whenever they are even. Step -six and seven ensure that the $u$ and $v$ respectively have no more factors of two. At most only one of the while--loops will iterate since -they cannot both be even. - -By step eight both of $u$ and $v$ are odd which is required for the inner logic. First the pair are swapped such that $v$ is equal to -or greater than $u$. This ensures that the subtraction on step 8.2 will always produce a positive and even result. Step 8.3 removes any -factors of two from the difference $u$ to ensure that in the next iteration of the loop both are once again odd. - -After $v = 0$ occurs the variable $u$ has the greatest common divisor of the pair $\left < u, v \right >$ just after step six. The result -must be adjusted by multiplying by the common factors of two ($2^k$) removed earlier. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_gcd.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -This function makes use of the macros mp\_iszero and mp\_iseven. The former evaluates to $1$ if the input mp\_int is equivalent to the -integer zero otherwise it evaluates to $0$. The latter evaluates to $1$ if the input mp\_int represents a non-zero even integer otherwise -it evaluates to $0$. Note that just because mp\_iseven may evaluate to $0$ does not mean the input is odd, it could also be zero. The three -trivial cases of inputs are handled on lines 24 through 30. After those lines the inputs are assumed to be non-zero. - -Lines 32 and 37 make local copies $u$ and $v$ of the inputs $a$ and $b$ respectively. At this point the common factors of two -must be divided out of the two inputs. The block starting at line 44 removes common factors of two by first counting the number of trailing -zero bits in both. The local integer $k$ is used to keep track of how many factors of $2$ are pulled out of both values. It is assumed that -the number of factors will not exceed the maximum value of a C ``int'' data type\footnote{Strictly speaking no array in C may have more than -entries than are accessible by an ``int'' so this is not a limitation.}. - -At this point there are no more common factors of two in the two values. The divisions by a power of two on lines 62 and 68 remove -any independent factors of two such that both $u$ and $v$ are guaranteed to be an odd integer before hitting the main body of the algorithm. The while loop -on line 73 performs the reduction of the pair until $v$ is equal to zero. The unsigned comparison and subtraction algorithms are used in -place of the full signed routines since both values are guaranteed to be positive and the result of the subtraction is guaranteed to be non-negative. - -\section{Least Common Multiple} -The least common multiple of a pair of integers is their product divided by their greatest common divisor. For two integers $a$ and $b$ the -least common multiple is normally denoted as $[ a, b ]$ and numerically equivalent to ${ab} \over {(a, b)}$. For example, if $a = 2 \cdot 2 \cdot 3 = 12$ -and $b = 2 \cdot 3 \cdot 3 \cdot 7 = 126$ the least common multiple is ${126 \over {(12, 126)}} = {126 \over 6} = 21$. - -The least common multiple arises often in coding theory as well as number theory. If two functions have periods of $a$ and $b$ respectively they will -collide, that is be in synchronous states, after only $[ a, b ]$ iterations. This is why, for example, random number generators based on -Linear Feedback Shift Registers (LFSR) tend to use registers with periods which are co-prime (\textit{e.g. the greatest common divisor is one.}). -Similarly in number theory if a composite $n$ has two prime factors $p$ and $q$ then maximal order of any unit of $\Z/n\Z$ will be $[ p - 1, q - 1] $. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_lcm}. \\ -\textbf{Input}. mp\_int $a$ and $b$ \\ -\textbf{Output}. The least common multiple $c = [a, b]$. \\ -\hline \\ -1. $c \leftarrow (a, b)$ \\ -2. $t \leftarrow a \cdot b$ \\ -3. $c \leftarrow \lfloor t / c \rfloor$ \\ -4. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_lcm} -\end{figure} -\textbf{Algorithm mp\_lcm.} -This algorithm computes the least common multiple of two mp\_int inputs $a$ and $b$. It computes the least common multiple directly by -dividing the product of the two inputs by their greatest common divisor. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_lcm.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\section{Jacobi Symbol Computation} -To explain the Jacobi Symbol we shall first discuss the Legendre function\footnote{Arrg. What is the name of this?} off which the Jacobi symbol is -defined. The Legendre function computes whether or not an integer $a$ is a quadratic residue modulo an odd prime $p$. Numerically it is -equivalent to equation \ref{eqn:legendre}. - -\textit{-- Tom, don't be an ass, cite your source here...!} - -\begin{equation} -a^{(p-1)/2} \equiv \begin{array}{rl} - -1 & \mbox{if }a\mbox{ is a quadratic non-residue.} \\ - 0 & \mbox{if }a\mbox{ divides }p\mbox{.} \\ - 1 & \mbox{if }a\mbox{ is a quadratic residue}. - \end{array} \mbox{ (mod }p\mbox{)} -\label{eqn:legendre} -\end{equation} - -\textbf{Proof.} \textit{Equation \ref{eqn:legendre} correctly identifies the residue status of an integer $a$ modulo a prime $p$.} -An integer $a$ is a quadratic residue if the following equation has a solution. - -\begin{equation} -x^2 \equiv a \mbox{ (mod }p\mbox{)} -\label{eqn:root} -\end{equation} - -Consider the following equation. - -\begin{equation} -0 \equiv x^{p-1} - 1 \equiv \left \lbrace \left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \right \rbrace + \left ( a^{(p-1)/2} - 1 \right ) \mbox{ (mod }p\mbox{)} -\label{eqn:rooti} -\end{equation} - -Whether equation \ref{eqn:root} has a solution or not equation \ref{eqn:rooti} is always true. If $a^{(p-1)/2} - 1 \equiv 0 \mbox{ (mod }p\mbox{)}$ -then the quantity in the braces must be zero. By reduction, - -\begin{eqnarray} -\left (x^2 \right )^{(p-1)/2} - a^{(p-1)/2} \equiv 0 \nonumber \\ -\left (x^2 \right )^{(p-1)/2} \equiv a^{(p-1)/2} \nonumber \\ -x^2 \equiv a \mbox{ (mod }p\mbox{)} -\end{eqnarray} - -As a result there must be a solution to the quadratic equation and in turn $a$ must be a quadratic residue. If $a$ does not divide $p$ and $a$ -is not a quadratic residue then the only other value $a^{(p-1)/2}$ may be congruent to is $-1$ since -\begin{equation} -0 \equiv a^{p - 1} - 1 \equiv (a^{(p-1)/2} + 1)(a^{(p-1)/2} - 1) \mbox{ (mod }p\mbox{)} -\end{equation} -One of the terms on the right hand side must be zero. \textbf{QED} - -\subsection{Jacobi Symbol} -The Jacobi symbol is a generalization of the Legendre function for any odd non prime moduli $p$ greater than 2. If $p = \prod_{i=0}^n p_i$ then -the Jacobi symbol $\left ( { a \over p } \right )$ is equal to the following equation. - -\begin{equation} -\left ( { a \over p } \right ) = \left ( { a \over p_0} \right ) \left ( { a \over p_1} \right ) \ldots \left ( { a \over p_n} \right ) -\end{equation} - -By inspection if $p$ is prime the Jacobi symbol is equivalent to the Legendre function. The following facts\footnote{See HAC \cite[pp. 72-74]{HAC} for -further details.} will be used to derive an efficient Jacobi symbol algorithm. Where $p$ is an odd integer greater than two and $a, b \in \Z$ the -following are true. - -\begin{enumerate} -\item $\left ( { a \over p} \right )$ equals $-1$, $0$ or $1$. -\item $\left ( { ab \over p} \right ) = \left ( { a \over p} \right )\left ( { b \over p} \right )$. -\item If $a \equiv b$ then $\left ( { a \over p} \right ) = \left ( { b \over p} \right )$. -\item $\left ( { 2 \over p} \right )$ equals $1$ if $p \equiv 1$ or $7 \mbox{ (mod }8\mbox{)}$. Otherwise, it equals $-1$. -\item $\left ( { a \over p} \right ) \equiv \left ( { p \over a} \right ) \cdot (-1)^{(p-1)(a-1)/4}$. More specifically -$\left ( { a \over p} \right ) = \left ( { p \over a} \right )$ if $p \equiv a \equiv 1 \mbox{ (mod }4\mbox{)}$. -\end{enumerate} - -Using these facts if $a = 2^k \cdot a'$ then - -\begin{eqnarray} -\left ( { a \over p } \right ) = \left ( {{2^k} \over p } \right ) \left ( {a' \over p} \right ) \nonumber \\ - = \left ( {2 \over p } \right )^k \left ( {a' \over p} \right ) -\label{eqn:jacobi} -\end{eqnarray} - -By fact five, - -\begin{equation} -\left ( { a \over p } \right ) = \left ( { p \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} -\end{equation} - -Subsequently by fact three since $p \equiv (p \mbox{ mod }a) \mbox{ (mod }a\mbox{)}$ then - -\begin{equation} -\left ( { a \over p } \right ) = \left ( { {p \mbox{ mod } a} \over a } \right ) \cdot (-1)^{(p-1)(a-1)/4} -\end{equation} - -By putting both observations into equation \ref{eqn:jacobi} the following simplified equation is formed. - -\begin{equation} -\left ( { a \over p } \right ) = \left ( {2 \over p } \right )^k \left ( {{p\mbox{ mod }a'} \over a'} \right ) \cdot (-1)^{(p-1)(a'-1)/4} -\end{equation} - -The value of $\left ( {{p \mbox{ mod }a'} \over a'} \right )$ can be found by using the same equation recursively. The value of -$\left ( {2 \over p } \right )^k$ equals $1$ if $k$ is even otherwise it equals $\left ( {2 \over p } \right )$. Using this approach the -factors of $p$ do not have to be known. Furthermore, if $(a, p) = 1$ then the algorithm will terminate when the recursion requests the -Jacobi symbol computation of $\left ( {1 \over a'} \right )$ which is simply $1$. - -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_jacobi}. \\ -\textbf{Input}. mp\_int $a$ and $p$, $a \ge 0$, $p \ge 3$, $p \equiv 1 \mbox{ (mod }2\mbox{)}$ \\ -\textbf{Output}. The Jacobi symbol $c = \left ( {a \over p } \right )$. \\ -\hline \\ -1. If $a = 0$ then \\ -\hspace{3mm}1.1 $c \leftarrow 0$ \\ -\hspace{3mm}1.2 Return(\textit{MP\_OKAY}). \\ -2. If $a = 1$ then \\ -\hspace{3mm}2.1 $c \leftarrow 1$ \\ -\hspace{3mm}2.2 Return(\textit{MP\_OKAY}). \\ -3. $a' \leftarrow a$ \\ -4. $k \leftarrow 0$ \\ -5. While $a'.used > 0$ and $a'_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}5.1 $k \leftarrow k + 1$ \\ -\hspace{3mm}5.2 $a' \leftarrow \lfloor a' / 2 \rfloor$ \\ -6. If $k \equiv 0 \mbox{ (mod }2\mbox{)}$ then \\ -\hspace{3mm}6.1 $s \leftarrow 1$ \\ -7. else \\ -\hspace{3mm}7.1 $r \leftarrow p_0 \mbox{ (mod }8\mbox{)}$ \\ -\hspace{3mm}7.2 If $r = 1$ or $r = 7$ then \\ -\hspace{6mm}7.2.1 $s \leftarrow 1$ \\ -\hspace{3mm}7.3 else \\ -\hspace{6mm}7.3.1 $s \leftarrow -1$ \\ -8. If $p_0 \equiv a'_0 \equiv 3 \mbox{ (mod }4\mbox{)}$ then \\ -\hspace{3mm}8.1 $s \leftarrow -s$ \\ -9. If $a' \ne 1$ then \\ -\hspace{3mm}9.1 $p' \leftarrow p \mbox{ (mod }a'\mbox{)}$ \\ -\hspace{3mm}9.2 $s \leftarrow s \cdot \mbox{mp\_jacobi}(p', a')$ \\ -10. $c \leftarrow s$ \\ -11. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_jacobi} -\end{figure} -\textbf{Algorithm mp\_jacobi.} -This algorithm computes the Jacobi symbol for an arbitrary positive integer $a$ with respect to an odd integer $p$ greater than three. The algorithm -is based on algorithm 2.149 of HAC \cite[pp. 73]{HAC}. - -Step numbers one and two handle the trivial cases of $a = 0$ and $a = 1$ respectively. Step five determines the number of two factors in the -input $a$. If $k$ is even than the term $\left ( { 2 \over p } \right )^k$ must always evaluate to one. If $k$ is odd than the term evaluates to one -if $p_0$ is congruent to one or seven modulo eight, otherwise it evaluates to $-1$. After the the $\left ( { 2 \over p } \right )^k$ term is handled -the $(-1)^{(p-1)(a'-1)/4}$ is computed and multiplied against the current product $s$. The latter term evaluates to one if both $p$ and $a'$ -are congruent to one modulo four, otherwise it evaluates to negative one. - -By step nine if $a'$ does not equal one a recursion is required. Step 9.1 computes $p' \equiv p \mbox{ (mod }a'\mbox{)}$ and will recurse to compute -$\left ( {p' \over a'} \right )$ which is multiplied against the current Jacobi product. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_jacobi.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -As a matter of practicality the variable $a'$ as per the pseudo-code is reprensented by the variable $a1$ since the $'$ symbol is not valid for a C -variable name character. - -The two simple cases of $a = 0$ and $a = 1$ are handled at the very beginning to simplify the algorithm. If the input is non-trivial the algorithm -has to proceed compute the Jacobi. The variable $s$ is used to hold the current Jacobi product. Note that $s$ is merely a C ``int'' data type since -the values it may obtain are merely $-1$, $0$ and $1$. - -After a local copy of $a$ is made all of the factors of two are divided out and the total stored in $k$. Technically only the least significant -bit of $k$ is required, however, it makes the algorithm simpler to follow to perform an addition. In practice an exclusive-or and addition have the same -processor requirements and neither is faster than the other. - -Line 58 through 71 determines the value of $\left ( { 2 \over p } \right )^k$. If the least significant bit of $k$ is zero than -$k$ is even and the value is one. Otherwise, the value of $s$ depends on which residue class $p$ belongs to modulo eight. The value of -$(-1)^{(p-1)(a'-1)/4}$ is compute and multiplied against $s$ on lines 71 through 74. - -Finally, if $a1$ does not equal one the algorithm must recurse and compute $\left ( {p' \over a'} \right )$. - -\textit{-- Comment about default $s$ and such...} - -\section{Modular Inverse} -\label{sec:modinv} -The modular inverse of a number actually refers to the modular multiplicative inverse. Essentially for any integer $a$ such that $(a, p) = 1$ there -exist another integer $b$ such that $ab \equiv 1 \mbox{ (mod }p\mbox{)}$. The integer $b$ is called the multiplicative inverse of $a$ which is -denoted as $b = a^{-1}$. Technically speaking modular inversion is a well defined operation for any finite ring or field not just for rings and -fields of integers. However, the former will be the matter of discussion. - -The simplest approach is to compute the algebraic inverse of the input. That is to compute $b \equiv a^{\Phi(p) - 1}$. If $\Phi(p)$ is the -order of the multiplicative subgroup modulo $p$ then $b$ must be the multiplicative inverse of $a$. The proof of which is trivial. - -\begin{equation} -ab \equiv a \left (a^{\Phi(p) - 1} \right ) \equiv a^{\Phi(p)} \equiv a^0 \equiv 1 \mbox{ (mod }p\mbox{)} -\end{equation} - -However, as simple as this approach may be it has two serious flaws. It requires that the value of $\Phi(p)$ be known which if $p$ is composite -requires all of the prime factors. This approach also is very slow as the size of $p$ grows. - -A simpler approach is based on the observation that solving for the multiplicative inverse is equivalent to solving the linear -Diophantine\footnote{See LeVeque \cite[pp. 40-43]{LeVeque} for more information.} equation. - -\begin{equation} -ab + pq = 1 -\end{equation} - -Where $a$, $b$, $p$ and $q$ are all integers. If such a pair of integers $ \left < b, q \right >$ exist than $b$ is the multiplicative inverse of -$a$ modulo $p$. The extended Euclidean algorithm (Knuth \cite[pp. 342]{TAOCPV2}) can be used to solve such equations provided $(a, p) = 1$. -However, instead of using that algorithm directly a variant known as the binary Extended Euclidean algorithm will be used in its place. The -binary approach is very similar to the binary greatest common divisor algorithm except it will produce a full solution to the Diophantine -equation. - -\subsection{General Case} -\newpage\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_invmod}. \\ -\textbf{Input}. mp\_int $a$ and $b$, $(a, b) = 1$, $p \ge 2$, $0 < a < p$. \\ -\textbf{Output}. The modular inverse $c \equiv a^{-1} \mbox{ (mod }b\mbox{)}$. \\ -\hline \\ -1. If $b \le 0$ then return(\textit{MP\_VAL}). \\ -2. If $b_0 \equiv 1 \mbox{ (mod }2\mbox{)}$ then use algorithm fast\_mp\_invmod. \\ -3. $x \leftarrow \vert a \vert, y \leftarrow b$ \\ -4. If $x_0 \equiv y_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ then return(\textit{MP\_VAL}). \\ -5. $B \leftarrow 0, C \leftarrow 0, A \leftarrow 1, D \leftarrow 1$ \\ -6. While $u.used > 0$ and $u_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}6.1 $u \leftarrow \lfloor u / 2 \rfloor$ \\ -\hspace{3mm}6.2 If ($A.used > 0$ and $A_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($B.used > 0$ and $B_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\ -\hspace{6mm}6.2.1 $A \leftarrow A + y$ \\ -\hspace{6mm}6.2.2 $B \leftarrow B - x$ \\ -\hspace{3mm}6.3 $A \leftarrow \lfloor A / 2 \rfloor$ \\ -\hspace{3mm}6.4 $B \leftarrow \lfloor B / 2 \rfloor$ \\ -7. While $v.used > 0$ and $v_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}7.1 $v \leftarrow \lfloor v / 2 \rfloor$ \\ -\hspace{3mm}7.2 If ($C.used > 0$ and $C_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) or ($D.used > 0$ and $D_0 \equiv 1 \mbox{ (mod }2\mbox{)}$) then \\ -\hspace{6mm}7.2.1 $C \leftarrow C + y$ \\ -\hspace{6mm}7.2.2 $D \leftarrow D - x$ \\ -\hspace{3mm}7.3 $C \leftarrow \lfloor C / 2 \rfloor$ \\ -\hspace{3mm}7.4 $D \leftarrow \lfloor D / 2 \rfloor$ \\ -8. If $u \ge v$ then \\ -\hspace{3mm}8.1 $u \leftarrow u - v$ \\ -\hspace{3mm}8.2 $A \leftarrow A - C$ \\ -\hspace{3mm}8.3 $B \leftarrow B - D$ \\ -9. else \\ -\hspace{3mm}9.1 $v \leftarrow v - u$ \\ -\hspace{3mm}9.2 $C \leftarrow C - A$ \\ -\hspace{3mm}9.3 $D \leftarrow D - B$ \\ -10. If $u \ne 0$ goto step 6. \\ -11. If $v \ne 1$ return(\textit{MP\_VAL}). \\ -12. While $C \le 0$ do \\ -\hspace{3mm}12.1 $C \leftarrow C + b$ \\ -13. While $C \ge b$ do \\ -\hspace{3mm}13.1 $C \leftarrow C - b$ \\ -14. $c \leftarrow C$ \\ -15. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\end{figure} -\textbf{Algorithm mp\_invmod.} -This algorithm computes the modular multiplicative inverse of an integer $a$ modulo an integer $b$. This algorithm is a variation of the -extended binary Euclidean algorithm from HAC \cite[pp. 608]{HAC}. It has been modified to only compute the modular inverse and not a complete -Diophantine solution. - -If $b \le 0$ than the modulus is invalid and MP\_VAL is returned. Similarly if both $a$ and $b$ are even then there cannot be a multiplicative -inverse for $a$ and the error is reported. - -The astute reader will observe that steps seven through nine are very similar to the binary greatest common divisor algorithm mp\_gcd. In this case -the other variables to the Diophantine equation are solved. The algorithm terminates when $u = 0$ in which case the solution is - -\begin{equation} -Ca + Db = v -\end{equation} - -If $v$, the greatest common divisor of $a$ and $b$ is not equal to one then the algorithm will report an error as no inverse exists. Otherwise, $C$ -is the modular inverse of $a$. The actual value of $C$ is congruent to, but not necessarily equal to, the ideal modular inverse which should lie -within $1 \le a^{-1} < b$. Step numbers twelve and thirteen adjust the inverse until it is in range. If the original input $a$ is within $0 < a < p$ -then only a couple of additions or subtractions will be required to adjust the inverse. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_invmod.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\subsubsection{Odd Moduli} - -When the modulus $b$ is odd the variables $A$ and $C$ are fixed and are not required to compute the inverse. In particular by attempting to solve -the Diophantine $Cb + Da = 1$ only $B$ and $D$ are required to find the inverse of $a$. - -The algorithm fast\_mp\_invmod is a direct adaptation of algorithm mp\_invmod with all all steps involving either $A$ or $C$ removed. This -optimization will halve the time required to compute the modular inverse. - -\section{Primality Tests} - -A non-zero integer $a$ is said to be prime if it is not divisible by any other integer excluding one and itself. For example, $a = 7$ is prime -since the integers $2 \ldots 6$ do not evenly divide $a$. By contrast, $a = 6$ is not prime since $a = 6 = 2 \cdot 3$. - -Prime numbers arise in cryptography considerably as they allow finite fields to be formed. The ability to determine whether an integer is prime or -not quickly has been a viable subject in cryptography and number theory for considerable time. The algorithms that will be presented are all -probablistic algorithms in that when they report an integer is composite it must be composite. However, when the algorithms report an integer is -prime the algorithm may be incorrect. - -As will be discussed it is possible to limit the probability of error so well that for practical purposes the probablity of error might as -well be zero. For the purposes of these discussions let $n$ represent the candidate integer of which the primality is in question. - -\subsection{Trial Division} - -Trial division means to attempt to evenly divide a candidate integer by small prime integers. If the candidate can be evenly divided it obviously -cannot be prime. By dividing by all primes $1 < p \le \sqrt{n}$ this test can actually prove whether an integer is prime. However, such a test -would require a prohibitive amount of time as $n$ grows. - -Instead of dividing by every prime, a smaller, more mangeable set of primes may be used instead. By performing trial division with only a subset -of the primes less than $\sqrt{n} + 1$ the algorithm cannot prove if a candidate is prime. However, often it can prove a candidate is not prime. - -The benefit of this test is that trial division by small values is fairly efficient. Specially compared to the other algorithms that will be -discussed shortly. The probability that this approach correctly identifies a composite candidate when tested with all primes upto $q$ is given by -$1 - {1.12 \over ln(q)}$. The graph (\ref{pic:primality}, will be added later) demonstrates the probability of success for the range -$3 \le q \le 100$. - -At approximately $q = 30$ the gain of performing further tests diminishes fairly quickly. At $q = 90$ further testing is generally not going to -be of any practical use. In the case of LibTomMath the default limit $q = 256$ was chosen since it is not too high and will eliminate -approximately $80\%$ of all candidate integers. The constant \textbf{PRIME\_SIZE} is equal to the number of primes in the test base. The -array \_\_prime\_tab is an array of the first \textbf{PRIME\_SIZE} prime numbers. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_prime\_is\_divisible}. \\ -\textbf{Input}. mp\_int $a$ \\ -\textbf{Output}. $c = 1$ if $n$ is divisible by a small prime, otherwise $c = 0$. \\ -\hline \\ -1. for $ix$ from $0$ to $PRIME\_SIZE$ do \\ -\hspace{3mm}1.1 $d \leftarrow n \mbox{ (mod }\_\_prime\_tab_{ix}\mbox{)}$ \\ -\hspace{3mm}1.2 If $d = 0$ then \\ -\hspace{6mm}1.2.1 $c \leftarrow 1$ \\ -\hspace{6mm}1.2.2 Return(\textit{MP\_OKAY}). \\ -2. $c \leftarrow 0$ \\ -3. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_prime\_is\_divisible} -\end{figure} -\textbf{Algorithm mp\_prime\_is\_divisible.} -This algorithm attempts to determine if a candidate integer $n$ is composite by performing trial divisions. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_is\_divisible.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -The algorithm defaults to a return of $0$ in case an error occurs. The values in the prime table are all specified to be in the range of a -mp\_digit. The table \_\_prime\_tab is defined in the following file. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_prime\_tab.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -Note that there are two possible tables. When an mp\_digit is 7-bits long only the primes upto $127$ may be included, otherwise the primes -upto $1619$ are used. Note that the value of \textbf{PRIME\_SIZE} is a constant dependent on the size of a mp\_digit. - -\subsection{The Fermat Test} -The Fermat test is probably one the oldest tests to have a non-trivial probability of success. It is based on the fact that if $n$ is in -fact prime then $a^{n} \equiv a \mbox{ (mod }n\mbox{)}$ for all $0 < a < n$. The reason being that if $n$ is prime than the order of -the multiplicative sub group is $n - 1$. Any base $a$ must have an order which divides $n - 1$ and as such $a^n$ is equivalent to -$a^1 = a$. - -If $n$ is composite then any given base $a$ does not have to have a period which divides $n - 1$. In which case -it is possible that $a^n \nequiv a \mbox{ (mod }n\mbox{)}$. However, this test is not absolute as it is possible that the order -of a base will divide $n - 1$ which would then be reported as prime. Such a base yields what is known as a Fermat pseudo-prime. Several -integers known as Carmichael numbers will be a pseudo-prime to all valid bases. Fortunately such numbers are extremely rare as $n$ grows -in size. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_prime\_fermat}. \\ -\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\ -\textbf{Output}. $c = 1$ if $b^a \equiv b \mbox{ (mod }a\mbox{)}$, otherwise $c = 0$. \\ -\hline \\ -1. $t \leftarrow b^a \mbox{ (mod }a\mbox{)}$ \\ -2. If $t = b$ then \\ -\hspace{3mm}2.1 $c = 1$ \\ -3. else \\ -\hspace{3mm}3.1 $c = 0$ \\ -4. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_prime\_fermat} -\end{figure} -\textbf{Algorithm mp\_prime\_fermat.} -This algorithm determines whether an mp\_int $a$ is a Fermat prime to the base $b$ or not. It uses a single modular exponentiation to -determine the result. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_fermat.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - -\subsection{The Miller-Rabin Test} -The Miller-Rabin (citation) test is another primality test which has tighter error bounds than the Fermat test specifically with sequentially chosen -candidate integers. The algorithm is based on the observation that if $n - 1 = 2^kr$ and if $b^r \nequiv \pm 1$ then after upto $k - 1$ squarings the -value must be equal to $-1$. The squarings are stopped as soon as $-1$ is observed. If the value of $1$ is observed first it means that -some value not congruent to $\pm 1$ when squared equals one which cannot occur if $n$ is prime. - -\begin{figure}[!here] -\begin{small} -\begin{center} -\begin{tabular}{l} -\hline Algorithm \textbf{mp\_prime\_miller\_rabin}. \\ -\textbf{Input}. mp\_int $a$ and $b$, $a \ge 2$, $0 < b < a$. \\ -\textbf{Output}. $c = 1$ if $a$ is a Miller-Rabin prime to the base $a$, otherwise $c = 0$. \\ -\hline -1. $a' \leftarrow a - 1$ \\ -2. $r \leftarrow n1$ \\ -3. $c \leftarrow 0, s \leftarrow 0$ \\ -4. While $r.used > 0$ and $r_0 \equiv 0 \mbox{ (mod }2\mbox{)}$ \\ -\hspace{3mm}4.1 $s \leftarrow s + 1$ \\ -\hspace{3mm}4.2 $r \leftarrow \lfloor r / 2 \rfloor$ \\ -5. $y \leftarrow b^r \mbox{ (mod }a\mbox{)}$ \\ -6. If $y \nequiv \pm 1$ then \\ -\hspace{3mm}6.1 $j \leftarrow 1$ \\ -\hspace{3mm}6.2 While $j \le (s - 1)$ and $y \nequiv a'$ \\ -\hspace{6mm}6.2.1 $y \leftarrow y^2 \mbox{ (mod }a\mbox{)}$ \\ -\hspace{6mm}6.2.2 If $y = 1$ then goto step 8. \\ -\hspace{6mm}6.2.3 $j \leftarrow j + 1$ \\ -\hspace{3mm}6.3 If $y \nequiv a'$ goto step 8. \\ -7. $c \leftarrow 1$\\ -8. Return(\textit{MP\_OKAY}). \\ -\hline -\end{tabular} -\end{center} -\end{small} -\caption{Algorithm mp\_prime\_miller\_rabin} -\end{figure} -\textbf{Algorithm mp\_prime\_miller\_rabin.} -This algorithm performs one trial round of the Miller-Rabin algorithm to the base $b$. It will set $c = 1$ if the algorithm cannot determine -if $b$ is composite or $c = 0$ if $b$ is provably composite. The values of $s$ and $r$ are computed such that $a' = a - 1 = 2^sr$. - -If the value $y \equiv b^r$ is congruent to $\pm 1$ then the algorithm cannot prove if $a$ is composite or not. Otherwise, the algorithm will -square $y$ upto $s - 1$ times stopping only when $y \equiv -1$. If $y^2 \equiv 1$ and $y \nequiv \pm 1$ then the algorithm can report that $a$ -is provably composite. If the algorithm performs $s - 1$ squarings and $y \nequiv -1$ then $a$ is provably composite. If $a$ is not provably -composite then it is \textit{probably} prime. - -\vspace{+3mm}\begin{small} -\hspace{-5.1mm}{\bf File}: bn\_mp\_prime\_miller\_rabin.c -\vspace{-3mm} -\begin{alltt} -\end{alltt} -\end{small} - - - - -\backmatter -\appendix -\begin{thebibliography}{ABCDEF} -\bibitem[1]{TAOCPV2} -Donald Knuth, \textit{The Art of Computer Programming}, Third Edition, Volume Two, Seminumerical Algorithms, Addison-Wesley, 1998 - -\bibitem[2]{HAC} -A. Menezes, P. van Oorschot, S. Vanstone, \textit{Handbook of Applied Cryptography}, CRC Press, 1996 - -\bibitem[3]{ROSE} -Michael Rosing, \textit{Implementing Elliptic Curve Cryptography}, Manning Publications, 1999 - -\bibitem[4]{COMBA} -Paul G. Comba, \textit{Exponentiation Cryptosystems on the IBM PC}. IBM Systems Journal 29(4): 526-538 (1990) - -\bibitem[5]{KARA} -A. Karatsuba, Doklay Akad. Nauk SSSR 145 (1962), pp.293-294 - -\bibitem[6]{KARAP} -Andre Weimerskirch and Christof Paar, \textit{Generalizations of the Karatsuba Algorithm for Polynomial Multiplication}, Submitted to Design, Codes and Cryptography, March 2002 - -\bibitem[7]{BARRETT} -Paul Barrett, \textit{Implementing the Rivest Shamir and Adleman Public Key Encryption Algorithm on a Standard Digital Signal Processor}, Advances in Cryptology, Crypto '86, Springer-Verlag. - -\bibitem[8]{MONT} -P.L.Montgomery. \textit{Modular multiplication without trial division}. Mathematics of Computation, 44(170):519-521, April 1985. - -\bibitem[9]{DRMET} -Chae Hoon Lim and Pil Joong Lee, \textit{Generating Efficient Primes for Discrete Log Cryptosystems}, POSTECH Information Research Laboratories - -\bibitem[10]{MMB} -J. Daemen and R. Govaerts and J. Vandewalle, \textit{Block ciphers based on Modular Arithmetic}, State and {P}rogress in the {R}esearch of {C}ryptography, 1993, pp. 80-89 - -\bibitem[11]{RSAREF} -R.L. Rivest, A. Shamir, L. Adleman, \textit{A Method for Obtaining Digital Signatures and Public-Key Cryptosystems} - -\bibitem[12]{DHREF} -Whitfield Diffie, Martin E. Hellman, \textit{New Directions in Cryptography}, IEEE Transactions on Information Theory, 1976 - -\bibitem[13]{IEEE} -IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985) - -\bibitem[14]{GMP} -GNU Multiple Precision (GMP), \url{http://www.swox.com/gmp/} - -\bibitem[15]{MPI} -Multiple Precision Integer Library (MPI), Michael Fromberger, \url{http://thayer.dartmouth.edu/~sting/mpi/} - -\bibitem[16]{OPENSSL} -OpenSSL Cryptographic Toolkit, \url{http://openssl.org} - -\bibitem[17]{LIP} -Large Integer Package, \url{http://home.hetnet.nl/~ecstr/LIP.zip} - -\bibitem[18]{ISOC} -JTC1/SC22/WG14, ISO/IEC 9899:1999, ``A draft rationale for the C99 standard.'' - -\bibitem[19]{JAVA} -The Sun Java Website, \url{http://java.sun.com/} - -\end{thebibliography} - -\input{tommath.ind} - -\end{document} diff --git a/lib/hcrypto/libtommath/tommath_class.h b/lib/hcrypto/libtommath/tommath_class.h index 8fd0f52f4..52ba585ec 100644 --- a/lib/hcrypto/libtommath/tommath_class.h +++ b/lib/hcrypto/libtommath/tommath_class.h @@ -1,214 +1,296 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + #if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) +#define LTM_INSIDE #if defined(LTM2) -#define LTM3 +# define LTM3 #endif #if defined(LTM1) -#define LTM2 +# 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_FIND_PRIME_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_ISPRIME_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_MP_ZERO_MULTI_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 +# define BN_CUTOFFS_C +# define BN_DEPRECATED_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_COMPLEMENT_C +# define BN_MP_COPY_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DECR_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_ERROR_TO_STRING_C +# define BN_MP_EXCH_C +# define BN_MP_EXPT_U32_C +# define BN_MP_EXPTMOD_C +# define BN_MP_EXTEUCLID_C +# define BN_MP_FREAD_C +# define BN_MP_FROM_SBIN_C +# define BN_MP_FROM_UBIN_C +# define BN_MP_FWRITE_C +# define BN_MP_GCD_C +# define BN_MP_GET_DOUBLE_C +# define BN_MP_GET_I32_C +# define BN_MP_GET_I64_C +# define BN_MP_GET_L_C +# define BN_MP_GET_LL_C +# define BN_MP_GET_MAG_U32_C +# define BN_MP_GET_MAG_U64_C +# define BN_MP_GET_MAG_UL_C +# define BN_MP_GET_MAG_ULL_C +# define BN_MP_GROW_C +# define BN_MP_INCR_C +# define BN_MP_INIT_C +# define BN_MP_INIT_COPY_C +# define BN_MP_INIT_I32_C +# define BN_MP_INIT_I64_C +# define BN_MP_INIT_L_C +# define BN_MP_INIT_LL_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_INIT_SET_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_INIT_U32_C +# define BN_MP_INIT_U64_C +# define BN_MP_INIT_UL_C +# define BN_MP_INIT_ULL_C +# define BN_MP_INVMOD_C +# define BN_MP_IS_SQUARE_C +# define BN_MP_ISEVEN_C +# define BN_MP_ISODD_C +# define BN_MP_KRONECKER_C +# define BN_MP_LCM_C +# define BN_MP_LOG_U32_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_NEG_C +# define BN_MP_OR_C +# define BN_MP_PACK_C +# define BN_MP_PACK_COUNT_C +# define BN_MP_PRIME_FERMAT_C +# define BN_MP_PRIME_FROBENIUS_UNDERWOOD_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_RAND_C +# define BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_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_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_ROOT_U32_C +# define BN_MP_RSHD_C +# define BN_MP_SBIN_SIZE_C +# define BN_MP_SET_C +# define BN_MP_SET_DOUBLE_C +# define BN_MP_SET_I32_C +# define BN_MP_SET_I64_C +# define BN_MP_SET_L_C +# define BN_MP_SET_LL_C +# define BN_MP_SET_U32_C +# define BN_MP_SET_U64_C +# define BN_MP_SET_UL_C +# define BN_MP_SET_ULL_C +# define BN_MP_SHRINK_C +# define BN_MP_SIGNED_RSH_C +# define BN_MP_SQR_C +# define BN_MP_SQRMOD_C +# define BN_MP_SQRT_C +# define BN_MP_SQRTMOD_PRIME_C +# define BN_MP_SUB_C +# define BN_MP_SUB_D_C +# define BN_MP_SUBMOD_C +# define BN_MP_TO_RADIX_C +# define BN_MP_TO_SBIN_C +# define BN_MP_TO_UBIN_C +# define BN_MP_UBIN_SIZE_C +# define BN_MP_UNPACK_C +# define BN_MP_XOR_C +# define BN_MP_ZERO_C +# define BN_PRIME_TAB_C +# define BN_S_MP_ADD_C +# define BN_S_MP_BALANCE_MUL_C +# define BN_S_MP_EXPTMOD_C +# define BN_S_MP_EXPTMOD_FAST_C +# define BN_S_MP_GET_BIT_C +# define BN_S_MP_INVMOD_FAST_C +# define BN_S_MP_INVMOD_SLOW_C +# define BN_S_MP_KARATSUBA_MUL_C +# define BN_S_MP_KARATSUBA_SQR_C +# define BN_S_MP_MONTGOMERY_REDUCE_FAST_C +# define BN_S_MP_MUL_DIGS_C +# define BN_S_MP_MUL_DIGS_FAST_C +# define BN_S_MP_MUL_HIGH_DIGS_C +# define BN_S_MP_MUL_HIGH_DIGS_FAST_C +# define BN_S_MP_PRIME_IS_DIVISIBLE_C +# define BN_S_MP_RAND_JENKINS_C +# define BN_S_MP_RAND_PLATFORM_C +# define BN_S_MP_REVERSE_C +# define BN_S_MP_SQR_C +# define BN_S_MP_SQR_FAST_C +# define BN_S_MP_SUB_C +# define BN_S_MP_TOOM_MUL_C +# define BN_S_MP_TOOM_SQR_C +#endif +#endif +#if defined(BN_CUTOFFS_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 +#if defined(BN_DEPRECATED_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_AND_C +# define BN_MP_BALANCE_MUL_C +# define BN_MP_CMP_D_C +# define BN_MP_EXPORT_C +# define BN_MP_EXPTMOD_FAST_C +# define BN_MP_EXPT_D_C +# define BN_MP_EXPT_D_EX_C +# define BN_MP_EXPT_U32_C +# define BN_MP_FROM_SBIN_C +# define BN_MP_FROM_UBIN_C +# define BN_MP_GET_BIT_C +# define BN_MP_GET_INT_C +# define BN_MP_GET_LONG_C +# define BN_MP_GET_LONG_LONG_C +# define BN_MP_GET_MAG_U32_C +# define BN_MP_GET_MAG_ULL_C +# define BN_MP_GET_MAG_UL_C +# define BN_MP_IMPORT_C +# define BN_MP_INIT_SET_INT_C +# define BN_MP_INIT_U32_C +# define BN_MP_INVMOD_SLOW_C +# define BN_MP_JACOBI_C +# define BN_MP_KARATSUBA_MUL_C +# define BN_MP_KARATSUBA_SQR_C +# define BN_MP_KRONECKER_C +# define BN_MP_N_ROOT_C +# define BN_MP_N_ROOT_EX_C +# define BN_MP_OR_C +# define BN_MP_PACK_C +# define BN_MP_PRIME_IS_DIVISIBLE_C +# define BN_MP_PRIME_RANDOM_EX_C +# define BN_MP_RAND_DIGIT_C +# define BN_MP_READ_SIGNED_BIN_C +# define BN_MP_READ_UNSIGNED_BIN_C +# define BN_MP_ROOT_U32_C +# define BN_MP_SBIN_SIZE_C +# define BN_MP_SET_INT_C +# define BN_MP_SET_LONG_C +# define BN_MP_SET_LONG_LONG_C +# define BN_MP_SET_U32_C +# define BN_MP_SET_U64_C +# define BN_MP_SIGNED_BIN_SIZE_C +# define BN_MP_SIGNED_RSH_C +# define BN_MP_TC_AND_C +# define BN_MP_TC_DIV_2D_C +# define BN_MP_TC_OR_C +# define BN_MP_TC_XOR_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_TO_RADIX_C +# define BN_MP_TO_SBIN_C +# define BN_MP_TO_SIGNED_BIN_C +# define BN_MP_TO_SIGNED_BIN_N_C +# define BN_MP_TO_UBIN_C +# define BN_MP_TO_UNSIGNED_BIN_C +# define BN_MP_TO_UNSIGNED_BIN_N_C +# define BN_MP_UBIN_SIZE_C +# define BN_MP_UNPACK_C +# define BN_MP_UNSIGNED_BIN_SIZE_C +# define BN_MP_XOR_C +# define BN_S_MP_BALANCE_MUL_C +# define BN_S_MP_EXPTMOD_FAST_C +# define BN_S_MP_GET_BIT_C +# define BN_S_MP_INVMOD_FAST_C +# define BN_S_MP_INVMOD_SLOW_C +# define BN_S_MP_KARATSUBA_MUL_C +# define BN_S_MP_KARATSUBA_SQR_C +# define BN_S_MP_MONTGOMERY_REDUCE_FAST_C +# define BN_S_MP_MUL_DIGS_FAST_C +# define BN_S_MP_MUL_HIGH_DIGS_FAST_C +# define BN_S_MP_PRIME_IS_DIVISIBLE_C +# define BN_S_MP_PRIME_RANDOM_EX_C +# define BN_S_MP_RAND_SOURCE_C +# define BN_S_MP_REVERSE_C +# define BN_S_MP_SQR_FAST_C +# define BN_S_MP_TOOM_MUL_C +# define BN_S_MP_TOOM_SQR_C #endif #if defined(BN_MP_2EXPT_C) - #define BN_MP_ZERO_C - #define BN_MP_GROW_C +# define BN_MP_GROW_C +# define BN_MP_ZERO_C #endif #if defined(BN_MP_ABS_C) - #define BN_MP_COPY_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 +# define BN_MP_CMP_MAG_C +# define BN_S_MP_ADD_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 +# define BN_MP_CLAMP_C +# define BN_MP_GROW_C +# define BN_MP_SUB_D_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 +# define BN_MP_ADD_C +# define BN_MP_CLEAR_C +# define BN_MP_INIT_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 +# define BN_MP_CLAMP_C +# define BN_MP_GROW_C #endif #if defined(BN_MP_CLAMP_C) @@ -218,11 +300,11 @@ #endif #if defined(BN_MP_CLEAR_MULTI_C) - #define BN_MP_CLEAR_C +# define BN_MP_CLEAR_C #endif #if defined(BN_MP_CMP_C) - #define BN_MP_CMP_MAG_C +# define BN_MP_CMP_MAG_C #endif #if defined(BN_MP_CMP_D_C) @@ -232,699 +314,788 @@ #endif #if defined(BN_MP_CNT_LSB_C) - #define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_COMPLEMENT_C) +# define BN_MP_NEG_C +# define BN_MP_SUB_D_C #endif #if defined(BN_MP_COPY_C) - #define BN_MP_GROW_C +# define BN_MP_GROW_C #endif #if defined(BN_MP_COUNT_BITS_C) #endif +#if defined(BN_MP_DECR_C) +# define BN_MP_INCR_C +# define BN_MP_SET_C +# define BN_MP_SUB_D_C +# define BN_MP_ZERO_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 +# define BN_MP_ADD_C +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_CMP_C +# define BN_MP_CMP_MAG_C +# define BN_MP_COPY_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_2D_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_C +# define BN_MP_INIT_COPY_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_LSHD_C +# define BN_MP_MUL_2D_C +# define BN_MP_MUL_D_C +# define BN_MP_RSHD_C +# define BN_MP_SUB_C +# define BN_MP_ZERO_C #endif #if defined(BN_MP_DIV_2_C) - #define BN_MP_GROW_C - #define BN_MP_CLAMP_C +# define BN_MP_CLAMP_C +# define BN_MP_GROW_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 +# define BN_MP_CLAMP_C +# define BN_MP_COPY_C +# define BN_MP_MOD_2D_C +# define BN_MP_RSHD_C +# define BN_MP_ZERO_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 +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_SIZE_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 +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_COPY_C +# define BN_MP_DIV_2D_C +# define BN_MP_DIV_3_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_SIZE_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 +# define BN_MP_CLAMP_C +# define BN_MP_CMP_MAG_C +# define BN_MP_GROW_C +# define BN_S_MP_SUB_C #endif #if defined(BN_MP_DR_SETUP_C) #endif +#if defined(BN_MP_ERROR_TO_STRING_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 +#if defined(BN_MP_EXPT_U32_C) +# define BN_MP_CLEAR_C +# define BN_MP_INIT_COPY_C +# define BN_MP_MUL_C +# define BN_MP_SET_C +# define BN_MP_SQR_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 +# define BN_MP_ABS_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_DR_IS_MODULUS_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_INVMOD_C +# define BN_MP_REDUCE_IS_2K_C +# define BN_MP_REDUCE_IS_2K_L_C +# define BN_S_MP_EXPTMOD_C +# define BN_S_MP_EXPTMOD_FAST_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 +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_COPY_C +# define BN_MP_DIV_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_MUL_C +# define BN_MP_NEG_C +# define BN_MP_SET_C +# define BN_MP_SUB_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 +# define BN_MP_ADD_D_C +# define BN_MP_MUL_D_C +# define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_FROM_SBIN_C) +# define BN_MP_FROM_UBIN_C +#endif + +#if defined(BN_MP_FROM_UBIN_C) +# define BN_MP_CLAMP_C +# define BN_MP_GROW_C +# define BN_MP_MUL_2D_C +# define BN_MP_ZERO_C #endif #if defined(BN_MP_FWRITE_C) - #define BN_MP_RADIX_SIZE_C - #define BN_MP_TORADIX_C +# define BN_MP_RADIX_SIZE_C +# define BN_MP_TO_RADIX_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 +# define BN_MP_ABS_C +# define BN_MP_CLEAR_C +# define BN_MP_CMP_MAG_C +# define BN_MP_CNT_LSB_C +# define BN_MP_DIV_2D_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_COPY_C +# define BN_MP_MUL_2D_C +# define BN_S_MP_SUB_C #endif -#if defined(BN_MP_GET_INT_C) +#if defined(BN_MP_GET_DOUBLE_C) +#endif + +#if defined(BN_MP_GET_I32_C) +# define BN_MP_GET_MAG_U32_C +#endif + +#if defined(BN_MP_GET_I64_C) +# define BN_MP_GET_MAG_U64_C +#endif + +#if defined(BN_MP_GET_L_C) +# define BN_MP_GET_MAG_UL_C +#endif + +#if defined(BN_MP_GET_LL_C) +# define BN_MP_GET_MAG_ULL_C +#endif + +#if defined(BN_MP_GET_MAG_U32_C) +#endif + +#if defined(BN_MP_GET_MAG_U64_C) +#endif + +#if defined(BN_MP_GET_MAG_UL_C) +#endif + +#if defined(BN_MP_GET_MAG_ULL_C) #endif #if defined(BN_MP_GROW_C) #endif +#if defined(BN_MP_INCR_C) +# define BN_MP_ADD_D_C +# define BN_MP_DECR_C +# define BN_MP_SET_C +#endif + #if defined(BN_MP_INIT_C) #endif #if defined(BN_MP_INIT_COPY_C) - #define BN_MP_COPY_C +# define BN_MP_CLEAR_C +# define BN_MP_COPY_C +# define BN_MP_INIT_SIZE_C +#endif + +#if defined(BN_MP_INIT_I32_C) +# define BN_MP_INIT_C +# define BN_MP_SET_I32_C +#endif + +#if defined(BN_MP_INIT_I64_C) +# define BN_MP_INIT_C +# define BN_MP_SET_I64_C +#endif + +#if defined(BN_MP_INIT_L_C) +# define BN_MP_INIT_C +# define BN_MP_SET_L_C +#endif + +#if defined(BN_MP_INIT_LL_C) +# define BN_MP_INIT_C +# define BN_MP_SET_LL_C #endif #if defined(BN_MP_INIT_MULTI_C) - #define BN_MP_ERR_C - #define BN_MP_INIT_C - #define BN_MP_CLEAR_C +# define BN_MP_CLEAR_C +# define BN_MP_INIT_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 +# define BN_MP_INIT_C +# define BN_MP_SET_C #endif #if defined(BN_MP_INIT_SIZE_C) - #define BN_MP_INIT_C +#endif + +#if defined(BN_MP_INIT_U32_C) +# define BN_MP_INIT_C +# define BN_MP_SET_U32_C +#endif + +#if defined(BN_MP_INIT_U64_C) +# define BN_MP_INIT_C +# define BN_MP_SET_U64_C +#endif + +#if defined(BN_MP_INIT_UL_C) +# define BN_MP_INIT_C +# define BN_MP_SET_UL_C +#endif + +#if defined(BN_MP_INIT_ULL_C) +# define BN_MP_INIT_C +# define BN_MP_SET_ULL_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 +# define BN_MP_CMP_D_C +# define BN_S_MP_INVMOD_FAST_C +# define BN_S_MP_INVMOD_SLOW_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 +# define BN_MP_CLEAR_C +# define BN_MP_CMP_MAG_C +# define BN_MP_GET_I32_C +# define BN_MP_INIT_U32_C +# define BN_MP_MOD_C +# define BN_MP_MOD_D_C +# define BN_MP_SQRT_C +# define BN_MP_SQR_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 +#if defined(BN_MP_ISEVEN_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 +#if defined(BN_MP_ISODD_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 +#if defined(BN_MP_KRONECKER_C) +# define BN_MP_CLEAR_C +# define BN_MP_CMP_D_C +# define BN_MP_CNT_LSB_C +# define BN_MP_COPY_C +# define BN_MP_DIV_2D_C +# define BN_MP_INIT_C +# define BN_MP_INIT_COPY_C +# define BN_MP_MOD_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 +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_CMP_MAG_C +# define BN_MP_DIV_C +# define BN_MP_GCD_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_MUL_C +#endif + +#if defined(BN_MP_LOG_U32_C) +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_CMP_C +# define BN_MP_CMP_D_C +# define BN_MP_COPY_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_EXCH_C +# define BN_MP_EXPT_U32_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_MUL_C +# define BN_MP_SET_C +# define BN_MP_SQR_C #endif #if defined(BN_MP_LSHD_C) - #define BN_MP_GROW_C - #define BN_MP_RSHD_C +# define BN_MP_GROW_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 +# define BN_MP_ADD_C +# define BN_MP_CLEAR_C +# define BN_MP_DIV_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_SIZE_C #endif #if defined(BN_MP_MOD_2D_C) - #define BN_MP_ZERO_C - #define BN_MP_COPY_C - #define BN_MP_CLAMP_C +# define BN_MP_CLAMP_C +# define BN_MP_COPY_C +# define BN_MP_ZERO_C #endif #if defined(BN_MP_MOD_D_C) - #define BN_MP_DIV_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 +# define BN_MP_2EXPT_C +# define BN_MP_CMP_MAG_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_MUL_2_C +# define BN_MP_SET_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 +# define BN_MP_CLAMP_C +# define BN_MP_CMP_MAG_C +# define BN_MP_GROW_C +# define BN_MP_RSHD_C +# define BN_S_MP_MONTGOMERY_REDUCE_FAST_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 +# define BN_S_MP_BALANCE_MUL_C +# define BN_S_MP_KARATSUBA_MUL_C +# define BN_S_MP_MUL_DIGS_C +# define BN_S_MP_MUL_DIGS_FAST_C +# define BN_S_MP_TOOM_MUL_C #endif #if defined(BN_MP_MUL_2_C) - #define BN_MP_GROW_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 +# define BN_MP_CLAMP_C +# define BN_MP_COPY_C +# define BN_MP_GROW_C +# define BN_MP_LSHD_C #endif #if defined(BN_MP_MUL_D_C) - #define BN_MP_GROW_C - #define BN_MP_CLAMP_C +# define BN_MP_CLAMP_C +# define BN_MP_GROW_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 +# define BN_MP_CLEAR_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_MOD_C +# define BN_MP_MUL_C #endif #if defined(BN_MP_NEG_C) - #define BN_MP_COPY_C - #define BN_MP_ISZERO_C +# define BN_MP_COPY_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 +# define BN_MP_CLAMP_C +# define BN_MP_GROW_C +#endif + +#if defined(BN_MP_PACK_C) +# define BN_MP_CLEAR_C +# define BN_MP_DIV_2D_C +# define BN_MP_INIT_COPY_C +# define BN_MP_PACK_COUNT_C +#endif + +#if defined(BN_MP_PACK_COUNT_C) +# define BN_MP_COUNT_BITS_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 +# define BN_MP_CLEAR_C +# define BN_MP_CMP_C +# define BN_MP_CMP_D_C +# define BN_MP_EXPTMOD_C +# define BN_MP_INIT_C #endif -#if defined(BN_MP_PRIME_IS_DIVISIBLE_C) - #define BN_MP_MOD_D_C +#if defined(BN_MP_PRIME_FROBENIUS_UNDERWOOD_C) +# define BN_MP_ADD_C +# define BN_MP_ADD_D_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_CMP_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_EXCH_C +# define BN_MP_GCD_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_KRONECKER_C +# define BN_MP_MOD_C +# define BN_MP_MUL_2_C +# define BN_MP_MUL_C +# define BN_MP_MUL_D_C +# define BN_MP_SET_C +# define BN_MP_SET_U32_C +# define BN_MP_SQR_C +# define BN_MP_SUB_C +# define BN_MP_SUB_D_C +# define BN_S_MP_GET_BIT_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 +# define BN_MP_CLEAR_C +# define BN_MP_CMP_C +# define BN_MP_CMP_D_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_2D_C +# define BN_MP_INIT_SET_C +# define BN_MP_IS_SQUARE_C +# define BN_MP_PRIME_MILLER_RABIN_C +# define BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_C +# define BN_MP_RAND_C +# define BN_MP_READ_RADIX_C +# define BN_MP_SET_C +# define BN_S_MP_PRIME_IS_DIVISIBLE_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 +# define BN_MP_CLEAR_C +# define BN_MP_CMP_C +# define BN_MP_CMP_D_C +# define BN_MP_CNT_LSB_C +# define BN_MP_DIV_2D_C +# define BN_MP_EXPTMOD_C +# define BN_MP_INIT_C +# define BN_MP_INIT_COPY_C +# define BN_MP_SQRMOD_C +# define BN_MP_SUB_D_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 +# define BN_MP_ADD_D_C +# define BN_MP_CLEAR_C +# define BN_MP_CMP_D_C +# define BN_MP_INIT_C +# define BN_MP_MOD_D_C +# define BN_MP_PRIME_IS_PRIME_C +# define BN_MP_SET_C +# define BN_MP_SUB_D_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 +#if defined(BN_MP_PRIME_RAND_C) +# define BN_MP_ADD_D_C +# define BN_MP_DIV_2_C +# define BN_MP_FROM_UBIN_C +# define BN_MP_MUL_2_C +# define BN_MP_PRIME_IS_PRIME_C +# define BN_MP_SUB_D_C +# define BN_S_MP_PRIME_RANDOM_EX_C +# define BN_S_MP_RAND_CB_C +# define BN_S_MP_RAND_SOURCE_C +#endif + +#if defined(BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_C) +# define BN_MP_ADD_C +# define BN_MP_ADD_D_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_CNT_LSB_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_2D_C +# define BN_MP_DIV_2_C +# define BN_MP_GCD_C +# define BN_MP_INIT_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_KRONECKER_C +# define BN_MP_MOD_C +# define BN_MP_MUL_2_C +# define BN_MP_MUL_C +# define BN_MP_SET_C +# define BN_MP_SET_I32_C +# define BN_MP_SET_U32_C +# define BN_MP_SQR_C +# define BN_MP_SUB_C +# define BN_MP_SUB_D_C +# define BN_S_MP_GET_BIT_C +# define BN_S_MP_MUL_SI_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 +# define BN_MP_CLEAR_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_D_C +# define BN_MP_INIT_COPY_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 +# define BN_MP_GROW_C +# define BN_MP_RAND_SOURCE_C +# define BN_MP_ZERO_C +# define BN_S_MP_RAND_PLATFORM_C +# define BN_S_MP_RAND_SOURCE_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 +# define BN_MP_ADD_D_C +# define BN_MP_MUL_D_C +# define BN_MP_ZERO_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 +# define BN_MP_ADD_C +# define BN_MP_CLEAR_C +# define BN_MP_CMP_C +# define BN_MP_CMP_D_C +# define BN_MP_INIT_COPY_C +# define BN_MP_LSHD_C +# define BN_MP_MOD_2D_C +# define BN_MP_MUL_C +# define BN_MP_RSHD_C +# define BN_MP_SET_C +# define BN_MP_SUB_C +# define BN_S_MP_MUL_DIGS_C +# define BN_S_MP_MUL_HIGH_DIGS_C +# define BN_S_MP_MUL_HIGH_DIGS_FAST_C +# define BN_S_MP_SUB_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 +# define BN_MP_CLEAR_C +# define BN_MP_CMP_MAG_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_2D_C +# define BN_MP_INIT_C +# define BN_MP_MUL_D_C +# define BN_S_MP_ADD_C +# define BN_S_MP_SUB_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 +# define BN_MP_CLEAR_C +# define BN_MP_CMP_MAG_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_2D_C +# define BN_MP_INIT_C +# define BN_MP_MUL_C +# define BN_S_MP_ADD_C +# define BN_S_MP_SUB_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 +# define BN_MP_2EXPT_C +# define BN_MP_CLEAR_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_INIT_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 +# define BN_MP_2EXPT_C +# define BN_MP_CLEAR_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_INIT_C +# define BN_S_MP_SUB_C #endif #if defined(BN_MP_REDUCE_IS_2K_C) - #define BN_MP_REDUCE_2K_C - #define BN_MP_COUNT_BITS_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 +# define BN_MP_2EXPT_C +# define BN_MP_DIV_C +#endif + +#if defined(BN_MP_ROOT_U32_C) +# define BN_MP_2EXPT_C +# define BN_MP_ADD_D_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_CMP_C +# define BN_MP_COPY_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DIV_C +# define BN_MP_EXCH_C +# define BN_MP_EXPT_U32_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_MUL_C +# define BN_MP_MUL_D_C +# define BN_MP_SET_C +# define BN_MP_SUB_C +# define BN_MP_SUB_D_C #endif #if defined(BN_MP_RSHD_C) - #define BN_MP_ZERO_C +# define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_SBIN_SIZE_C) +# define BN_MP_UBIN_SIZE_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 +#if defined(BN_MP_SET_DOUBLE_C) +# define BN_MP_DIV_2D_C +# define BN_MP_MUL_2D_C +# define BN_MP_SET_U64_C +#endif + +#if defined(BN_MP_SET_I32_C) +# define BN_MP_SET_U32_C +#endif + +#if defined(BN_MP_SET_I64_C) +# define BN_MP_SET_U64_C +#endif + +#if defined(BN_MP_SET_L_C) +# define BN_MP_SET_UL_C +#endif + +#if defined(BN_MP_SET_LL_C) +# define BN_MP_SET_ULL_C +#endif + +#if defined(BN_MP_SET_U32_C) +#endif + +#if defined(BN_MP_SET_U64_C) +#endif + +#if defined(BN_MP_SET_UL_C) +#endif + +#if defined(BN_MP_SET_ULL_C) #endif #if defined(BN_MP_SHRINK_C) #endif -#if defined(BN_MP_SIGNED_BIN_SIZE_C) - #define BN_MP_UNSIGNED_BIN_SIZE_C +#if defined(BN_MP_SIGNED_RSH_C) +# define BN_MP_ADD_D_C +# define BN_MP_DIV_2D_C +# define BN_MP_SUB_D_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 +# define BN_S_MP_KARATSUBA_SQR_C +# define BN_S_MP_SQR_C +# define BN_S_MP_SQR_FAST_C +# define BN_S_MP_TOOM_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 +# define BN_MP_CLEAR_C +# define BN_MP_INIT_C +# define BN_MP_MOD_C +# define BN_MP_SQR_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 +# define BN_MP_ADD_C +# define BN_MP_CLEAR_C +# define BN_MP_CMP_MAG_C +# define BN_MP_DIV_2_C +# define BN_MP_DIV_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_C +# define BN_MP_INIT_COPY_C +# define BN_MP_RSHD_C +# define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_SQRTMOD_PRIME_C) +# define BN_MP_ADD_D_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_CMP_D_C +# define BN_MP_COPY_C +# define BN_MP_DIV_2_C +# define BN_MP_EXPTMOD_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_KRONECKER_C +# define BN_MP_MOD_D_C +# define BN_MP_MULMOD_C +# define BN_MP_SET_C +# define BN_MP_SET_U32_C +# define BN_MP_SQRMOD_C +# define BN_MP_SUB_D_C +# define BN_MP_ZERO_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 +# define BN_MP_CMP_MAG_C +# define BN_S_MP_ADD_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 +# define BN_MP_ADD_D_C +# define BN_MP_CLAMP_C +# define BN_MP_GROW_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 +# define BN_MP_CLEAR_C +# define BN_MP_INIT_C +# define BN_MP_MOD_C +# define BN_MP_SUB_C #endif -#if defined(BN_MP_TO_SIGNED_BIN_C) - #define BN_MP_TO_UNSIGNED_BIN_C +#if defined(BN_MP_TO_RADIX_C) +# define BN_MP_CLEAR_C +# define BN_MP_DIV_D_C +# define BN_MP_INIT_COPY_C +# define BN_S_MP_REVERSE_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 +#if defined(BN_MP_TO_SBIN_C) +# define BN_MP_TO_UBIN_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 +#if defined(BN_MP_TO_UBIN_C) +# define BN_MP_CLEAR_C +# define BN_MP_DIV_2D_C +# define BN_MP_INIT_COPY_C +# define BN_MP_UBIN_SIZE_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 +#if defined(BN_MP_UBIN_SIZE_C) +# define BN_MP_COUNT_BITS_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 +#if defined(BN_MP_UNPACK_C) +# define BN_MP_CLAMP_C +# define BN_MP_MUL_2D_C +# define BN_MP_ZERO_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 +# define BN_MP_CLAMP_C +# define BN_MP_GROW_C #endif #if defined(BN_MP_ZERO_C) @@ -933,70 +1104,216 @@ #if defined(BN_PRIME_TAB_C) #endif -#if defined(BN_REVERSE_C) +#if defined(BN_S_MP_ADD_C) +# define BN_MP_CLAMP_C +# define BN_MP_GROW_C #endif -#if defined(BN_S_MP_ADD_C) - #define BN_MP_GROW_C - #define BN_MP_CLAMP_C +#if defined(BN_S_MP_BALANCE_MUL_C) +# define BN_MP_ADD_C +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_LSHD_C +# define BN_MP_MUL_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 +# define BN_MP_CLEAR_C +# define BN_MP_COPY_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_C +# define BN_MP_MOD_C +# define BN_MP_MUL_C +# define BN_MP_REDUCE_2K_L_C +# define BN_MP_REDUCE_2K_SETUP_L_C +# define BN_MP_REDUCE_C +# define BN_MP_REDUCE_SETUP_C +# define BN_MP_SET_C +# define BN_MP_SQR_C +#endif + +#if defined(BN_S_MP_EXPTMOD_FAST_C) +# define BN_MP_CLEAR_C +# define BN_MP_COPY_C +# define BN_MP_COUNT_BITS_C +# define BN_MP_DR_REDUCE_C +# define BN_MP_DR_SETUP_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_MOD_C +# define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +# define BN_MP_MONTGOMERY_REDUCE_C +# define BN_MP_MONTGOMERY_SETUP_C +# define BN_MP_MULMOD_C +# define BN_MP_MUL_C +# define BN_MP_REDUCE_2K_C +# define BN_MP_REDUCE_2K_SETUP_C +# define BN_MP_SET_C +# define BN_MP_SQR_C +# define BN_S_MP_MONTGOMERY_REDUCE_FAST_C +#endif + +#if defined(BN_S_MP_GET_BIT_C) +#endif + +#if defined(BN_S_MP_INVMOD_FAST_C) +# define BN_MP_ADD_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_COPY_C +# define BN_MP_DIV_2_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_MOD_C +# define BN_MP_SET_C +# define BN_MP_SUB_C +#endif + +#if defined(BN_S_MP_INVMOD_SLOW_C) +# define BN_MP_ADD_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_COPY_C +# define BN_MP_DIV_2_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_MOD_C +# define BN_MP_SET_C +# define BN_MP_SUB_C +#endif + +#if defined(BN_S_MP_KARATSUBA_MUL_C) +# define BN_MP_ADD_C +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_LSHD_C +# define BN_MP_MUL_C +# define BN_S_MP_ADD_C +# define BN_S_MP_SUB_C +#endif + +#if defined(BN_S_MP_KARATSUBA_SQR_C) +# define BN_MP_ADD_C +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_LSHD_C +# define BN_MP_SQR_C +# define BN_S_MP_ADD_C +# define BN_S_MP_SUB_C +#endif + +#if defined(BN_S_MP_MONTGOMERY_REDUCE_FAST_C) +# define BN_MP_CLAMP_C +# define BN_MP_CMP_MAG_C +# define BN_MP_GROW_C +# define BN_S_MP_SUB_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 +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_SIZE_C +# define BN_S_MP_MUL_DIGS_FAST_C +#endif + +#if defined(BN_S_MP_MUL_DIGS_FAST_C) +# define BN_MP_CLAMP_C +# define BN_MP_GROW_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 +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_SIZE_C +# define BN_S_MP_MUL_HIGH_DIGS_FAST_C +#endif + +#if defined(BN_S_MP_MUL_HIGH_DIGS_FAST_C) +# define BN_MP_CLAMP_C +# define BN_MP_GROW_C +#endif + +#if defined(BN_S_MP_PRIME_IS_DIVISIBLE_C) +# define BN_MP_MOD_D_C +#endif + +#if defined(BN_S_MP_RAND_JENKINS_C) +# define BN_S_MP_RAND_JENKINS_INIT_C +#endif + +#if defined(BN_S_MP_RAND_PLATFORM_C) +#endif + +#if defined(BN_S_MP_REVERSE_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 +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_EXCH_C +# define BN_MP_INIT_SIZE_C +#endif + +#if defined(BN_S_MP_SQR_FAST_C) +# define BN_MP_CLAMP_C +# define BN_MP_GROW_C #endif #if defined(BN_S_MP_SUB_C) - #define BN_MP_GROW_C - #define BN_MP_CLAMP_C +# define BN_MP_CLAMP_C +# define BN_MP_GROW_C #endif -#if defined(BNCORE_C) +#if defined(BN_S_MP_TOOM_MUL_C) +# define BN_MP_ADD_C +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_DIV_2_C +# define BN_MP_DIV_3_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_LSHD_C +# define BN_MP_MUL_2_C +# define BN_MP_MUL_C +# define BN_MP_SUB_C #endif +#if defined(BN_S_MP_TOOM_SQR_C) +# define BN_MP_ADD_C +# define BN_MP_CLAMP_C +# define BN_MP_CLEAR_C +# define BN_MP_DIV_2_C +# define BN_MP_INIT_C +# define BN_MP_INIT_SIZE_C +# define BN_MP_LSHD_C +# define BN_MP_MUL_2_C +# define BN_MP_MUL_C +# define BN_MP_SQR_C +# define BN_MP_SUB_C +#endif + +#ifdef LTM_INSIDE +#undef LTM_INSIDE #ifdef LTM3 -#define LTM_LAST -#endif -#include -#include -#else -#define LTM_LAST +# define LTM_LAST #endif -/* $Source: /cvs/libtom/libtommath/tommath_class.h,v $ */ -/* $Revision: 1.3 $ */ -/* $Date: 2005/07/28 11:59:32 $ */ +#include "tommath_superclass.h" +#include "tommath_class.h" +#else +# define LTM_LAST +#endif diff --git a/lib/hcrypto/libtommath/tommath_cutoffs.h b/lib/hcrypto/libtommath/tommath_cutoffs.h new file mode 100644 index 000000000..a65a9b3e3 --- /dev/null +++ b/lib/hcrypto/libtommath/tommath_cutoffs.h @@ -0,0 +1,13 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* + Current values evaluated on an AMD A8-6600K (64-bit). + Type "make tune" to optimize them for your machine but + be aware that it may take a long time. It took 2:30 minutes + on the aforementioned machine for example. + */ + +#define MP_DEFAULT_KARATSUBA_MUL_CUTOFF 80 +#define MP_DEFAULT_KARATSUBA_SQR_CUTOFF 120 +#define MP_DEFAULT_TOOM_MUL_CUTOFF 350 +#define MP_DEFAULT_TOOM_SQR_CUTOFF 400 diff --git a/lib/hcrypto/libtommath/tommath_private.h b/lib/hcrypto/libtommath/tommath_private.h new file mode 100644 index 000000000..1a0096f85 --- /dev/null +++ b/lib/hcrypto/libtommath/tommath_private.h @@ -0,0 +1,303 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef TOMMATH_PRIV_H_ +#define TOMMATH_PRIV_H_ + +#include "tommath.h" +#include "tommath_class.h" + +/* + * Private symbols + * --------------- + * + * On Unix symbols can be marked as hidden if libtommath is compiled + * as a shared object. By default, symbols are visible. + * As of now, this feature is opt-in via the MP_PRIVATE_SYMBOLS define. + * + * On Win32 a .def file must be used to specify the exported symbols. + */ +#if defined (MP_PRIVATE_SYMBOLS) && defined(__GNUC__) && __GNUC__ >= 4 +# define MP_PRIVATE __attribute__ ((visibility ("hidden"))) +#else +# define MP_PRIVATE +#endif + +/* Hardening libtommath + * -------------------- + * + * By default memory is zeroed before calling + * MP_FREE to avoid leaking data. This is good + * practice in cryptographical applications. + * + * Note however that memory allocators used + * in cryptographical applications can often + * be configured by itself to clear memory, + * rendering the clearing in tommath unnecessary. + * See for example https://github.com/GrapheneOS/hardened_malloc + * and the option CONFIG_ZERO_ON_FREE. + * + * Furthermore there are applications which + * value performance more and want this + * feature to be disabled. For such applications + * define MP_NO_ZERO_ON_FREE during compilation. + */ +#ifdef MP_NO_ZERO_ON_FREE +# define MP_FREE_BUFFER(mem, size) MP_FREE((mem), (size)) +# define MP_FREE_DIGITS(mem, digits) MP_FREE((mem), sizeof (mp_digit) * (size_t)(digits)) +#else +# define MP_FREE_BUFFER(mem, size) \ +do { \ + size_t fs_ = (size); \ + void* fm_ = (mem); \ + if (fm_ != NULL) { \ + MP_ZERO_BUFFER(fm_, fs_); \ + MP_FREE(fm_, fs_); \ + } \ +} while (0) +# define MP_FREE_DIGITS(mem, digits) \ +do { \ + int fd_ = (digits); \ + void* fm_ = (mem); \ + if (fm_ != NULL) { \ + size_t fs_ = sizeof (mp_digit) * (size_t)fd_; \ + MP_ZERO_BUFFER(fm_, fs_); \ + MP_FREE(fm_, fs_); \ + } \ +} while (0) +#endif + +#ifdef MP_USE_MEMSET +# include +# define MP_ZERO_BUFFER(mem, size) memset((mem), 0, (size)) +# define MP_ZERO_DIGITS(mem, digits) \ +do { \ + int zd_ = (digits); \ + if (zd_ > 0) { \ + memset((mem), 0, sizeof(mp_digit) * (size_t)zd_); \ + } \ +} while (0) +#else +# define MP_ZERO_BUFFER(mem, size) \ +do { \ + size_t zs_ = (size); \ + char* zm_ = (char*)(mem); \ + while (zs_-- > 0u) { \ + *zm_++ = '\0'; \ + } \ +} while (0) +# define MP_ZERO_DIGITS(mem, digits) \ +do { \ + int zd_ = (digits); \ + mp_digit* zm_ = (mem); \ + while (zd_-- > 0) { \ + *zm_++ = 0; \ + } \ +} while (0) +#endif + +/* Tunable cutoffs + * --------------- + * + * - In the default settings, a cutoff X can be modified at runtime + * by adjusting the corresponding X_CUTOFF variable. + * + * - Tunability of the library can be disabled at compile time + * by defining the MP_FIXED_CUTOFFS macro. + * + * - There is an additional file tommath_cutoffs.h, which defines + * the default cutoffs. These can be adjusted manually or by the + * autotuner. + * + */ + +#ifdef MP_FIXED_CUTOFFS +# include "tommath_cutoffs.h" +# define MP_KARATSUBA_MUL_CUTOFF MP_DEFAULT_KARATSUBA_MUL_CUTOFF +# define MP_KARATSUBA_SQR_CUTOFF MP_DEFAULT_KARATSUBA_SQR_CUTOFF +# define MP_TOOM_MUL_CUTOFF MP_DEFAULT_TOOM_MUL_CUTOFF +# define MP_TOOM_SQR_CUTOFF MP_DEFAULT_TOOM_SQR_CUTOFF +#else +# define MP_KARATSUBA_MUL_CUTOFF KARATSUBA_MUL_CUTOFF +# define MP_KARATSUBA_SQR_CUTOFF KARATSUBA_SQR_CUTOFF +# define MP_TOOM_MUL_CUTOFF TOOM_MUL_CUTOFF +# define MP_TOOM_SQR_CUTOFF TOOM_SQR_CUTOFF +#endif + +/* define heap macros */ +#ifndef MP_MALLOC +/* default to libc stuff */ +# include +# define MP_MALLOC(size) malloc(size) +# define MP_REALLOC(mem, oldsize, newsize) realloc((mem), (newsize)) +# define MP_CALLOC(nmemb, size) calloc((nmemb), (size)) +# define MP_FREE(mem, size) free(mem) +#else +/* prototypes for our heap functions */ +extern void *MP_MALLOC(size_t size); +extern void *MP_REALLOC(void *mem, size_t oldsize, size_t newsize); +extern void *MP_CALLOC(size_t nmemb, size_t size); +extern void MP_FREE(void *mem, size_t size); +#endif + +/* feature detection macro */ +#ifdef _MSC_VER +/* Prevent false positive: not enough arguments for function-like macro invocation */ +#pragma warning(disable: 4003) +#endif +#define MP_STRINGIZE(x) MP__STRINGIZE(x) +#define MP__STRINGIZE(x) ""#x"" +#define MP_HAS(x) (sizeof(MP_STRINGIZE(BN_##x##_C)) == 1u) + +/* TODO: Remove private_mp_word as soon as deprecated mp_word is removed from tommath. */ +#undef mp_word +typedef private_mp_word mp_word; + +#define MP_MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MP_MAX(x, y) (((x) > (y)) ? (x) : (y)) + +/* Static assertion */ +#define MP_STATIC_ASSERT(msg, cond) typedef char mp_static_assert_##msg[(cond) ? 1 : -1]; + +/* ---> Basic Manipulations <--- */ +#define MP_IS_ZERO(a) ((a)->used == 0) +#define MP_IS_EVEN(a) (((a)->used == 0) || (((a)->dp[0] & 1u) == 0u)) +#define MP_IS_ODD(a) (((a)->used > 0) && (((a)->dp[0] & 1u) == 1u)) + +#define MP_SIZEOF_BITS(type) ((size_t)CHAR_BIT * sizeof(type)) +#define MP_MAXFAST (int)(1uL << (MP_SIZEOF_BITS(mp_word) - (2u * (size_t)MP_DIGIT_BIT))) + +/* TODO: Remove PRIVATE_MP_WARRAY as soon as deprecated MP_WARRAY is removed from tommath.h */ +#undef MP_WARRAY +#define MP_WARRAY PRIVATE_MP_WARRAY + +/* TODO: Remove PRIVATE_MP_PREC as soon as deprecated MP_PREC is removed from tommath.h */ +#ifdef PRIVATE_MP_PREC +# undef MP_PREC +# define MP_PREC PRIVATE_MP_PREC +#endif + +/* Minimum number of available digits in mp_int, MP_PREC >= MP_MIN_PREC */ +#define MP_MIN_PREC ((((int)MP_SIZEOF_BITS(long long) + MP_DIGIT_BIT) - 1) / MP_DIGIT_BIT) + +MP_STATIC_ASSERT(prec_geq_min_prec, MP_PREC >= MP_MIN_PREC) + +/* random number source */ +extern MP_PRIVATE mp_err(*s_mp_rand_source)(void *out, size_t size); + +/* lowlevel functions, do not call! */ +MP_PRIVATE mp_bool s_mp_get_bit(const mp_int *a, unsigned int b); +MP_PRIVATE mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_sqr_fast(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_sqr(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_karatsuba_sqr(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_toom_sqr(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_invmod_fast(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_montgomery_reduce_fast(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR; +MP_PRIVATE mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; +MP_PRIVATE mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; +MP_PRIVATE mp_err s_mp_rand_platform(void *p, size_t n) MP_WUR; +MP_PRIVATE mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat); +MP_PRIVATE void s_mp_reverse(unsigned char *s, size_t len); +MP_PRIVATE mp_err s_mp_prime_is_divisible(const mp_int *a, mp_bool *result); + +/* TODO: jenkins prng is not thread safe as of now */ +MP_PRIVATE mp_err s_mp_rand_jenkins(void *p, size_t n) MP_WUR; +MP_PRIVATE void s_mp_rand_jenkins_init(uint64_t seed); + +extern MP_PRIVATE const char *const mp_s_rmap; +extern MP_PRIVATE const uint8_t mp_s_rmap_reverse[]; +extern MP_PRIVATE const size_t mp_s_rmap_reverse_sz; +extern MP_PRIVATE const mp_digit *s_mp_prime_tab; + +/* deprecated functions */ +MP_DEPRECATED(s_mp_invmod_fast) mp_err fast_mp_invmod(const mp_int *a, const mp_int *b, mp_int *c); +MP_DEPRECATED(s_mp_montgomery_reduce_fast) mp_err fast_mp_montgomery_reduce(mp_int *x, const mp_int *n, + mp_digit rho); +MP_DEPRECATED(s_mp_mul_digs_fast) mp_err fast_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, + int digs); +MP_DEPRECATED(s_mp_mul_high_digs_fast) mp_err fast_s_mp_mul_high_digs(const mp_int *a, const mp_int *b, + mp_int *c, + int digs); +MP_DEPRECATED(s_mp_sqr_fast) mp_err fast_s_mp_sqr(const mp_int *a, mp_int *b); +MP_DEPRECATED(s_mp_balance_mul) mp_err mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c); +MP_DEPRECATED(s_mp_exptmod_fast) mp_err mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, + mp_int *Y, + int redmode); +MP_DEPRECATED(s_mp_invmod_slow) mp_err mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c); +MP_DEPRECATED(s_mp_karatsuba_mul) mp_err mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c); +MP_DEPRECATED(s_mp_karatsuba_sqr) mp_err mp_karatsuba_sqr(const mp_int *a, mp_int *b); +MP_DEPRECATED(s_mp_toom_mul) mp_err mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c); +MP_DEPRECATED(s_mp_toom_sqr) mp_err mp_toom_sqr(const mp_int *a, mp_int *b); +MP_DEPRECATED(s_mp_reverse) void bn_reverse(unsigned char *s, int len); + +#define MP_GET_ENDIANNESS(x) \ + do{\ + int16_t n = 0x1; \ + char *p = (char *)&n; \ + x = (p[0] == '\x01') ? MP_LITTLE_ENDIAN : MP_BIG_ENDIAN; \ + } while (0) + +/* code-generating macros */ +#define MP_SET_UNSIGNED(name, type) \ + void name(mp_int * a, type b) \ + { \ + int i = 0; \ + while (b != 0u) { \ + a->dp[i++] = ((mp_digit)b & MP_MASK); \ + if (MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) { break; } \ + b >>= ((MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) ? 0 : MP_DIGIT_BIT); \ + } \ + a->used = i; \ + a->sign = MP_ZPOS; \ + MP_ZERO_DIGITS(a->dp + a->used, a->alloc - a->used); \ + } + +#define MP_SET_SIGNED(name, uname, type, utype) \ + void name(mp_int * a, type b) \ + { \ + uname(a, (b < 0) ? -(utype)b : (utype)b); \ + if (b < 0) { a->sign = MP_NEG; } \ + } + +#define MP_INIT_INT(name , set, type) \ + mp_err name(mp_int * a, type b) \ + { \ + mp_err err; \ + if ((err = mp_init(a)) != MP_OKAY) { \ + return err; \ + } \ + set(a, b); \ + return MP_OKAY; \ + } + +#define MP_GET_MAG(name, type) \ + type name(const mp_int* a) \ + { \ + unsigned i = MP_MIN((unsigned)a->used, (unsigned)((MP_SIZEOF_BITS(type) + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT)); \ + type res = 0u; \ + while (i --> 0u) { \ + res <<= ((MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) ? 0 : MP_DIGIT_BIT); \ + res |= (type)a->dp[i]; \ + if (MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) { break; } \ + } \ + return res; \ + } + +#define MP_GET_SIGNED(name, mag, type, utype) \ + type name(const mp_int* a) \ + { \ + utype res = mag(a); \ + return (a->sign == MP_NEG) ? (type)-res : (type)res; \ + } + +#endif diff --git a/lib/hcrypto/libtommath/tommath_superclass.h b/lib/hcrypto/libtommath/tommath_superclass.h index a96c36feb..d88bce9c7 100644 --- a/lib/hcrypto/libtommath/tommath_superclass.h +++ b/lib/hcrypto/libtommath/tommath_superclass.h @@ -1,10 +1,16 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + /* super class file for PK algos */ /* default ... include all MPI */ +#ifndef LTM_NOTHING #define LTM_ALL +#endif /* RSA only (does not support DH/DSA/ECC) */ /* #define SC_RSA_1 */ +/* #define SC_RSA_1_WITH_TESTS */ /* For reference.... On an Athlon64 optimizing for speed... @@ -12,65 +18,93 @@ */ +#ifdef SC_RSA_1_WITH_TESTS +# define BN_MP_ERROR_TO_STRING_C +# define BN_MP_FREAD_C +# define BN_MP_FWRITE_C +# define BN_MP_INCR_C +# define BN_MP_ISEVEN_C +# define BN_MP_ISODD_C +# define BN_MP_NEG_C +# define BN_MP_PRIME_FROBENIUS_UNDERWOOD_C +# define BN_MP_RADIX_SIZE_C +# define BN_MP_RAND_C +# define BN_MP_REDUCE_C +# define BN_MP_REDUCE_2K_L_C +# define BN_MP_FROM_SBIN_C +# define BN_MP_ROOT_U32_C +# define BN_MP_SET_L_C +# define BN_MP_SET_UL_C +# define BN_MP_SBIN_SIZE_C +# define BN_MP_TO_RADIX_C +# define BN_MP_TO_SBIN_C +# define BN_S_MP_RAND_JENKINS_C +# define BN_S_MP_RAND_PLATFORM_C +#endif + /* 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 +#if defined(SC_RSA_1) || defined (SC_RSA_1_WITH_TESTS) +# define BN_CUTOFFS_C +# define BN_MP_ADDMOD_C +# define BN_MP_CLEAR_MULTI_C +# define BN_MP_EXPTMOD_C +# define BN_MP_GCD_C +# define BN_MP_INIT_MULTI_C +# define BN_MP_INVMOD_C +# define BN_MP_LCM_C +# define BN_MP_MOD_C +# define BN_MP_MOD_D_C +# define BN_MP_MULMOD_C +# define BN_MP_PRIME_IS_PRIME_C +# define BN_MP_PRIME_RABIN_MILLER_TRIALS_C +# define BN_MP_PRIME_RAND_C +# define BN_MP_RADIX_SMAP_C +# define BN_MP_SET_INT_C +# define BN_MP_SHRINK_C +# define BN_MP_TO_UNSIGNED_BIN_C +# define BN_MP_UNSIGNED_BIN_SIZE_C +# define BN_PRIME_TAB_C +# define BN_S_MP_REVERSE_C - /* other modifiers */ - #define BN_MP_DIV_SMALL /* Slower division, not critical */ +/* 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 +/* 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_DR_IS_MODULUS_C +# undef BN_MP_DR_SETUP_C +# undef BN_MP_DR_REDUCE_C +# undef BN_MP_DIV_3_C +# undef BN_MP_REDUCE_2K_SETUP_C +# undef BN_MP_REDUCE_2K_C +# undef BN_MP_REDUCE_IS_2K_C +# undef BN_MP_REDUCE_SETUP_C +# undef BN_S_MP_BALANCE_MUL_C +# undef BN_S_MP_EXPTMOD_C +# undef BN_S_MP_INVMOD_FAST_C +# undef BN_S_MP_KARATSUBA_MUL_C +# undef BN_S_MP_KARATSUBA_SQR_C +# undef BN_S_MP_MUL_HIGH_DIGS_C +# undef BN_S_MP_MUL_HIGH_DIGS_FAST_C +# undef BN_S_MP_TOOM_MUL_C +# undef BN_S_MP_TOOM_SQR_C + +# ifndef SC_RSA_1_WITH_TESTS +# undef BN_MP_REDUCE_C +# endif + +/* 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_MP_MONTGOMERY_REDUCE_C +# undef BN_S_MP_MUL_DIGS_C +# undef BN_S_MP_SQR_C +# endif #endif - -/* $Source: /cvs/libtom/libtommath/tommath_superclass.h,v $ */ -/* $Revision: 1.3 $ */ -/* $Date: 2005/05/14 13:29:17 $ */