s4:heimdal: import lorikeet-heimdal-201009250123 (commit 42cabfb5b683dbcb97d583c397b8...
authorMatthieu Patou <mat@matws.net>
Sun, 15 Aug 2010 14:31:28 +0000 (18:31 +0400)
committerAndrew Bartlett <abartlet@samba.org>
Sun, 3 Oct 2010 01:15:04 +0000 (01:15 +0000)
I based this on Matthieu's import of lorikeet-heimdal, and then
updated it to this commit.

Andrew Bartlett

382 files changed:
source4/heimdal/HEIMDAL-LICENCE.txt
source4/heimdal/kdc/default_config.c
source4/heimdal/kdc/kerberos5.c
source4/heimdal/kdc/krb5tgs.c
source4/heimdal/kdc/pkinit.c
source4/heimdal/kdc/windc.c
source4/heimdal/lib/asn1/asn1-common.h
source4/heimdal/lib/asn1/asn1_gen.c
source4/heimdal/lib/asn1/asn1parse.c
source4/heimdal/lib/asn1/asn1parse.y
source4/heimdal/lib/asn1/cms.opt
source4/heimdal/lib/asn1/der_cmp.c
source4/heimdal/lib/asn1/der_copy.c
source4/heimdal/lib/asn1/der_free.c
source4/heimdal/lib/asn1/der_get.c
source4/heimdal/lib/asn1/der_length.c
source4/heimdal/lib/asn1/der_put.c
source4/heimdal/lib/asn1/gen.c
source4/heimdal/lib/asn1/gen_copy.c
source4/heimdal/lib/asn1/gen_decode.c
source4/heimdal/lib/asn1/gen_encode.c
source4/heimdal/lib/asn1/gen_free.c
source4/heimdal/lib/asn1/gen_glue.c
source4/heimdal/lib/asn1/gen_length.c
source4/heimdal/lib/asn1/gen_seq.c
source4/heimdal/lib/asn1/gen_template.c
source4/heimdal/lib/asn1/rfc2459.asn1
source4/heimdal/lib/com_err/com_err.c
source4/heimdal/lib/com_err/com_err.h
source4/heimdal/lib/gssapi/gssapi/gssapi.h
source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h
source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h
source4/heimdal/lib/gssapi/gssapi_mech.h
source4/heimdal/lib/gssapi/krb5/8003.c
source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
source4/heimdal/lib/gssapi/krb5/acquire_cred.c
source4/heimdal/lib/gssapi/krb5/add_cred.c
source4/heimdal/lib/gssapi/krb5/aeap.c
source4/heimdal/lib/gssapi/krb5/canonicalize_name.c
source4/heimdal/lib/gssapi/krb5/compare_name.c
source4/heimdal/lib/gssapi/krb5/context_time.c
source4/heimdal/lib/gssapi/krb5/creds.c
source4/heimdal/lib/gssapi/krb5/delete_sec_context.c
source4/heimdal/lib/gssapi/krb5/display_name.c
source4/heimdal/lib/gssapi/krb5/display_status.c
source4/heimdal/lib/gssapi/krb5/duplicate_name.c
source4/heimdal/lib/gssapi/krb5/export_name.c
source4/heimdal/lib/gssapi/krb5/export_sec_context.c
source4/heimdal/lib/gssapi/krb5/external.c
source4/heimdal/lib/gssapi/krb5/get_mic.c
source4/heimdal/lib/gssapi/krb5/import_name.c
source4/heimdal/lib/gssapi/krb5/import_sec_context.c
source4/heimdal/lib/gssapi/krb5/indicate_mechs.c
source4/heimdal/lib/gssapi/krb5/init_sec_context.c
source4/heimdal/lib/gssapi/krb5/inquire_context.c
source4/heimdal/lib/gssapi/krb5/inquire_cred.c
source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c
source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c
source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c
source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c
source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c
source4/heimdal/lib/gssapi/krb5/prf.c
source4/heimdal/lib/gssapi/krb5/process_context_token.c
source4/heimdal/lib/gssapi/krb5/release_cred.c
source4/heimdal/lib/gssapi/krb5/release_name.c
source4/heimdal/lib/gssapi/krb5/set_cred_option.c
source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c
source4/heimdal/lib/gssapi/krb5/store_cred.c
source4/heimdal/lib/gssapi/krb5/unwrap.c
source4/heimdal/lib/gssapi/krb5/verify_mic.c
source4/heimdal/lib/gssapi/krb5/wrap.c
source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c
source4/heimdal/lib/gssapi/mech/gss_add_cred.c
source4/heimdal/lib/gssapi/mech/gss_add_oid_set_member.c
source4/heimdal/lib/gssapi/mech/gss_aeap.c
source4/heimdal/lib/gssapi/mech/gss_buffer_set.c
source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c
source4/heimdal/lib/gssapi/mech/gss_compare_name.c
source4/heimdal/lib/gssapi/mech/gss_context_time.c
source4/heimdal/lib/gssapi/mech/gss_create_empty_oid_set.c
source4/heimdal/lib/gssapi/mech/gss_cred.c
source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c
source4/heimdal/lib/gssapi/mech/gss_delete_sec_context.c
source4/heimdal/lib/gssapi/mech/gss_display_name.c
source4/heimdal/lib/gssapi/mech/gss_display_status.c
source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c
source4/heimdal/lib/gssapi/mech/gss_duplicate_oid.c
source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c
source4/heimdal/lib/gssapi/mech/gss_export_name.c
source4/heimdal/lib/gssapi/mech/gss_export_sec_context.c
source4/heimdal/lib/gssapi/mech/gss_get_mic.c
source4/heimdal/lib/gssapi/mech/gss_import_name.c
source4/heimdal/lib/gssapi/mech/gss_import_sec_context.c
source4/heimdal/lib/gssapi/mech/gss_indicate_mechs.c
source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c
source4/heimdal/lib/gssapi/mech/gss_inquire_context.c
source4/heimdal/lib/gssapi/mech/gss_inquire_cred.c
source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c
source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.c
source4/heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.c
source4/heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.c
source4/heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.c
source4/heimdal/lib/gssapi/mech/gss_krb5.c
source4/heimdal/lib/gssapi/mech/gss_oid_equal.c
source4/heimdal/lib/gssapi/mech/gss_oid_to_str.c
source4/heimdal/lib/gssapi/mech/gss_process_context_token.c
source4/heimdal/lib/gssapi/mech/gss_pseudo_random.c
source4/heimdal/lib/gssapi/mech/gss_release_buffer.c
source4/heimdal/lib/gssapi/mech/gss_release_cred.c
source4/heimdal/lib/gssapi/mech/gss_release_name.c
source4/heimdal/lib/gssapi/mech/gss_release_oid.c
source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c
source4/heimdal/lib/gssapi/mech/gss_seal.c
source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c
source4/heimdal/lib/gssapi/mech/gss_set_sec_context_option.c
source4/heimdal/lib/gssapi/mech/gss_sign.c
source4/heimdal/lib/gssapi/mech/gss_test_oid_set_member.c
source4/heimdal/lib/gssapi/mech/gss_unseal.c
source4/heimdal/lib/gssapi/mech/gss_unwrap.c
source4/heimdal/lib/gssapi/mech/gss_verify.c
source4/heimdal/lib/gssapi/mech/gss_verify_mic.c
source4/heimdal/lib/gssapi/mech/gss_wrap.c
source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c
source4/heimdal/lib/gssapi/spnego/accept_sec_context.c
source4/heimdal/lib/gssapi/spnego/compat.c
source4/heimdal/lib/gssapi/spnego/context_stubs.c
source4/heimdal/lib/gssapi/spnego/cred_stubs.c
source4/heimdal/lib/gssapi/spnego/external.c
source4/heimdal/lib/gssapi/spnego/init_sec_context.c
source4/heimdal/lib/hcrypto/aes.c
source4/heimdal/lib/hcrypto/aes.h
source4/heimdal/lib/hcrypto/camellia.h
source4/heimdal/lib/hcrypto/common.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/common.h [new file with mode: 0644]
source4/heimdal/lib/hcrypto/dh-imath.c
source4/heimdal/lib/hcrypto/dh-ltm.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/dh.c
source4/heimdal/lib/hcrypto/dh.h
source4/heimdal/lib/hcrypto/engine.c
source4/heimdal/lib/hcrypto/engine.h
source4/heimdal/lib/hcrypto/evp-cc.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/evp-cc.h
source4/heimdal/lib/hcrypto/evp-hcrypto.c
source4/heimdal/lib/hcrypto/evp-hcrypto.h
source4/heimdal/lib/hcrypto/evp.c
source4/heimdal/lib/hcrypto/evp.h
source4/heimdal/lib/hcrypto/hash.h
source4/heimdal/lib/hcrypto/imath/imath.c
source4/heimdal/lib/hcrypto/libtommath/LICENSE [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn.ilg [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn.ind [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_error.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_fast_mp_invmod.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_2expt.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_abs.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_add.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_add_d.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_addmod.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_and.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_clamp.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_clear.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_clear_multi.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp_d.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp_mag.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_copy.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_count_bits.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_div.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_2.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_2d.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_3.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_reduce.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_setup.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_exch.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_expt_d.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_exptmod.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_exptmod_fast.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_exteuclid.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_find_prime.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_fread.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_fwrite.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_gcd.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_get_int.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_grow.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_init.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_copy.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_multi.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_set.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_set_int.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_size.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_invmod.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_invmod_slow.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_is_square.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_isprime.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_jacobi.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_karatsuba_sqr.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_lcm.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_lshd.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod_2d.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod_d.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2d.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_d.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_mulmod.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_n_root.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_neg.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_or.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_fermat.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_random_ex.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_radix_size.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_radix_smap.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_rand.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_radix.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_signed_bin.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_setup.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_rshd.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_set.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_set_int.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_shrink.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_signed_bin_size.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqr.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqrmod.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqrt.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_sub.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_sub_d.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_submod.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_signed_bin.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_toom_mul.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_toom_sqr.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_toradix.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_toradix_n.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_xor.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_zero.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_mp_zero_multi.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_prime_tab.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_reverse.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_add.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_exptmod.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_sqr.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_sub.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/bncore.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/booker.pl [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/callgraph.txt [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/libtommath.dsp [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/mtest/logtab.h [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-config.h [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-types.h [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.h [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/mtest/mtest.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/pics/design_process.sxd [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/pics/design_process.tif [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.sxd [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.tif [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/pics/makefile [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/pics/primality.tif [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/pics/radix.sxd [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.sxd [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.tif [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/pretty.build [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/tombc/grammar.txt [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/tommath.h [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/tommath_class.h [new file with mode: 0644]
source4/heimdal/lib/hcrypto/libtommath/tommath_superclass.h [new file with mode: 0644]
source4/heimdal/lib/hcrypto/md4.c
source4/heimdal/lib/hcrypto/md5.c
source4/heimdal/lib/hcrypto/rand-fortuna.c
source4/heimdal/lib/hcrypto/rand-unix.c
source4/heimdal/lib/hcrypto/rand.c
source4/heimdal/lib/hcrypto/rand.h
source4/heimdal/lib/hcrypto/randi.h
source4/heimdal/lib/hcrypto/rijndael-alg-fst.c
source4/heimdal/lib/hcrypto/rsa-imath.c
source4/heimdal/lib/hcrypto/rsa-ltm.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/rsa.c
source4/heimdal/lib/hcrypto/rsa.h
source4/heimdal/lib/hcrypto/sha.c
source4/heimdal/lib/hcrypto/sha256.c
source4/heimdal/lib/hcrypto/ui.c
source4/heimdal/lib/hcrypto/validate.c [new file with mode: 0644]
source4/heimdal/lib/hdb/ext.c
source4/heimdal/lib/hdb/hdb_err.et
source4/heimdal/lib/hdb/keytab.c
source4/heimdal/lib/hdb/mkey.c
source4/heimdal/lib/hdb/ndbm.c
source4/heimdal/lib/hx509/ca.c
source4/heimdal/lib/hx509/cert.c
source4/heimdal/lib/hx509/char_map.h [new file with mode: 0644]
source4/heimdal/lib/hx509/cms.c
source4/heimdal/lib/hx509/crypto.c
source4/heimdal/lib/hx509/hx509.h
source4/heimdal/lib/hx509/ks_p11.c
source4/heimdal/lib/hx509/name.c
source4/heimdal/lib/hx509/req.c
source4/heimdal/lib/hx509/sel.c
source4/heimdal/lib/krb5/acache.c
source4/heimdal/lib/krb5/cache.c
source4/heimdal/lib/krb5/ccache_plugin.h [new file with mode: 0644]
source4/heimdal/lib/krb5/config_file.c
source4/heimdal/lib/krb5/context.c
source4/heimdal/lib/krb5/crypto.c
source4/heimdal/lib/krb5/data.c
source4/heimdal/lib/krb5/error_string.c
source4/heimdal/lib/krb5/expand_path.c [new file with mode: 0644]
source4/heimdal/lib/krb5/fcache.c
source4/heimdal/lib/krb5/generate_seq_number.c
source4/heimdal/lib/krb5/get_cred.c
source4/heimdal/lib/krb5/get_default_principal.c
source4/heimdal/lib/krb5/init_creds_pw.c
source4/heimdal/lib/krb5/kcm.c
source4/heimdal/lib/krb5/keytab.c
source4/heimdal/lib/krb5/keytab_any.c
source4/heimdal/lib/krb5/keytab_file.c
source4/heimdal/lib/krb5/keytab_keyfile.c
source4/heimdal/lib/krb5/keytab_memory.c
source4/heimdal/lib/krb5/krb5.h
source4/heimdal/lib/krb5/krb5_locl.h
source4/heimdal/lib/krb5/krbhst.c
source4/heimdal/lib/krb5/log.c
source4/heimdal/lib/krb5/mcache.c
source4/heimdal/lib/krb5/mit_glue.c
source4/heimdal/lib/krb5/pcache.c [new file with mode: 0644]
source4/heimdal/lib/krb5/pkinit.c
source4/heimdal/lib/krb5/plugin.c
source4/heimdal/lib/krb5/prompter_posix.c
source4/heimdal/lib/krb5/rd_req.c
source4/heimdal/lib/krb5/replay.c
source4/heimdal/lib/krb5/send_to_kdc.c
source4/heimdal/lib/krb5/ticket.c
source4/heimdal/lib/krb5/v4_glue.c
source4/heimdal/lib/krb5/warn.c
source4/heimdal/lib/ntlm/ntlm.c
source4/heimdal/lib/roken/base64.c
source4/heimdal/lib/roken/getarg.c
source4/heimdal/lib/roken/getarg.h
source4/heimdal/lib/roken/inet_ntop.c
source4/heimdal/lib/roken/inet_pton.c
source4/heimdal/lib/roken/net_read.c
source4/heimdal/lib/roken/net_write.c
source4/heimdal/lib/roken/resolve.c
source4/heimdal/lib/roken/resolve.h
source4/heimdal/lib/roken/roken.h.in
source4/heimdal/lib/roken/roken_gethostby.c
source4/heimdal/lib/roken/socket.c
source4/heimdal/lib/roken/strerror_r.c
source4/heimdal/lib/wind/errorlist.c
source4/heimdal/lib/wind/normalize.c
source4/heimdal/lib/wind/stringprep.py
source4/heimdal/lib/wind/wind.h

index 90ff52309f0de704670d5ede68bbdfbb11fce3c1..8ff94195121e29ada47c734c8de7ad57963ab4cb 100644 (file)
@@ -12,34 +12,33 @@ cooperation in the use of the heimdal code in Samba.
 
 /*
  * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan and others.
- * (Royal Institute of Technology, Stockholm, Sweden). 
- * All rights reserved. 
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
  *
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions 
- * are met: 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
  *
- * 1. Redistributions of source code must retain the above copyright 
- *    notice, this list of conditions and the following disclaimer. 
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
  *
- * 2. Redistributions in binary form must reproduce the above copyright 
- *    notice, this list of conditions and the following disclaimer in the 
- *    documentation and/or other materials provided with the distribution. 
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
  *
- * 3. Neither the name of the Institute nor the names of its contributors 
- *    may be used to endorse or promote products derived from this software 
- *    without specific prior written permission. 
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE. 
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
-
index f5df4e0298c0c882a84ac8d64f29cd8803164132..118bdf97aa62723b56d626e69ca76e8a58d7c666 100644 (file)
@@ -264,7 +264,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
 
     if (c->pkinit_kdc_identity == NULL) {
        if (c->pkinit_kdc_friendly_name == NULL)
-           c->pkinit_kdc_friendly_name = 
+           c->pkinit_kdc_friendly_name =
                strdup("O=System Identity,CN=com.apple.kerberos.kdc");
        c->pkinit_kdc_identity = strdup("KEYCHAIN:");
     }
@@ -276,7 +276,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
     if (c->enable_pkinit) {
        if (c->pkinit_kdc_identity == NULL)
            krb5_errx(context, 1, "pkinit enabled but no identity");
+
        if (c->pkinit_kdc_anchors == NULL)
            krb5_errx(context, 1, "pkinit enabled but no X509 anchors");
 
@@ -287,7 +287,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
                               c->pkinit_kdc_revoke);
 
     }
-    
+
     *config = c;
 
     return 0;
index 05df86e143248b3a3c2aba59c5b95fe9811401d2..9fb0998a2aae523346066373197e090d2681d20f 100644 (file)
@@ -910,7 +910,7 @@ _kdc_as_rep(krb5_context context,
     const char *e_text = NULL;
     krb5_crypto crypto;
     Key *ckey, *skey;
-    EncryptionKey *reply_key, session_key;
+    EncryptionKey *reply_key = NULL, session_key;
     int flags = 0;
 #ifdef PKINIT
     pk_client_params *pkp = NULL;
index 06a535d4d4483fa6a53f801def1a9be5e55425d8..23f9674bef21a69cf3810e4a6f25cb6eb5a37f7e 100644 (file)
@@ -314,6 +314,7 @@ check_PAC(krb5_context context,
        for (j = 0; j < child.len; j++) {
 
            if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) {
+               int signed_pac = 0;
                krb5_pac pac;
 
                /* Found PAC */
@@ -334,19 +335,26 @@ check_PAC(krb5_context context,
                }
 
                ret = _kdc_pac_verify(context, client_principal,
-                                     client, server, krbtgt, &pac);
+                                     client, server, krbtgt, &pac, &signed_pac);
                if (ret) {
                    krb5_pac_free(context, pac);
                    return ret;
                }
-               *signedpath = 1;
-
-               ret = _krb5_pac_sign(context, pac, tkt->authtime,
-                                    client_principal,
-                                    server_key, krbtgt_sign_key, rspac);
 
+               /*
+                * Only re-sign PAC if we could verify it with the PAC
+                * function. The no-verify case happens when we get in
+                * a PAC from cross realm from a Windows domain and
+                * that there is no PAC verification function.
+                */
+               if (signed_pac) {
+                   *signedpath = 1;
+                   ret = _krb5_pac_sign(context, pac, tkt->authtime,
+                                        client_principal,
+                                        server_key, krbtgt_key, rspac);
+               }
                krb5_pac_free(context, pac);
-
+               
                return ret;
            }
        }
@@ -449,7 +457,7 @@ check_tgs_flags(krb5_context context,
     }
 
     if(f.renewable){
-       if(!tgt->flags.renewable){
+       if(!tgt->flags.renewable || tgt->renew_till == NULL){
            kdc_log(context, config, 0,
                    "Bad request for renewable ticket");
            return KRB5KDC_ERR_BADOPTION;
@@ -802,7 +810,9 @@ tgs_make_reply(krb5_context context,
        et.endtime = *et.starttime + life;
     }
     if(f.renewable_ok && tgt->flags.renewable &&
-       et.renew_till == NULL && et.endtime < *b->till){
+       et.renew_till == NULL && et.endtime < *b->till &&
+       tgt->renew_till != NULL)
+    {
        et.flags.renewable = 1;
        ALLOC(et.renew_till);
        *et.renew_till = *b->till;
index 4405bf4f19410ef68baafdc28974e19b42a1666c..9c0be23b14c3d78d44b137af97a9a5fc7db4a7cd 100644 (file)
@@ -227,10 +227,7 @@ generate_dh_keyblock(krb5_context context,
            goto out;
        }
 
-       dh_gen_keylen = DH_size(client_params->u.dh.key);
-       size = BN_num_bytes(client_params->u.dh.key->p);
-       if (size < dh_gen_keylen)
-           size = dh_gen_keylen;
+       size = DH_size(client_params->u.dh.key);
 
        dh_gen_key = malloc(size);
        if (dh_gen_key == NULL) {
@@ -238,17 +235,20 @@ generate_dh_keyblock(krb5_context context,
            krb5_set_error_message(context, ret, "malloc: out of memory");
            goto out;
        }
-       memset(dh_gen_key, 0, size - dh_gen_keylen);
 
-       dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),
-                                      client_params->u.dh.public_key,
-                                      client_params->u.dh.key);
+       dh_gen_keylen = DH_compute_key(dh_gen_key,client_params->u.dh.public_key, client_params->u.dh.key);
        if (dh_gen_keylen == -1) {
            ret = KRB5KRB_ERR_GENERIC;
            krb5_set_error_message(context, ret,
                                   "Can't compute Diffie-Hellman key");
            goto out;
        }
+       if (dh_gen_keylen < size) {
+           size -= dh_gen_keylen;
+           memmove(dh_gen_key + size, dh_gen_key, dh_gen_keylen);
+           memset(dh_gen_key, 0, size);
+       }
+
        ret = 0;
 #ifdef HAVE_OPENSSL
     } else if (client_params->keyex == USE_ECDH) {
index a8f1eb15d1f45595056b8146c1dde92090234024..6efbeee9dd05daf0f650b70c3cbfb9eaaf7c1870 100644 (file)
@@ -87,14 +87,19 @@ _kdc_pac_verify(krb5_context context,
                hdb_entry_ex *client,
                hdb_entry_ex *server,
                hdb_entry_ex *krbtgt,
-               krb5_pac *pac)
+               krb5_pac *pac,
+               int *verified)
 {
-    if (windcft == NULL) {
-       krb5_set_error_message(context, EINVAL, "Can't verify PAC, no function");
-       return EINVAL;
-    }
-    return (windcft->pac_verify)(windcctx, context,
-                                client_principal, client, server, krbtgt, pac);
+    krb5_error_code ret;
+
+    if (windcft == NULL)
+       return 0;
+
+    ret = windcft->pac_verify(windcctx, context,
+                             client_principal, client, server, krbtgt, pac);
+    if (ret == 0)
+       *verified = 1;
+    return ret;
 }
 
 krb5_error_code
index 8ab97761dbf8e193b44f8018bd24a12ea9a1b2de..9c8793e0ccfcde9af6d75c01072165a2e51ce69e 100644 (file)
@@ -20,8 +20,8 @@ typedef struct heim_octet_string {
 
 typedef char *heim_general_string;
 typedef char *heim_utf8_string;
-typedef char *heim_printable_string;
-typedef char *heim_ia5_string;
+typedef struct heim_octet_string heim_printable_string;
+typedef struct heim_octet_string heim_ia5_string;
 
 typedef struct heim_bmp_string {
     size_t length;
@@ -64,4 +64,16 @@ typedef struct heim_octet_string heim_any_set;
     }                                                          \
   } while (0)
 
+#ifdef _WIN32
+#ifndef ASN1_LIB
+#define ASN1EXP  __declspec(dllimport)
+#else
+#define ASN1EXP
+#endif
+#define ASN1CALL __stdcall
+#else
+#define ASN1EXP
+#define ASN1CALL
+#endif
+         
 #endif
index 925cc72cb497c33f52d8b923447ef002a68261dc..01dc6805162205b01fae2582b82b863e43a102a5 100644 (file)
@@ -46,7 +46,7 @@ static int
 doit(const char *fn)
 {
     char buf[2048];
-    char *fnout;
+    char *fnout = NULL;
     const char *bname;
     unsigned long line = 0;
     FILE *f, *fout;
@@ -62,8 +62,7 @@ doit(const char *fn)
     else
        bname = fn;
 
-    asprintf(&fnout, "%s.out", bname);
-    if (fnout == NULL)
+    if (asprintf(&fnout, "%s.out", bname) < 0 || fnout == NULL)
        errx(1, "malloc");
 
     fout = fopen(fnout, "w");
index 545e0f69225c5f993dcdba8baa5c2fda1a4b344d..7fa937a49d938848bb8fa67d15f020c2fce091e8 100644 (file)
@@ -3015,7 +3015,8 @@ static void fix_labels1(struct memhead *members, const char *prefix)
     if(members == NULL)
        return;
     ASN1_TAILQ_FOREACH(m, members, members) {
-       asprintf(&m->label, "%s_%s", prefix, m->gen_name);
+       if (asprintf(&m->label, "%s_%s", prefix, m->gen_name) < 0)
+           errx(1, "malloc");
        if (m->label == NULL)
            errx(1, "malloc");
        if(m->type != NULL)
@@ -3032,9 +3033,8 @@ static void fix_labels2(Type *t, const char *prefix)
 static void
 fix_labels(Symbol *s)
 {
-    char *p;
-    asprintf(&p, "choice_%s", s->gen_name);
-    if (p == NULL)
+    char *p = NULL;
+    if (asprintf(&p, "choice_%s", s->gen_name) < 0 || p == NULL)
        errx(1, "malloc");
     fix_labels2(s->type, p);
     free(p);
index 13b86b17c1e68cb007ae68904bc68a564c443ed4..611c5b521ad906a6260edbeb59264f38b3af9319 100644 (file)
@@ -1007,7 +1007,8 @@ static void fix_labels1(struct memhead *members, const char *prefix)
     if(members == NULL)
        return;
     ASN1_TAILQ_FOREACH(m, members, members) {
-       asprintf(&m->label, "%s_%s", prefix, m->gen_name);
+       if (asprintf(&m->label, "%s_%s", prefix, m->gen_name) < 0)
+           errx(1, "malloc");
        if (m->label == NULL)
            errx(1, "malloc");
        if(m->type != NULL)
@@ -1024,9 +1025,8 @@ static void fix_labels2(Type *t, const char *prefix)
 static void
 fix_labels(Symbol *s)
 {
-    char *p;
-    asprintf(&p, "choice_%s", s->gen_name);
-    if (p == NULL)
+    char *p = NULL;
+    if (asprintf(&p, "choice_%s", s->gen_name) < 0 || p == NULL)
        errx(1, "malloc");
     fix_labels2(s->type, p);
     free(p);
index bf7d3965298783aa883ad22793f3cc6fc0735912..49333e53a758aa34cfb3394d1bdc47d50c223a81 100644 (file)
@@ -1 +1,2 @@
 --decode-dce-ber
+--sequence=DigestAlgorithmIdentifiers
index 7329c5867f6a80888370024e1f52f46265b8d0d2..84aee4cce06221b629db1a6eea0d38f11f97dbd0 100644 (file)
@@ -52,6 +52,20 @@ der_heim_octet_string_cmp(const heim_octet_string *p,
     return memcmp(p->data, q->data, p->length);
 }
 
+int
+der_printable_string_cmp(const heim_printable_string *p, 
+                        const heim_printable_string *q)
+{
+    return der_heim_octet_string_cmp(p, q);
+}
+
+int
+der_ia5_string_cmp(const heim_ia5_string *p, 
+                  const heim_ia5_string *q)
+{
+    return der_heim_octet_string_cmp(p, q);
+}
+
 int
 der_heim_bit_string_cmp(const heim_bit_string *p,
                        const heim_bit_string *q)
index a80c851f96827572472503ee0d92423f8a5a826f..3a0a8c5ffa6ab309d073f9e0948ac5ec3f8c53d7 100644 (file)
@@ -85,14 +85,20 @@ int
 der_copy_printable_string (const heim_printable_string *from,
                       heim_printable_string *to)
 {
-    return der_copy_general_string(from, to);
+    to->length = from->length;
+    to->data   = malloc(to->length + 1);
+    if(to->data == NULL)
+       return ENOMEM;
+    memcpy(to->data, from->data, to->length);
+    ((char *)to->data)[to->length] = '\0';
+    return 0;
 }
 
 int
-der_copy_ia5_string (const heim_printable_string *from,
-                    heim_printable_string *to)
+der_copy_ia5_string (const heim_ia5_string *from,
+                    heim_ia5_string *to)
 {
-    return der_copy_general_string(from, to);
+    return der_copy_printable_string(from, to);
 }
 
 int
index a16ddaed1c0f92c4d7cbbe68d512c96c42b63d48..4bae5fc2338f3ea975602265ce32eab4998e358d 100644 (file)
@@ -79,15 +79,13 @@ der_free_utf8string (heim_utf8_string *str)
 void
 der_free_printable_string (heim_printable_string *str)
 {
-    free(*str);
-    *str = NULL;
+    der_free_octet_string(str);
 }
 
 void
 der_free_ia5_string (heim_ia5_string *str)
 {
-    free(*str);
-    *str = NULL;
+    der_free_octet_string(str);
 }
 
 void
index aee565040fd61168d76b9b17249f7244502c5aee..3ea0d5ea1816f407a320c8e3c084b39e4910c3d3 100644 (file)
@@ -167,17 +167,24 @@ der_get_utf8string (const unsigned char *p, size_t len,
 }
 
 int
-der_get_printable_string (const unsigned char *p, size_t len,
-                         heim_printable_string *str, size_t *size)
+der_get_printable_string(const unsigned char *p, size_t len,
+                        heim_printable_string *str, size_t *size)
 {
-    return der_get_general_string(p, len, str, size);
+    str->length = len;
+    str->data = malloc(len + 1);
+    if (str->data == NULL)
+       return ENOMEM;
+    memcpy(str->data, p, len);
+    ((char *)str->data)[len] = '\0';
+    if(size) *size = len;
+    return 0;
 }
 
 int
-der_get_ia5_string (const unsigned char *p, size_t len,
-                   heim_ia5_string *str, size_t *size)
+der_get_ia5_string(const unsigned char *p, size_t len,
+                  heim_ia5_string *str, size_t *size)
 {
-    return der_get_general_string(p, len, str, size);
+    return der_get_printable_string(p, len, str, size);
 }
 
 int
index 688e6ba8171ef76b8951d5b9d2d0a92ba4963412..7a41de9d225cac8e64c2bc994d5c46fb8dfbf9fa 100644 (file)
@@ -161,13 +161,13 @@ der_length_utf8string (const heim_utf8_string *data)
 size_t
 der_length_printable_string (const heim_printable_string *data)
 {
-    return strlen(*data);
+    return data->length;
 }
 
 size_t
 der_length_ia5_string (const heim_ia5_string *data)
 {
-    return strlen(*data);
+    return data->length;
 }
 
 size_t
index 10fc0023341b895dea4dd444bd0fe56c79908c15..c8192f25fe5ca1e5b87f183bf87ef0f2f3ee9f72 100644 (file)
@@ -181,14 +181,14 @@ int
 der_put_printable_string (unsigned char *p, size_t len,
                          const heim_printable_string *str, size_t *size)
 {
-    return der_put_general_string(p, len, str, size);
+    return der_put_octet_string(p, len, str, size);
 }
 
 int
 der_put_ia5_string (unsigned char *p, size_t len,
                    const heim_ia5_string *str, size_t *size)
 {
-    return der_put_general_string(p, len, str, size);
+    return der_put_octet_string(p, len, str, size);
 }
 
 int
index 8c13434203b928967f30062b7d5d59fb909a884f..d59f3bfa4755de9f790c231c7518dd2660e02fd8 100644 (file)
@@ -116,7 +116,7 @@ get_filename (void)
 void
 init_generate (const char *filename, const char *base)
 {
-    char *fn;
+    char *fn = NULL;
 
     orig_filename = filename;
     if (base != NULL) {
@@ -126,34 +126,30 @@ init_generate (const char *filename, const char *base)
     }
 
     /* public header file */
-    asprintf(&header, "%s.h", headerbase);
-    if (header == NULL)
+    if (asprintf(&header, "%s.h", headerbase) < 0 || header == NULL)
        errx(1, "malloc");
-    asprintf(&fn, "%s.hx", headerbase);
-    if (fn == NULL)
+    if (asprintf(&fn, "%s.hx", headerbase) < 0 || fn == NULL)
        errx(1, "malloc");
     headerfile = fopen (fn, "w");
     if (headerfile == NULL)
        err (1, "open %s", fn);
     free(fn);
+    fn = NULL;
 
     /* private header file */
-    asprintf(&privheader, "%s-priv.h", headerbase);
-    if (privheader == NULL)
+    if (asprintf(&privheader, "%s-priv.h", headerbase) < 0 || privheader == NULL)
        errx(1, "malloc");
-    asprintf(&fn, "%s-priv.hx", headerbase);
-    if (fn == NULL)
+    if (asprintf(&fn, "%s-priv.hx", headerbase) < 0 || fn == NULL)
        errx(1, "malloc");
     privheaderfile = fopen (fn, "w");
     if (privheaderfile == NULL)
        err (1, "open %s", fn);
     free(fn);
+    fn = NULL;
 
     /* template file */
-    asprintf(&template, "%s-template.c", headerbase);
-    if (template == NULL)
+    if (asprintf(&template, "%s-template.c", headerbase) < 0 || template == NULL)
        errx(1, "malloc");
-
     fprintf (headerfile,
             "/* Generated from %s */\n"
             "/* Do not edit */\n\n",
@@ -185,10 +181,10 @@ init_generate (const char *filename, const char *base)
             "typedef char *heim_utf8_string;\n\n"
             );
     fprintf (headerfile,
-            "typedef char *heim_printable_string;\n\n"
+            "typedef struct heim_octet_string heim_printable_string;\n\n"
             );
     fprintf (headerfile,
-            "typedef char *heim_ia5_string;\n\n"
+            "typedef struct heim_octet_string heim_ia5_string;\n\n"
             );
     fprintf (headerfile,
             "typedef struct heim_bmp_string {\n"
@@ -232,10 +228,21 @@ init_generate (const char *filename, const char *base)
          "    }                                                          \\\n"
          "  } while (0)\n\n",
          headerfile);
+    fputs("#ifdef _WIN32\n"
+         "#ifndef ASN1_LIB\n"
+         "#define ASN1EXP  __declspec(dllimport)\n"
+         "#else\n"
+         "#define ASN1EXP\n"
+         "#endif\n"
+         "#define ASN1CALL __stdcall\n"
+         "#else\n"
+         "#define ASN1EXP\n"
+         "#define ASN1CALL\n"
+         "#endif\n",
+         headerfile);
     fprintf (headerfile, "struct units;\n\n");
     fprintf (headerfile, "#endif\n\n");
-    asprintf(&fn, "%s_files", base);
-    if (fn == NULL)
+    if (asprintf(&fn, "%s_files", base) < 0 || fn == NULL)
        errx(1, "malloc");
     logfile = fopen(fn, "w");
     if (logfile == NULL)
@@ -333,22 +340,23 @@ gen_compare_defval(const char *var, struct value *val)
 void
 generate_header_of_codefile(const char *name)
 {
-    char *filename;
+    char *filename = NULL;
 
     if (codefile != NULL)
        abort();
 
-    asprintf (&filename, "%s_%s.x", STEM, name);
-    if (filename == NULL)
+    if (asprintf (&filename, "%s_%s.x", STEM, name) < 0 || filename == NULL)
        errx(1, "malloc");
     codefile = fopen (filename, "w");
     if (codefile == NULL)
        err (1, "fopen %s", filename);
     fprintf(logfile, "%s ", filename);
     free(filename);
+    filename = NULL;
     fprintf (codefile,
             "/* Generated from %s */\n"
             "/* Do not edit */\n\n"
+            "#define  ASN1_LIB\n\n"
             "#include <stdio.h>\n"
             "#include <stdlib.h>\n"
             "#include <time.h>\n"
@@ -399,6 +407,7 @@ generate_constant (const Symbol *s)
     case objectidentifiervalue: {
        struct objid *o, **list;
        unsigned int i, len;
+       char *gen_upper;
 
        if (!one_code_file)
            generate_header_of_codefile(s->gen_name);
@@ -424,12 +433,6 @@ generate_constant (const Symbol *s)
                    o->label ? o->label : "label-less", o->value);
        }
 
-       fprintf (headerfile, "} */\n");
-       fprintf (headerfile,
-                "extern const heim_oid asn1_oid_%s;\n\n",
-                s->gen_name);
-
-
        fprintf (codefile, "static unsigned oid_%s_variable_num[%d] =  {",
                 s->gen_name, len);
        for (i = len ; i > 0; i--) {
@@ -443,6 +446,23 @@ generate_constant (const Symbol *s)
 
        free(list);
 
+       /* header file */
+
+       gen_upper = strdup(s->gen_name);
+       len = strlen(gen_upper);
+       for (i = 0; i < len; i++)
+           gen_upper[i] = toupper((int)s->gen_name[i]);
+
+       fprintf (headerfile, "} */\n");
+       fprintf (headerfile,
+                "extern ASN1EXP const heim_oid asn1_oid_%s;\n"
+                "#define ASN1_OID_%s (&asn1_oid_%s)\n\n",
+                s->gen_name,
+                gen_upper,
+                s->gen_name);
+
+       free(gen_upper);
+
        if (!one_code_file)
            close_codefile();
 
@@ -673,7 +693,8 @@ getnewbasename(char **newbasename, int typedefp, const char *basename, const cha
     else {
        if (name[0] == '*')
            name++;
-       asprintf(newbasename, "%s_%s", basename, name);
+       if (asprintf(newbasename, "%s_%s", basename, name) < 0)
+           errx(1, "malloc");
     }
     if (*newbasename == NULL)
        err(1, "malloc");
@@ -739,27 +760,30 @@ define_type (int level, const char *name, const char *basename, Type *t, int typ
 
            fprintf (headerfile, "struct %s {\n", newbasename);
            ASN1_TAILQ_FOREACH(m, t->members, members) {
-               char *n;
+               char *n = NULL;
        
                /* pad unused */
                while (pos < m->val) {
-                   asprintf (&n, "_unused%d:1", pos);
+                   if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL)
+                       errx(1, "malloc");
                    define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
                    free(n);
                    pos++;
                }
 
-               asprintf (&n, "%s:1", m->gen_name);
-               if (n == NULL)
+               n = NULL;
+               if (asprintf (&n, "%s:1", m->gen_name) < 0 || n == NULL)
                    errx(1, "malloc");
                define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
                free (n);
+               n = NULL;
                pos++;
            }
            /* pad to 32 elements */
            while (pos < 32) {
-               char *n;
-               asprintf (&n, "_unused%d:1", pos);
+               char *n = NULL;
+               if (asprintf (&n, "_unused%d:1", pos) < 0 || n == NULL)
+                   errx(1, "malloc");
                define_type (level + 1, n, newbasename, &i, FALSE, FALSE);
                free(n);
                pos++;
@@ -803,10 +827,9 @@ define_type (int level, const char *name, const char *basename, Type *t, int typ
            if (m->ellipsis) {
                ;
            } else if (m->optional) {
-               char *n;
+               char *n = NULL;
 
-               asprintf (&n, "*%s", m->gen_name);
-               if (n == NULL)
+               if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
                    errx(1, "malloc");
                define_type (level + 1, n, newbasename, m->type, FALSE, FALSE);
                free (n);
@@ -891,10 +914,9 @@ define_type (int level, const char *name, const char *basename, Type *t, int typ
                space(level + 2);
                fprintf(headerfile, "heim_octet_string asn1_ellipsis;\n");
            } else if (m->optional) {
-               char *n;
+               char *n = NULL;
 
-               asprintf (&n, "*%s", m->gen_name);
-               if (n == NULL)
+               if (asprintf (&n, "*%s", m->gen_name) < 0 || n == NULL)
                    errx(1, "malloc");
                define_type (level + 2, n, newbasename, m->type, FALSE, FALSE);
                free (n);
@@ -970,6 +992,7 @@ void
 generate_type (const Symbol *s)
 {
     FILE *h;
+    const char * exp;
 
     if (!one_code_file)
        generate_header_of_codefile(s->gen_name);
@@ -991,30 +1014,37 @@ generate_type (const Symbol *s)
 
     /* generate prototypes */
 
-    if (is_export(s->name))
+    if (is_export(s->name)) {
        h = headerfile;
-    else
+       exp = "ASN1EXP ";
+    } else {
        h = privheaderfile;
+       exp = "";
+    }
    
     fprintf (h,
-            "int    "
+            "%sint    ASN1CALL "
             "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
+            exp,
             s->gen_name, s->gen_name);
     fprintf (h,
-            "int    "
+            "%sint    ASN1CALL "
             "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
+            exp,
             s->gen_name, s->gen_name);
     fprintf (h,
-            "size_t length_%s(const %s *);\n",
+            "%ssize_t ASN1CALL length_%s(const %s *);\n",
+            exp,
             s->gen_name, s->gen_name);
     fprintf (h,
-            "int    copy_%s  (const %s *, %s *);\n",
+            "%sint    ASN1CALL copy_%s  (const %s *, %s *);\n",
+            exp,
             s->gen_name, s->gen_name, s->gen_name);
     fprintf (h,
-            "void   free_%s  (%s *);\n",
+            "%svoid   ASN1CALL free_%s  (%s *);\n",
+            exp,
             s->gen_name, s->gen_name);
    
-
     fprintf(h, "\n\n");
 
     if (!one_code_file) {
index 5e228d0e6474324c02d45c3064eef4283d2045ed..36f68ee5d99cb1c4c2e314d730ca81d8841a8faf 100644 (file)
@@ -110,14 +110,16 @@ copy_type (const char *from, const char *to, const Type *t, int preserve)
            if(t->type == TChoice)
                fprintf(codefile, "case %s:\n", m->label);
 
-           asprintf (&fs, "%s(%s)->%s%s",
-                     m->optional ? "" : "&", from,
-                     t->type == TChoice ? "u." : "", m->gen_name);
+           if (asprintf (&fs, "%s(%s)->%s%s",
+                         m->optional ? "" : "&", from,
+                         t->type == TChoice ? "u." : "", m->gen_name) < 0)
+               errx(1, "malloc");
            if (fs == NULL)
                errx(1, "malloc");
-           asprintf (&ts, "%s(%s)->%s%s",
-                     m->optional ? "" : "&", to,
-                     t->type == TChoice ? "u." : "", m->gen_name);
+           if (asprintf (&ts, "%s(%s)->%s%s",
+                         m->optional ? "" : "&", to,
+                         t->type == TChoice ? "u." : "", m->gen_name) < 0)
+               errx(1, "malloc");
            if (ts == NULL)
                errx(1, "malloc");
            if(m->optional){
@@ -155,8 +157,7 @@ copy_type (const char *from, const char *to, const Type *t, int preserve)
     }
     case TSetOf:
     case TSequenceOf: {
-       char *f;
-       char *T;
+       char *f = NULL, *T = NULL;
 
        fprintf (codefile, "if(((%s)->val = "
                 "malloc((%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n",
@@ -166,10 +167,12 @@ copy_type (const char *from, const char *to, const Type *t, int preserve)
        fprintf(codefile,
                "for((%s)->len = 0; (%s)->len < (%s)->len; (%s)->len++){\n",
                to, to, from, to);
-       asprintf(&f, "&(%s)->val[(%s)->len]", from, to);
+       if (asprintf(&f, "&(%s)->val[(%s)->len]", from, to) < 0)
+           errx(1, "malloc");
        if (f == NULL)
            errx(1, "malloc");
-       asprintf(&T, "&(%s)->val[(%s)->len]", to, to);
+       if (asprintf(&T, "&(%s)->val[(%s)->len]", to, to) < 0)
+           errx(1, "malloc");
        if (T == NULL)
            errx(1, "malloc");
        copy_type(f, T, t->subtype, FALSE);
@@ -228,7 +231,7 @@ generate_type_copy (const Symbol *s)
 
   used_fail = 0;
 
-  fprintf (codefile, "int\n"
+  fprintf (codefile, "int ASN1CALL\n"
           "copy_%s(const %s *from, %s *to)\n"
           "{\n"
           "memset(to, 0, sizeof(*to));\n",
index 043cfac2dbaf89dbcd30cc289698de52ff196124..ad76c07251d4955ac17e8e23cff35e3a7e104a3a 100644 (file)
@@ -320,14 +320,13 @@ decode_type (const char *name, const Type *t, int optional,
            break;
 
        ASN1_TAILQ_FOREACH(m, t->members, members) {
-           char *s;
+           char *s = NULL;
 
            if (m->ellipsis)
                continue;
 
-           asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&",
-                     name, m->gen_name);
-           if (s == NULL)
+           if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&",
+                         name, m->gen_name) < 0 || s == NULL)
                errx(1, "malloc");
            decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL);
            free (s);
@@ -363,8 +362,7 @@ decode_type (const char *name, const Type *t, int optional,
                    is_primitive_type(m->type->subtype->type) ? "PRIM" : "CONS",
                    valuename(m->type->tag.tagclass, m->type->tag.tagvalue));
 
-           asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name);
-           if (s == NULL)
+           if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL)
                errx(1, "malloc");
            if(m->optional)
                fprintf(codefile,
@@ -388,8 +386,7 @@ decode_type (const char *name, const Type *t, int optional,
        ASN1_TAILQ_FOREACH(m, t->members, members) {
            char *s;
 
-           asprintf (&s, "%s->%s", name, m->gen_name);
-           if (s == NULL)
+           if (asprintf (&s, "%s->%s", name, m->gen_name) < 0 || s == NULL)
                errx(1, "malloc");
            fprintf(codefile, "if((members & (1 << %d)) == 0)\n", memno);
            if(m->optional)
@@ -406,8 +403,8 @@ decode_type (const char *name, const Type *t, int optional,
     }
     case TSetOf:
     case TSequenceOf: {
-       char *n;
-       char *sname;
+       char *n = NULL;
+       char *sname = NULL;
 
        fprintf (codefile,
                 "{\n"
@@ -441,11 +438,9 @@ decode_type (const char *name, const Type *t, int optional,
                 tmpstr, forwstr,
                 name, tmpstr);
 
-       asprintf (&n, "&(%s)->val[(%s)->len]", name, name);
-       if (n == NULL)
+       if (asprintf (&n, "&(%s)->val[(%s)->len]", name, name) < 0 || n == NULL)
            errx(1, "malloc");
-       asprintf (&sname, "%s_s_of", tmpstr);
-       if (sname == NULL)
+       if (asprintf (&sname, "%s_s_of", tmpstr) < 0 || sname == NULL)
            errx(1, "malloc");
        decode_type (n, t->subtype, 0, forwstr, sname, NULL);
        fprintf (codefile,
@@ -472,10 +467,11 @@ decode_type (const char *name, const Type *t, int optional,
        decode_primitive ("general_string", name, forwstr);
        break;
     case TTag:{
-       char *tname, *typestring;
+       char *tname = NULL, *typestring = NULL;
        char *ide = NULL;
 
-       asprintf(&typestring, "%s_type", tmpstr);
+       if (asprintf(&typestring, "%s_type", tmpstr) < 0 || typestring == NULL)
+           errx(1, "malloc");
 
        fprintf(codefile,
                "{\n"
@@ -528,8 +524,7 @@ decode_type (const char *name, const Type *t, int optional,
            fprintf(codefile,
                    "if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n"
                    "len = %s_datalen;\n", tmpstr, forwstr, tmpstr);
-       asprintf (&tname, "%s_Tag", tmpstr);
-       if (tname == NULL)
+       if (asprintf (&tname, "%s_Tag", tmpstr) < 0 || tname == NULL)
            errx(1, "malloc");
        decode_type (name, t->subtype, 0, forwstr, tname, ide);
        if(support_ber)
@@ -568,7 +563,7 @@ decode_type (const char *name, const Type *t, int optional,
 
        ASN1_TAILQ_FOREACH(m, t->members, members) {
            const Type *tt = m->type;
-           char *s;
+           char *s = NULL;
            Der_class cl;
            Der_type  ty;
            unsigned  tag;
@@ -586,9 +581,8 @@ decode_type (const char *name, const Type *t, int optional,
                    classname(cl),
                    ty ? "CONS" : "PRIM",
                    valuename(cl, tag));
-           asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&",
-                     name, m->gen_name);
-           if (s == NULL)
+           if (asprintf (&s, "%s(%s)->u.%s", m->optional ? "" : "&",
+                         name, m->gen_name) < 0 || s == NULL)
                errx(1, "malloc");
            decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL);
            fprintf(codefile,
@@ -667,7 +661,7 @@ generate_type_decode (const Symbol *s)
 {
     int preserve = preserve_type(s->name) ? TRUE : FALSE;
 
-    fprintf (codefile, "int\n"
+    fprintf (codefile, "int ASN1CALL\n"
             "decode_%s(const unsigned char *p,"
             " size_t len, %s *data, size_t *size)\n"
             "{\n",
index e9b4e7cd12e60852f16010db85470451c594557c..43f29c1fe123fa7e466b057d5b3c7424815d9b1d 100644 (file)
@@ -259,13 +259,12 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
            break;
 
        ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
-           char *s;
+           char *s = NULL;
 
            if (m->ellipsis)
                continue;
 
-           asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name);
-           if (s == NULL)
+           if (asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name) < 0 || s == NULL)
                errx(1, "malloc");
            fprintf(codefile, "/* %s */\n", m->name);
            if (m->optional)
@@ -289,8 +288,8 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
        fprintf(codefile,
                "{\n"
                "struct heim_octet_string *val;\n"
-               "size_t elen, totallen = 0;\n"
-               "int eret;\n");
+               "size_t elen = 0, totallen = 0;\n"
+               "int eret = 0;\n");
 
        fprintf(codefile,
                "if ((%s)->len > UINT_MAX/sizeof(val[0]))\n"
@@ -352,19 +351,17 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
        break;
     }
     case TSequenceOf: {
-       char *n;
-       char *sname;
+       char *sname = NULL;
+       char *n = NULL;
 
        fprintf (codefile,
                 "for(i = (%s)->len - 1; i >= 0; --i) {\n"
                 "size_t %s_for_oldret = ret;\n"
                 "ret = 0;\n",
                 name, tmpstr);
-       asprintf (&n, "&(%s)->val[i]", name);
-       if (n == NULL)
+       if (asprintf (&n, "&(%s)->val[i]", name) < 0 || n == NULL)
            errx(1, "malloc");
-       asprintf (&sname, "%s_S_Of", tmpstr);
-       if (sname == NULL)
+       if (asprintf (&sname, "%s_S_Of", tmpstr) < 0 || sname == NULL)
            errx(1, "malloc");
        encode_type (n, t->subtype, sname);
        fprintf (codefile,
@@ -388,10 +385,9 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
        constructed = 0;
        break;
     case TTag: {
-       char *tname;
+       char *tname = NULL;
        int c;
-       asprintf (&tname, "%s_tag", tmpstr);
-       if (tname == NULL)
+       if (asprintf (&tname, "%s_tag", tmpstr) < 0 || tname == NULL)
            errx(1, "malloc");
        c = encode_type (name, t->subtype, tname);
        fprintf (codefile,
@@ -405,20 +401,19 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
     }
     case TChoice:{
        Member *m, *have_ellipsis = NULL;
-       char *s;
+       char *s = NULL;
 
        if (t->members == NULL)
            break;
 
        fprintf(codefile, "\n");
 
-       asprintf (&s, "(%s)", name);
-       if (s == NULL)
+       if (asprintf (&s, "(%s)", name) < 0 || s == NULL)
            errx(1, "malloc");
        fprintf(codefile, "switch(%s->element) {\n", s);
 
        ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
-           char *s2;
+           char *s2 = NULL;
 
            if (m->ellipsis) {
                have_ellipsis = m;
@@ -426,9 +421,8 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
            }
 
            fprintf (codefile, "case %s: {", m->label);
-           asprintf(&s2, "%s(%s)->u.%s", m->optional ? "" : "&",
-                    s, m->gen_name);
-           if (s2 == NULL)
+           if (asprintf(&s2, "%s(%s)->u.%s", m->optional ? "" : "&",
+                        s, m->gen_name) < 0 || s2 == NULL)
                errx(1, "malloc");
            if (m->optional)
                fprintf (codefile, "if(%s) {\n", s2);
@@ -508,7 +502,7 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
 void
 generate_type_encode (const Symbol *s)
 {
-    fprintf (codefile, "int\n"
+    fprintf (codefile, "int ASN1CALL\n"
             "encode_%s(unsigned char *p, size_t len,"
             " const %s *data, size_t *size)\n"
             "{\n",
index dc612074a3a66e04474c649b47450897592f99c6..7c88751c32b28388dc9196a87299d3d93401748c 100644 (file)
@@ -93,10 +93,9 @@ free_type (const char *name, const Type *t, int preserve)
 
            if(t->type == TChoice)
                fprintf(codefile, "case %s:\n", m->label);
-           asprintf (&s, "%s(%s)->%s%s",
-                     m->optional ? "" : "&", name,
-                     t->type == TChoice ? "u." : "", m->gen_name);
-           if (s == NULL)
+           if (asprintf (&s, "%s(%s)->%s%s",
+                         m->optional ? "" : "&", name,
+                         t->type == TChoice ? "u." : "", m->gen_name) < 0 || s == NULL)
                errx(1, "malloc");
            if(m->optional)
                fprintf(codefile, "if(%s) {\n", s);
@@ -128,8 +127,7 @@ free_type (const char *name, const Type *t, int preserve)
        char *n;
 
        fprintf (codefile, "while((%s)->len){\n", name);
-       asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name);
-       if (n == NULL)
+       if (asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name) < 0 || n == NULL)
            errx(1, "malloc");
        free_type(n, t->subtype, FALSE);
        fprintf(codefile,
@@ -182,7 +180,7 @@ generate_type_free (const Symbol *s)
 {
     int preserve = preserve_type(s->name) ? TRUE : FALSE;
    
-    fprintf (codefile, "void\n"
+    fprintf (codefile, "void ASN1CALL\n"
             "free_%s(%s *data)\n"
             "{\n",
             s->gen_name, s->gen_name);
index 32680cef4112ef0720fb6baa6e97f7e63e55e93e..5ab93305a24ed186db8dedebb524ed6790e1b27c 100644 (file)
@@ -103,7 +103,7 @@ generate_units (const Type *t, const char *gen_name)
                 gen_name, gen_name);
     } else {
        fprintf (headerfile,
-                "const struct units * asn1_%s_units(void);",
+                "const struct units * asn1_%s_units(void);\n",
                 gen_name);
     }
 
index da6d26e3735faede26c0cb5b0d6cea697302fff1..20b5adfe5d022b99e1e7cd6932d6a5561f2f051c 100644 (file)
@@ -149,10 +149,9 @@ length_type (const char *name, const Type *t,
            if(t->type == TChoice)
                fprintf(codefile, "case %s:\n", m->label);
 
-           asprintf (&s, "%s(%s)->%s%s",
-                     m->optional ? "" : "&", name,
-                     t->type == TChoice ? "u." : "", m->gen_name);
-           if (s == NULL)
+           if (asprintf (&s, "%s(%s)->%s%s",
+                         m->optional ? "" : "&", name,
+                         t->type == TChoice ? "u." : "", m->gen_name) < 0 || s == NULL)
                errx(1, "malloc");
            if (m->optional)
                fprintf (codefile, "if(%s)", s);
@@ -183,24 +182,22 @@ length_type (const char *name, const Type *t,
     }
     case TSetOf:
     case TSequenceOf: {
-       char *n;
-       char *sname;
+       char *n = NULL;
+       char *sname = NULL;
 
        fprintf (codefile,
                 "{\n"
-                "int %s_oldret = %s;\n"
+                "size_t %s_oldret = %s;\n"
                 "int i;\n"
                 "%s = 0;\n",
                 tmpstr, variable, variable);
 
        fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i){\n", name);
-       fprintf (codefile, "int %s_for_oldret = %s;\n"
+       fprintf (codefile, "size_t %s_for_oldret = %s;\n"
                 "%s = 0;\n", tmpstr, variable, variable);
-       asprintf (&n, "&(%s)->val[i]", name);
-       if (n == NULL)
+       if (asprintf (&n, "&(%s)->val[i]", name) < 0  || n == NULL)
            errx(1, "malloc");
-       asprintf (&sname, "%s_S_Of", tmpstr);
-       if (sname == NULL)
+       if (asprintf (&sname, "%s_S_Of", tmpstr) < 0 || sname == NULL)
            errx(1, "malloc");
        length_type(n, t->subtype, variable, sname);
        fprintf (codefile, "%s += %s_for_oldret;\n",
@@ -248,9 +245,8 @@ length_type (const char *name, const Type *t,
        fprintf (codefile, "/* NULL */\n");
        break;
     case TTag:{
-       char *tname;
-       asprintf(&tname, "%s_tag", tmpstr);
-       if (tname == NULL)
+       char *tname = NULL;
+       if (asprintf(&tname, "%s_tag", tmpstr) < 0 || tname == NULL)
            errx(1, "malloc");
        length_type (name, t->subtype, variable, tname);
        fprintf (codefile, "ret += %lu + der_length_len (ret);\n",
@@ -271,7 +267,7 @@ void
 generate_type_length (const Symbol *s)
 {
     fprintf (codefile,
-            "size_t\n"
+            "size_t ASN1CALL\n"
             "length_%s(const %s *data)\n"
             "{\n"
             "size_t ret = 0;\n",
index ec3ccc265e374a44712b3582c182188917c798aa..ac7b9ed0ba17c69091bb8879557523a6936ea681 100644 (file)
@@ -47,8 +47,8 @@ generate_type_seq (const Symbol *s)
     while(type->type == TTag)
        type = type->subtype;
 
-    if (type->type != TSequenceOf) {
-       printf("%s not seq of %d\n", s->name, (int)type->type);
+    if (type->type != TSequenceOf && type->type != TSetOf) {
+       fprintf(stderr, "%s not seq of %d\n", s->name, (int)type->type);
        return;
     }
 
@@ -67,12 +67,12 @@ generate_type_seq (const Symbol *s)
     subname = type->subtype->symbol->gen_name;
 
     fprintf (headerfile,
-            "int   add_%s  (%s *, const %s *);\n"
-            "int   remove_%s  (%s *, unsigned int);\n",
+            "ASN1EXP int   ASN1CALL add_%s  (%s *, const %s *);\n"
+            "ASN1EXP int   ASN1CALL remove_%s  (%s *, unsigned int);\n",
             s->gen_name, s->gen_name, subname,
             s->gen_name, s->gen_name);
 
-    fprintf (codefile, "int\n"
+    fprintf (codefile, "int ASN1CALL\n"
             "add_%s(%s *data, const %s *element)\n"
             "{\n",
             s->gen_name, s->gen_name, subname);
@@ -93,7 +93,7 @@ generate_type_seq (const Symbol *s)
 
     fprintf (codefile, "}\n\n");
 
-    fprintf (codefile, "int\n"
+    fprintf (codefile, "int ASN1CALL\n"
             "remove_%s(%s *data, unsigned int element)\n"
             "{\n",
             s->gen_name, s->gen_name);
index 8d4d9b49c2936bfa83cb7e3192d7397ea282d9b6..9e09eb2d8db1f50d221b9036f540ee5590183ac1 100644 (file)
@@ -224,7 +224,8 @@ partial_offset(const char *basetype, const char *name, int need_offset)
     char *str;
     if (name == NULL || need_offset == 0)
        return strdup("0");
-    asprintf(&str, "offsetof(struct %s, %s)", basetype, name);
+    if (asprintf(&str, "offsetof(struct %s, %s)", basetype, name) < 0 || str == NULL)
+       errx(1, "malloc");
     return str;
 }
 
@@ -273,7 +274,8 @@ tlist_header(struct tlist *t, const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
-    vasprintf(&t->header, fmt, ap);
+    if (vasprintf(&t->header, fmt, ap) < 0 || t->header == NULL)
+       errx(1, "malloc");
     va_end(ap);
 }
 
@@ -389,7 +391,8 @@ add_line(struct templatehead *t, const char *fmt, ...)
     struct template *q = calloc(1, sizeof(*q));
     va_list ap;
     va_start(ap, fmt);
-    vasprintf(&q->line, fmt, ap);
+    if (vasprintf(&q->line, fmt, ap) < 0 || q->line == NULL)
+       errx(1, "malloc");
     va_end(ap);
     ASN1_TAILQ_INSERT_TAIL(t, q, members);
     return q;
@@ -404,10 +407,11 @@ add_line_pointer(struct templatehead *t,
 {
     struct template *q;
     va_list ap;
-    char *tt;
+    char *tt = NULL;
 
     va_start(ap, ttfmt);
-    vasprintf(&tt, ttfmt, ap);
+    if (vasprintf(&tt, ttfmt, ap) < 0 || tt == NULL)
+       errx(1, "malloc");
     va_end(ap);
 
     q = add_line(t, "{ %s, %s, asn1_%s }", tt, offset, ptr);
@@ -543,7 +547,7 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
        struct template *q;
        Member *m;
        size_t count = 0, i;
-       char *bname;
+       char *bname = NULL;
        FILE *f = get_code_file();
 
        if (ASN1_TAILQ_EMPTY(t->members)) {
@@ -551,7 +555,8 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
            break;
        }
 
-       asprintf(&bname, "bmember_%s_%lu", name ? name : "", (unsigned long)t);
+       if (asprintf(&bname, "bmember_%s_%lu", name ? name : "", (unsigned long)t) < 0 || bname == NULL)
+           errx(1, "malloc");
        output_name(bname);
 
        ASN1_TAILQ_FOREACH(m, t->members, members) {
@@ -583,15 +588,18 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
        Member *m;
 
        ASN1_TAILQ_FOREACH(m, t->members, members) {
-           char *newbasename;
-
+           char *newbasename = NULL;
+           
            if (m->ellipsis)
                continue;
 
-           if (name)
-               asprintf(&newbasename, "%s_%s", basetype, name);
-           else
+           if (name) {
+               if (asprintf(&newbasename, "%s_%s", basetype, name) < 0)
+                   errx(1, "malloc");
+           } else
                newbasename = strdup(basetype);
+           if (newbasename == NULL)
+               errx(1, "malloc");
 
            template_members(temp, newbasename, m->gen_name, m->type, m->optional, isstruct, 1);
 
@@ -601,7 +609,7 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
        break;
     }
     case TTag: {
-       char *tname, *elname;
+       char *tname = NULL, *elname = NULL;
        const char *sename, *dupname;
        int subtype_is_struct = is_struct(t->subtype, isstruct);
 
@@ -610,10 +618,12 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
        else
            sename = symbol_name(basetype, t->subtype);
 
-       asprintf(&tname, "tag_%s_%lu", name ? name : "", (unsigned long)t);
+       if (asprintf(&tname, "tag_%s_%lu", name ? name : "", (unsigned long)t) < 0 || tname == NULL)
+           errx(1, "malloc");
        output_name(tname);
 
-       asprintf(&elname, "%s_%s", basetype, tname);
+       if (asprintf(&elname, "%s_%s", basetype, tname) < 0 || elname == NULL)
+           errx(1, "malloc");
 
        generate_template_type(elname, &dupname, NULL, sename, name,
                               t->subtype, 0, subtype_is_struct, 0);
@@ -633,16 +643,17 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
     case TSetOf:
     case TSequenceOf: {
        const char *type, *tname, *dupname;
-       char *sename, *elname;
+       char *sename = NULL, *elname = NULL;
        int subtype_is_struct = is_struct(t->subtype, 0);
 
        if (name && subtype_is_struct) {
            tname = "seofTstruct";
-           asprintf(&sename, "%s_%s_val",
-                    basetype, name);
+           if (asprintf(&sename, "%s_%s_val", basetype, name) < 0)
+               errx(1, "malloc");
        } else if (subtype_is_struct) {
            tname = "seofTstruct";
-           asprintf(&sename, "%s_val", symbol_name(basetype, t->subtype));
+           if (asprintf(&sename, "%s_val", symbol_name(basetype, t->subtype)) < 0)
+               errx(1, "malloc");
        } else {
            if (name)
                tname = name;
@@ -650,12 +661,15 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
                tname = "seofTstruct";
            sename = strdup(symbol_name(basetype, t->subtype));
        }
+       if (sename == NULL)
+           errx(1, "malloc");
 
        if (t->type == TSetOf) type = "A1_OP_SETOF";
        else if (t->type == TSequenceOf) type = "A1_OP_SEQOF";
        else abort();
 
-       asprintf(&elname, "%s_%s_%lu", basetype, tname, (unsigned long)t);
+       if (asprintf(&elname, "%s_%s_%lu", basetype, tname, (unsigned long)t) < 0 || elname == NULL)
+           errx(1, "malloc");
 
        generate_template_type(elname, &dupname, NULL, sename, NULL, t->subtype,
                               0, subtype_is_struct, need_offset);
@@ -668,21 +682,22 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
        struct templatehead template = ASN1_TAILQ_HEAD_INITIALIZER(template);
        struct template *q;
        size_t count = 0, i;
-       char *tname;
+       char *tname = NULL;
        FILE *f = get_code_file();
        Member *m;
        int ellipsis = 0;
        char *e;
 
-       asprintf(&tname, "asn1_choice_%s_%s%x",
-                basetype, name ? name : "", (unsigned int)(uintptr_t)t);
+       if (asprintf(&tname, "asn1_choice_%s_%s%x",
+                    basetype, name ? name : "", (unsigned int)(uintptr_t)t) < 0 || tname == NULL)
+           errx(1, "malloc");
 
        ASN1_TAILQ_FOREACH(m, t->members, members) {
            const char *dupname;
-           char *elname;
-           char *newbasename;
+           char *elname = NULL;
+           char *newbasename = NULL;
            int subtype_is_struct;
-
+           
            if (m->ellipsis) {
                ellipsis = 1;
                continue;
@@ -690,13 +705,19 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
 
            subtype_is_struct = is_struct(m->type, 0);
 
-           asprintf(&elname, "%s_choice_%s", basetype, m->gen_name);
+           if (asprintf(&elname, "%s_choice_%s", basetype, m->gen_name) < 0 || elname == NULL)
+               errx(1, "malloc");
 
-           if (subtype_is_struct)
-               asprintf(&newbasename, "%s_%s", basetype, m->gen_name);
-           else
+           if (subtype_is_struct) {
+               if (asprintf(&newbasename, "%s_%s", basetype, m->gen_name) < 0)
+                   errx(1, "malloc");
+           } else
                newbasename = strdup(basetype);
 
+           if (newbasename == NULL)
+               errx(1, "malloc");
+
+
            generate_template_type(elname, &dupname, NULL,
                                   symbol_name(newbasename, m->type),
                                   NULL, m->type, 0, subtype_is_struct, 1);
@@ -710,10 +731,11 @@ template_members(struct templatehead *temp, const char *basetype, const char *na
            free(newbasename);
        }
 
+       e = NULL;
        if (ellipsis) {
-           asprintf(&e, "offsetof(%s%s, u.asn1_ellipsis)", isstruct ? "struct " : "", basetype);
-       } else
-           e = NULL;
+           if (asprintf(&e, "offsetof(%s%s, u.asn1_ellipsis)", isstruct ? "struct " : "", basetype) < 0 || e == NULL)
+               errx(1, "malloc");
+       }
 
        ASN1_TAILQ_FOREACH(q, &template, members) {
            count++;
index 9794ca1514f5d7ee2be313cea25e52a962acb79a..5df9e41fffd2f92362e520d598193a4c5f21aa09 100644 (file)
@@ -52,6 +52,9 @@ id-rsadsi-des-ede3-cbc OBJECT IDENTIFIER ::=  { id-rsadsi-encalg 7 }
 id-secsig-sha-1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
        oiw(14) secsig(3) algorithm(2) 26 }
 
+id-secsig-sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+       oiw(14) secsig(3) algorithm(2) 29 }
+
 id-nistAlgorithm OBJECT IDENTIFIER ::= {
    joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) 4 }
   
@@ -241,6 +244,13 @@ DomainParameters ::= SEQUENCE {
        validationParms ValidationParms OPTIONAL -- ValidationParms
 }
 
+-- As defined by PKCS3
+DHParameter ::= SEQUENCE {
+       prime           INTEGER, -- odd prime, p=jq +1
+       base            INTEGER, -- generator, g
+       privateValueLength INTEGER OPTIONAL
+}
+
 DHPublicKey ::= INTEGER
 
 OtherName ::= SEQUENCE {
index a43d1e3e6cde5c01fa9e983c371615be6838c41a..fe4cc2983c50cce11d3dd2a3b8b97b0b5f285e4d 100644 (file)
@@ -43,7 +43,7 @@
 struct et_list *_et_list = NULL;
 
 
-const char *
+KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
 error_message (long code)
 {
     static char msg[128];
@@ -61,18 +61,18 @@ error_message (long code)
     return msg;
 }
 
-int
+KRB5_LIB_FUNCTION int KRB5_LIB_CALL
 init_error_table(const char **msgs, long base, int count)
 {
     initialize_error_table_r(&_et_list, msgs, count, base);
     return 0;
 }
 
-static void
+static void KRB5_CALLCONV
 default_proc (const char *whoami, long code, const char *fmt, va_list args)
     __attribute__((__format__(__printf__, 3, 0)));
 
-static void
+static void KRB5_CALLCONV
 default_proc (const char *whoami, long code, const char *fmt, va_list args)
 {
     if (whoami)
@@ -86,7 +86,7 @@ default_proc (const char *whoami, long code, const char *fmt, va_list args)
 
 static errf com_err_hook = default_proc;
 
-void
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 com_err_va (const char *whoami,
            long code,
            const char *fmt,
@@ -95,7 +95,7 @@ com_err_va (const char *whoami,
     (*com_err_hook) (whoami, code, fmt, args);
 }
 
-void
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 com_err (const char *whoami,
         long code,
         const char *fmt,
@@ -107,7 +107,7 @@ com_err (const char *whoami,
     va_end(ap);
 }
 
-errf
+KRB5_LIB_FUNCTION errf KRB5_LIB_CALL
 set_com_err_hook (errf new)
 {
     errf old = com_err_hook;
@@ -120,7 +120,7 @@ set_com_err_hook (errf new)
     return old;
 }
 
-errf
+KRB5_LIB_FUNCTION errf KRB5_LIB_CALL
 reset_com_err_hook (void)
 {
     return set_com_err_hook(NULL);
@@ -134,7 +134,7 @@ static const char char_set[] =
 
 static char buf[6];
 
-const char *
+KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
 error_table_name(int num)
 {
     int ch;
@@ -156,7 +156,7 @@ error_table_name(int num)
     return(buf);
 }
 
-void
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 add_to_error_table(struct et_list *new_table)
 {
     struct et_list *et;
index a8ceb969cb1dfc477c592846c5f565ab773c6c18..1fcfe7f7aa93218bfa5d48442a680c6f95c11320 100644 (file)
 #define __attribute__(X)
 #endif
 
-typedef void (*errf) (const char *, long, const char *, va_list);
+#ifndef KRB5_LIB
+#ifndef KRB5_LIB_FUNCTION
+#if defined(_WIN32)
+#define KRB5_LIB_FUNCTION __declspec(dllimport)
+#define KRB5_LIB_CALL __stdcall
+#define KRB5_LIB_VARIABLE __declspec(dllimport)
+#else
+#define KRB5_LIB_FUNCTION
+#define KRB5_LIB_CALL
+#define KRB5_LIB_VARIABLE
+#endif
+#endif
+#endif
+
+#ifdef _WIN32
+#define KRB5_CALLCONV __stdcall
+#else
+#define KRB5_CALLCONV
+#endif
+
+typedef void (KRB5_CALLCONV *errf) (const char *, long, const char *, va_list);
 
-const char * error_message (long);
-int init_error_table (const char**, long, int);
+KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
+error_message (long);
 
-void com_err_va (const char *, long, const char *, va_list)
+KRB5_LIB_FUNCTION int KRB5_LIB_CALL
+init_error_table (const char**, long, int);
+
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
+com_err_va (const char *, long, const char *, va_list)
     __attribute__((format(printf, 3, 0)));
 
-void com_err (const char *, long, const char *, ...)
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
+com_err (const char *, long, const char *, ...)
     __attribute__((format(printf, 3, 4)));
 
-errf set_com_err_hook (errf);
-errf reset_com_err_hook (void);
+KRB5_LIB_FUNCTION errf KRB5_LIB_CALL
+set_com_err_hook (errf);
+
+KRB5_LIB_FUNCTION errf KRB5_LIB_CALL
+reset_com_err_hook (void);
 
-const char *error_table_name  (int num);
+KRB5_LIB_FUNCTION const char * KRB5_LIB_CALL
+error_table_name  (int num);
 
-void add_to_error_table (struct et_list *new_table);
+KRB5_LIB_FUNCTION void KRB5_LIB_CALL
+add_to_error_table (struct et_list *new_table);
 
 #endif /* __COM_ERR_H__ */
index 3f217d38cb8ced2bc76ea1817d71d886def9caa9..fa53a8a74cbf3c7eaf9996bec534d72e23687558 100644 (file)
 #define GSSAPI_CPP_END
 #endif
 
+#ifdef _WIN32
+#define GSSAPI_CALLCONV __stdcall
+#else
+#define GSSAPI_CALLCONV
+#endif
+
 /*
  * Now define the three implementation-dependent types.
  */
@@ -266,7 +272,8 @@ GSSAPI_CPP_START
  * GSS_C_NT_USER_NAME should be initialized to point
  * to that gss_OID_desc.
  */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_USER_NAME;
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_user_name_oid_desc;
+#define GSS_C_NT_USER_NAME (&__gss_c_nt_user_name_oid_desc)
 
 /*
  * The implementation must reserve static storage for a
@@ -279,7 +286,8 @@ extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_USER_NAME;
  * The constant GSS_C_NT_MACHINE_UID_NAME should be
  * initialized to point to that gss_OID_desc.
  */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_MACHINE_UID_NAME;
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_machine_uid_name_oid_desc;
+#define GSS_C_NT_MACHINE_UID_NAME (&__gss_c_nt_machine_uid_name_oid_desc)
 
 /*
  * The implementation must reserve static storage for a
@@ -292,7 +300,8 @@ extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_MACHINE_UID_NAME;
  * The constant GSS_C_NT_STRING_UID_NAME should be
  * initialized to point to that gss_OID_desc.
  */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_STRING_UID_NAME;
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_string_uid_name_oid_desc;
+#define GSS_C_NT_STRING_UID_NAME (&__gss_c_nt_string_uid_name_oid_desc)
 
 /*
  * The implementation must reserve static storage for a
@@ -311,7 +320,8 @@ extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_STRING_UID_NAME;
  * parameter, but should not be emitted by GSS-API
  * implementations
  */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_HOSTBASED_SERVICE_X;
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_hostbased_service_x_oid_desc;
+#define GSS_C_NT_HOSTBASED_SERVICE_X (&__gss_c_nt_hostbased_service_x_oid_desc)
 
 /*
  * The implementation must reserve static storage for a
@@ -324,7 +334,8 @@ extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_HOSTBASED_SERVICE_X;
  * GSS_C_NT_HOSTBASED_SERVICE should be initialized
  * to point to that gss_OID_desc.
  */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_HOSTBASED_SERVICE;
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_hostbased_service_oid_desc;
+#define GSS_C_NT_HOSTBASED_SERVICE (&__gss_c_nt_hostbased_service_oid_desc)
 
 /*
  * The implementation must reserve static storage for a
@@ -336,7 +347,8 @@ extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_HOSTBASED_SERVICE;
  * and GSS_C_NT_ANONYMOUS should be initialized to point
  * to that gss_OID_desc.
  */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_ANONYMOUS;
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_anonymous_oid_desc;
+#define GSS_C_NT_ANONYMOUS (&__gss_c_nt_anonymous_oid_desc)
 
 /*
  * The implementation must reserve static storage for a
@@ -348,13 +360,16 @@ extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_ANONYMOUS;
  * GSS_C_NT_EXPORT_NAME should be initialized to point
  * to that gss_OID_desc.
  */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_EXPORT_NAME;
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_export_name_oid_desc;
+#define GSS_C_NT_EXPORT_NAME (&__gss_c_nt_export_name_oid_desc) 
 
 /*
  * Digest mechanism
  */
 
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_SASL_DIGEST_MD5_MECHANISM;
+extern gss_OID_desc GSSAPI_LIB_VARIABLE __gss_sasl_digest_md5_mechanism_oid_desc;
+#define GSS_SASL_DIGEST_MD5_MECHANISM (&__gss_sasl_digest_md5_mechanism_oid_desc)
+
 
 /* Major status codes */
 
@@ -437,7 +452,7 @@ extern GSSAPI_LIB_VARIABLE gss_OID GSS_SASL_DIGEST_MD5_MECHANISM;
  * Finally, function prototypes for the GSS-API routines.
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_acquire_cred
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_acquire_cred
            (OM_uint32 * /*minor_status*/,
             const gss_name_t /*desired_name*/,
             OM_uint32 /*time_req*/,
@@ -448,12 +463,12 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_acquire_cred
             OM_uint32 * /*time_rec*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_release_cred
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_release_cred
            (OM_uint32 * /*minor_status*/,
             gss_cred_id_t * /*cred_handle*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_init_sec_context
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_init_sec_context
            (OM_uint32 * /*minor_status*/,
             const gss_cred_id_t /*initiator_cred_handle*/,
             gss_ctx_id_t * /*context_handle*/,
@@ -469,7 +484,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_init_sec_context
             OM_uint32 * /*time_rec*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_accept_sec_context
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_accept_sec_context
            (OM_uint32 * /*minor_status*/,
             gss_ctx_id_t * /*context_handle*/,
             const gss_cred_id_t /*acceptor_cred_handle*/,
@@ -483,25 +498,25 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_accept_sec_context
             gss_cred_id_t * /*delegated_cred_handle*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_process_context_token
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_process_context_token
            (OM_uint32 * /*minor_status*/,
             const gss_ctx_id_t /*context_handle*/,
             const gss_buffer_t /*token_buffer*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_delete_sec_context
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_delete_sec_context
            (OM_uint32 * /*minor_status*/,
             gss_ctx_id_t * /*context_handle*/,
             gss_buffer_t /*output_token*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_context_time
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_context_time
            (OM_uint32 * /*minor_status*/,
             const gss_ctx_id_t /*context_handle*/,
             OM_uint32 * /*time_rec*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_get_mic
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_get_mic
            (OM_uint32 * /*minor_status*/,
             const gss_ctx_id_t /*context_handle*/,
             gss_qop_t /*qop_req*/,
@@ -509,7 +524,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_get_mic
             gss_buffer_t /*message_token*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_verify_mic
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_verify_mic
            (OM_uint32 * /*minor_status*/,
             const gss_ctx_id_t /*context_handle*/,
             const gss_buffer_t /*message_buffer*/,
@@ -517,7 +532,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_verify_mic
             gss_qop_t * /*qop_state*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_wrap
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_wrap
            (OM_uint32 * /*minor_status*/,
             const gss_ctx_id_t /*context_handle*/,
             int /*conf_req_flag*/,
@@ -527,7 +542,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_wrap
             gss_buffer_t /*output_message_buffer*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_unwrap
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_unwrap
            (OM_uint32 * /*minor_status*/,
             const gss_ctx_id_t /*context_handle*/,
             const gss_buffer_t /*input_message_buffer*/,
@@ -536,7 +551,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_unwrap
             gss_qop_t * /*qop_state*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_display_status
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_display_status
            (OM_uint32 * /*minor_status*/,
             OM_uint32 /*status_value*/,
             int /*status_type*/,
@@ -545,54 +560,54 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_display_status
             gss_buffer_t /*status_string*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_indicate_mechs
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_indicate_mechs
            (OM_uint32 * /*minor_status*/,
             gss_OID_set * /*mech_set*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_compare_name
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_compare_name
            (OM_uint32 * /*minor_status*/,
             const gss_name_t /*name1*/,
             const gss_name_t /*name2*/,
             int * /*name_equal*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_display_name
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_display_name
            (OM_uint32 * /*minor_status*/,
             const gss_name_t /*input_name*/,
             gss_buffer_t /*output_name_buffer*/,
             gss_OID * /*output_name_type*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_import_name
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_import_name
            (OM_uint32 * /*minor_status*/,
             const gss_buffer_t /*input_name_buffer*/,
             const gss_OID /*input_name_type*/,
             gss_name_t * /*output_name*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_export_name
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_export_name
            (OM_uint32  * /*minor_status*/,
             const gss_name_t /*input_name*/,
             gss_buffer_t /*exported_name*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_release_name
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_release_name
            (OM_uint32 * /*minor_status*/,
             gss_name_t * /*input_name*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_release_buffer
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_release_buffer
            (OM_uint32 * /*minor_status*/,
             gss_buffer_t /*buffer*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_release_oid_set
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_release_oid_set
            (OM_uint32 * /*minor_status*/,
             gss_OID_set * /*set*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_cred
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_cred
            (OM_uint32 * /*minor_status*/,
             const gss_cred_id_t /*cred_handle*/,
             gss_name_t * /*name*/,
@@ -601,7 +616,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_cred
             gss_OID_set * /*mechanisms*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_context (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_context (
             OM_uint32 * /*minor_status*/,
             const gss_ctx_id_t /*context_handle*/,
             gss_name_t * /*src_name*/,
@@ -613,7 +628,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_context (
             int * /*open_context*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_wrap_size_limit (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_wrap_size_limit (
             OM_uint32 * /*minor_status*/,
             const gss_ctx_id_t /*context_handle*/,
             int /*conf_req_flag*/,
@@ -622,7 +637,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_wrap_size_limit (
             OM_uint32 * /*max_input_size*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_add_cred (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_add_cred (
             OM_uint32 * /*minor_status*/,
             const gss_cred_id_t /*input_cred_handle*/,
             const gss_name_t /*desired_name*/,
@@ -636,7 +651,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_add_cred (
             OM_uint32 * /*acceptor_time_rec*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_cred_by_mech (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_cred_by_mech (
             OM_uint32 * /*minor_status*/,
             const gss_cred_id_t /*cred_handle*/,
             const gss_OID /*mech_type*/,
@@ -646,81 +661,81 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_cred_by_mech (
             gss_cred_usage_t * /*cred_usage*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_export_sec_context (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_export_sec_context (
             OM_uint32 * /*minor_status*/,
             gss_ctx_id_t * /*context_handle*/,
             gss_buffer_t /*interprocess_token*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_import_sec_context (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_import_sec_context (
             OM_uint32 * /*minor_status*/,
             const gss_buffer_t /*interprocess_token*/,
             gss_ctx_id_t * /*context_handle*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_create_empty_oid_set (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_create_empty_oid_set (
             OM_uint32 * /*minor_status*/,
             gss_OID_set * /*oid_set*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_add_oid_set_member (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_add_oid_set_member (
             OM_uint32 * /*minor_status*/,
             const gss_OID /*member_oid*/,
             gss_OID_set * /*oid_set*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_test_oid_set_member (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_test_oid_set_member (
             OM_uint32 * /*minor_status*/,
             const gss_OID /*member*/,
             const gss_OID_set /*set*/,
             int * /*present*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_names_for_mech (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_names_for_mech (
             OM_uint32 * /*minor_status*/,
             const gss_OID /*mechanism*/,
             gss_OID_set * /*name_types*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_inquire_mechs_for_name (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_inquire_mechs_for_name (
             OM_uint32 * /*minor_status*/,
             const gss_name_t /*input_name*/,
             gss_OID_set * /*mech_types*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_canonicalize_name (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_canonicalize_name (
             OM_uint32 * /*minor_status*/,
             const gss_name_t /*input_name*/,
             const gss_OID /*mech_type*/,
             gss_name_t * /*output_name*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_duplicate_name (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_duplicate_name (
             OM_uint32 * /*minor_status*/,
             const gss_name_t /*src_name*/,
             gss_name_t * /*dest_name*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_duplicate_oid (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_duplicate_oid (
            OM_uint32 * /* minor_status */,
            gss_OID /* src_oid */,
            gss_OID * /* dest_oid */
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_release_oid
        (OM_uint32 * /*minor_status*/,
         gss_OID * /* oid */
        );
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_oid_to_str(
            OM_uint32 * /*minor_status*/,
            gss_OID /* oid */,
            gss_buffer_t /* str */
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_inquire_sec_context_by_oid(
            OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
@@ -728,38 +743,38 @@ gss_inquire_sec_context_by_oid(
             gss_buffer_set_t *data_set
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_set_sec_context_option (OM_uint32 *minor_status,
                            gss_ctx_id_t *context_handle,
                            const gss_OID desired_object,
                            const gss_buffer_t value);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_set_cred_option (OM_uint32 *minor_status,
                     gss_cred_id_t *cred_handle,
                     const gss_OID object,
                     const gss_buffer_t value);
 
-int GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL
 gss_oid_equal(const gss_OID a, const gss_OID b);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_create_empty_buffer_set
           (OM_uint32 * minor_status,
            gss_buffer_set_t *buffer_set);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_add_buffer_set_member
           (OM_uint32 * minor_status,
            const gss_buffer_t member_buffer,
            gss_buffer_set_t *buffer_set);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_release_buffer_set
           (OM_uint32 * minor_status,
            gss_buffer_set_t *buffer_set);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_inquire_cred_by_oid(OM_uint32 *minor_status,
                        const gss_cred_id_t cred_handle,
                        const gss_OID desired_object,
@@ -772,7 +787,7 @@ gss_inquire_cred_by_oid(OM_uint32 *minor_status,
 #define GSS_C_PRF_KEY_FULL 0
 #define GSS_C_PRF_KEY_PARTIAL 1
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_pseudo_random
        (OM_uint32 *minor_status,
         gss_ctx_id_t context,
@@ -782,7 +797,7 @@ gss_pseudo_random
         gss_buffer_t prf_out
        );
 
-OM_uint32
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_store_cred(OM_uint32         * /* minor_status */,
               gss_cred_id_t     /* input_cred_handle */,
               gss_cred_usage_t  /* cred_usage */,
@@ -807,10 +822,11 @@ typedef struct {
                         (GSS_IOV_BUFFER_TYPE_PADDING) */
 } gss_context_stream_sizes; 
 
-extern gss_OID GSSAPI_LIB_VARIABLE GSS_C_ATTR_STREAM_SIZES;
+extern gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_attr_stream_sizes_oid_desc;
+#define GSS_C_ATTR_STREAM_SIZES (&__gss_c_attr_stream_sizes_oid_desc)
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_context_query_attributes(OM_uint32 * /* minor_status */,
                             const gss_ctx_id_t /* context_handle */,
                             const gss_OID /* attribute */,
@@ -827,7 +843,7 @@ gss_context_query_attributes(OM_uint32 * /* minor_status */,
  * obsolete versions of these routines and their current forms.
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_sign
+GSSAPI_DEPRECATED GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_sign
            (OM_uint32 * /*minor_status*/,
             gss_ctx_id_t /*context_handle*/,
             int /*qop_req*/,
@@ -835,7 +851,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_sign
             gss_buffer_t /*message_token*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_verify
+GSSAPI_DEPRECATED GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_verify
            (OM_uint32 * /*minor_status*/,
             gss_ctx_id_t /*context_handle*/,
             gss_buffer_t /*message_buffer*/,
@@ -843,7 +859,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_verify
             int * /*qop_state*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_seal
+GSSAPI_DEPRECATED GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_seal
            (OM_uint32 * /*minor_status*/,
             gss_ctx_id_t /*context_handle*/,
             int /*conf_req_flag*/,
@@ -853,7 +869,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_seal
             gss_buffer_t /*output_message_buffer*/
            );
 
-OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_unseal
+GSSAPI_DEPRECATED GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_unseal
            (OM_uint32 * /*minor_status*/,
             gss_ctx_id_t /*context_handle*/,
             gss_buffer_t /*input_message_buffer*/,
@@ -866,12 +882,12 @@ OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_unseal
  *
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_encapsulate_token(const gss_buffer_t /* input_token */,
                      const gss_OID /* oid */,
                      gss_buffer_t /* output_token */);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_decapsulate_token(const gss_buffer_t /* input_token */,
                      const gss_OID /* oid */,
                      gss_buffer_t /* output_token */);
@@ -886,29 +902,29 @@ gss_decapsulate_token(const gss_buffer_t /* input_token */,
  * GSS_IOV
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_wrap_iov(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, int *,
             gss_iov_buffer_desc *, int);
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_unwrap_iov(OM_uint32 *, gss_ctx_id_t, int *, gss_qop_t *,
               gss_iov_buffer_desc *, int);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_wrap_iov_length(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, int *,
                    gss_iov_buffer_desc *, int);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_release_iov_buffer(OM_uint32 *, gss_iov_buffer_desc *, int);
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_export_cred(OM_uint32 * /* minor_status */,
                gss_cred_id_t /* cred_handle */,
                gss_buffer_t /* cred_token */);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_import_cred(OM_uint32 * /* minor_status */,
                gss_buffer_t /* cred_token */,
                gss_cred_id_t * /* cred_handle */);
index 1b91bbbb845c337c2b0f1b8d1f37e7fea9af8fd9..28f9c3777b5a57bda3dd2ae2ad42576fdc5a4d46 100644 (file)
@@ -53,12 +53,15 @@ GSSAPI_CPP_START
  * This is for kerberos5 names.
  */
 
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_NT_PRINCIPAL_NAME;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_NT_USER_NAME;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_NT_MACHINE_UID_NAME;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_NT_STRING_UID_NAME;
+extern gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_nt_principal_name_oid_desc;
+#define GSS_KRB5_NT_PRINCIPAL_NAME (&__gss_krb5_nt_principal_name_oid_desc)
 
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_MECHANISM;
+#define GSS_KRB5_NT_USER_NAME (&__gss_c_nt_user_name_oid_desc)
+#define GSS_KRB5_NT_MACHINE_UID_NAME (&__gss_c_nt_machine_uid_name_oid_desc)
+#define GSS_KRB5_NT_STRING_UID_NAME (&__gss_c_nt_string_uid_name_oid_desc)
+
+extern gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_mechanism_oid_desc;
+#define GSS_KRB5_MECHANISM (&__gss_krb5_mechanism_oid_desc)
 
 /* for compatibility with MIT api */
 
@@ -66,31 +69,77 @@ extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_MECHANISM;
 #define gss_krb5_nt_general_name GSS_KRB5_NT_PRINCIPAL_NAME
 
 /* Extensions set contexts options */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_COPY_CCACHE_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_COMPAT_DES3_MIC_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_SET_DNS_CANONICALIZE_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_SEND_TO_KDC_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_SET_DEFAULT_REALM_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_CCACHE_NAME_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_SET_TIME_OFFSET_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_TIME_OFFSET_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_PLUGIN_REGISTER_X;
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_copy_ccache_x_oid_desc;
+#define GSS_KRB5_COPY_CCACHE_X (&__gss_krb5_copy_ccache_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_compat_des3_mic_x_oid_desc;
+#define GSS_KRB5_COMPAT_DES3_MIC_X (&__gss_krb5_compat_des3_mic_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_register_acceptor_identity_x_oid_desc;
+#define GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X (&__gss_krb5_register_acceptor_identity_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_set_dns_canonicalize_x_oid_desc;
+#define GSS_KRB5_SET_DNS_CANONICALIZE_X (&__gss_krb5_set_dns_canonicalize_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_send_to_kdc_x_oid_desc;
+#define GSS_KRB5_SEND_TO_KDC_X (&__gss_krb5_send_to_kdc_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_set_default_realm_x_oid_desc;
+#define GSS_KRB5_SET_DEFAULT_REALM_X (&__gss_krb5_set_default_realm_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_ccache_name_x_oid_desc;
+#define GSS_KRB5_CCACHE_NAME_X (&__gss_krb5_ccache_name_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_set_time_offset_x_oid_desc;
+#define GSS_KRB5_SET_TIME_OFFSET_X (&__gss_krb5_set_time_offset_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_time_offset_x_oid_desc;
+#define GSS_KRB5_GET_TIME_OFFSET_X (&__gss_krb5_get_time_offset_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_plugin_register_x_oid_desc;
+#define GSS_KRB5_PLUGIN_REGISTER_X (&__gss_krb5_plugin_register_x_oid_desc)
+
 /* Extensions inquire context */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_TKT_FLAGS_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_PEER_HAS_UPDATED_SPNEGO;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_EXPORT_LUCID_CONTEXT_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_SUBKEY_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_INITIATOR_SUBKEY_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_ACCEPTOR_SUBKEY_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_AUTHTIME_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_GET_SERVICE_KEYBLOCK_X;
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_tkt_flags_x_oid_desc;
+#define GSS_KRB5_GET_TKT_FLAGS_X (&__gss_krb5_get_tkt_flags_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_extract_authz_data_from_sec_context_x_oid_desc;
+#define GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X (&__gss_krb5_extract_authz_data_from_sec_context_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_peer_has_updated_spnego_oid_desc;
+#define GSS_C_PEER_HAS_UPDATED_SPNEGO (&__gss_c_peer_has_updated_spnego_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_export_lucid_context_x_oid_desc;
+#define GSS_KRB5_EXPORT_LUCID_CONTEXT_X (&__gss_krb5_export_lucid_context_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_export_lucid_context_v1_x_oid_desc;
+#define GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X (&__gss_krb5_export_lucid_context_v1_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_subkey_x_oid_desc;
+#define GSS_KRB5_GET_SUBKEY_X (&__gss_krb5_get_subkey_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_initiator_subkey_x_oid_desc;
+#define GSS_KRB5_GET_INITIATOR_SUBKEY_X (&__gss_krb5_get_initiator_subkey_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_acceptor_subkey_x_oid_desc;
+#define GSS_KRB5_GET_ACCEPTOR_SUBKEY_X (&__gss_krb5_get_acceptor_subkey_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_authtime_x_oid_desc;
+#define GSS_KRB5_GET_AUTHTIME_X (&__gss_krb5_get_authtime_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_get_service_keyblock_x_oid_desc;
+#define GSS_KRB5_GET_SERVICE_KEYBLOCK_X (&__gss_krb5_get_service_keyblock_x_oid_desc)
+
 /* Extensions creds */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_IMPORT_CRED_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X;
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X;
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_import_cred_x_oid_desc;
+#define GSS_KRB5_IMPORT_CRED_X (&__gss_krb5_import_cred_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_set_allowable_enctypes_x_oid_desc;
+#define GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X (&__gss_krb5_set_allowable_enctypes_x_oid_desc)
+
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_krb5_cred_no_ci_flags_x_oid_desc;
+#define GSS_KRB5_CRED_NO_CI_FLAGS_X (&__gss_krb5_cred_no_ci_flags_x_oid_desc)
 
 /*
  * kerberos mechanism specific functions
@@ -100,42 +149,42 @@ struct krb5_keytab_data;
 struct krb5_ccache_data;
 struct Principal;
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_ccache_name(OM_uint32 * /*minor_status*/,
                     const char * /*name */,
                     const char ** /*out_name */);
 
-OM_uint32 GSSAPI_LIB_FUNCTION gsskrb5_register_acceptor_identity
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gsskrb5_register_acceptor_identity
         (const char * /*identity*/);
 
-OM_uint32 GSSAPI_LIB_FUNCTION krb5_gss_register_acceptor_identity
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL krb5_gss_register_acceptor_identity
        (const char * /*identity*/);
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_krb5_copy_ccache
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_krb5_copy_ccache
        (OM_uint32 * /*minor*/,
         gss_cred_id_t /*cred*/,
         struct krb5_ccache_data * /*out*/);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_import_cred(OM_uint32 * /*minor*/,
                     struct krb5_ccache_data * /*in*/,
                     struct Principal * /*keytab_principal*/,
                     struct krb5_keytab_data * /*keytab*/,
                     gss_cred_id_t * /*out*/);
 
-OM_uint32 GSSAPI_LIB_FUNCTION gss_krb5_get_tkt_flags
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_krb5_get_tkt_flags
        (OM_uint32 * /*minor*/,
         gss_ctx_id_t /*context_handle*/,
         OM_uint32 * /*tkt_flags*/);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_extract_authz_data_from_sec_context
        (OM_uint32 * /*minor_status*/,
         gss_ctx_id_t /*context_handle*/,
         int /*ad_type*/,
         gss_buffer_t /*ad_data*/);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_set_dns_canonicalize(int);
 
 struct gsskrb5_send_to_kdc {
@@ -143,35 +192,35 @@ struct gsskrb5_send_to_kdc {
     void *ptr;
 };
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *)
     GSSKRB5_FUNCTION_DEPRECATED;
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_set_default_realm(const char *);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_extract_authtime_from_sec_context(OM_uint32 *, gss_ctx_id_t, time_t *);
 
 struct EncryptionKey;
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_extract_service_keyblock(OM_uint32 *minor_status,
                                 gss_ctx_id_t context_handle,
                                 struct EncryptionKey **out);
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_get_initiator_subkey(OM_uint32 *minor_status,
                                 gss_ctx_id_t context_handle,
                                 struct EncryptionKey **out);
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_get_subkey(OM_uint32 *minor_status,
                   gss_ctx_id_t context_handle,
                   struct EncryptionKey **out);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_set_time_offset(int);
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_get_time_offset(int *);
 
 struct gsskrb5_krb5_plugin {
@@ -180,7 +229,7 @@ struct gsskrb5_krb5_plugin {
     void *symbol;
 };
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_plugin_register(struct gsskrb5_krb5_plugin *);
 
 
@@ -226,19 +275,19 @@ typedef struct gss_krb5_lucid_context_version {
  * Function declarations
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
                                  gss_ctx_id_t *context_handle,
                                  OM_uint32 version,
                                  void **kctx);
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status,
                                void *kctx);
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
                                gss_cred_id_t cred,
                                OM_uint32 num_enctypes,
index c5d372d6dc4618a462c4eefeb045b556f4ca8b10..dd3b2a5c3f8be2335f7329b7204d7ff02bc98288 100644 (file)
@@ -46,7 +46,8 @@ GSSAPI_CPP_START
  *  negotiation token is identified by the Object Identifier
  *  iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2).
  */
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_SPNEGO_MECHANISM;
+extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_spnego_mechanism_oid_desc;
+#define GSS_SPNEGO_MECHANISM (&__gss_spnego_mechanism_oid_desc)
 #define gss_mech_spnego GSS_SPNEGO_MECHANISM
 
 GSSAPI_CPP_END
index 65cabf54d170ca7618eddcbdd6d5544047101961..93b7bf72d79030c6a36f3708fb9b25e62e12d794 100644 (file)
@@ -31,7 +31,7 @@
 
 #include <gssapi.h>
 
-typedef OM_uint32 _gss_acquire_cred_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_acquire_cred_t
              (OM_uint32 *,            /* minor_status */
               const gss_name_t,       /* desired_name */
               OM_uint32,              /* time_req */
@@ -42,12 +42,12 @@ typedef OM_uint32 _gss_acquire_cred_t
               OM_uint32 *             /* time_rec */
              );
 
-typedef OM_uint32 _gss_release_cred_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_release_cred_t
              (OM_uint32 *,            /* minor_status */
               gss_cred_id_t *         /* cred_handle */
              );
 
-typedef OM_uint32 _gss_init_sec_context_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_init_sec_context_t
              (OM_uint32 *,            /* minor_status */
               const gss_cred_id_t,    /* initiator_cred_handle */
               gss_ctx_id_t *,         /* context_handle */
@@ -64,7 +64,7 @@ typedef OM_uint32 _gss_init_sec_context_t
               OM_uint32 *             /* time_rec */
              );
 
-typedef OM_uint32 _gss_accept_sec_context_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_accept_sec_context_t
              (OM_uint32 *,            /* minor_status */
               gss_ctx_id_t *,         /* context_handle */
               const gss_cred_id_t,    /* acceptor_cred_handle */
@@ -79,25 +79,25 @@ typedef OM_uint32 _gss_accept_sec_context_t
               gss_cred_id_t *         /* delegated_cred_handle */
              );
 
-typedef OM_uint32 _gss_process_context_token_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_process_context_token_t
              (OM_uint32 *,            /* minor_status */
               const gss_ctx_id_t,     /* context_handle */
               const gss_buffer_t      /* token_buffer */
              );
 
-typedef OM_uint32 _gss_delete_sec_context_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_delete_sec_context_t
              (OM_uint32 *,            /* minor_status */
               gss_ctx_id_t *,         /* context_handle */
               gss_buffer_t            /* output_token */
              );
 
-typedef OM_uint32 _gss_context_time_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_context_time_t
              (OM_uint32 *,            /* minor_status */
               const gss_ctx_id_t,     /* context_handle */
               OM_uint32 *             /* time_rec */
              );
 
-typedef OM_uint32 _gss_get_mic_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_get_mic_t
              (OM_uint32 *,            /* minor_status */
               const gss_ctx_id_t,     /* context_handle */
               gss_qop_t,              /* qop_req */
@@ -105,7 +105,7 @@ typedef OM_uint32 _gss_get_mic_t
               gss_buffer_t            /* message_token */
              );
 
-typedef OM_uint32 _gss_verify_mic_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_verify_mic_t
              (OM_uint32 *,            /* minor_status */
               const gss_ctx_id_t,     /* context_handle */
               const gss_buffer_t,     /* message_buffer */
@@ -113,7 +113,7 @@ typedef OM_uint32 _gss_verify_mic_t
               gss_qop_t *             /* qop_state */
              );
 
-typedef OM_uint32 _gss_wrap_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_wrap_t
              (OM_uint32 *,            /* minor_status */
               const gss_ctx_id_t,     /* context_handle */
               int,                    /* conf_req_flag */
@@ -123,7 +123,7 @@ typedef OM_uint32 _gss_wrap_t
               gss_buffer_t            /* output_message_buffer */
              );
 
-typedef OM_uint32 _gss_unwrap_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_unwrap_t
              (OM_uint32 *,            /* minor_status */
               const gss_ctx_id_t,     /* context_handle */
               const gss_buffer_t,     /* input_message_buffer */
@@ -132,7 +132,7 @@ typedef OM_uint32 _gss_unwrap_t
               gss_qop_t *             /* qop_state */
              );
 
-typedef OM_uint32 _gss_display_status_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_display_status_t
              (OM_uint32 *,            /* minor_status */
               OM_uint32,              /* status_value */
               int,                    /* status_type */
@@ -141,44 +141,44 @@ typedef OM_uint32 _gss_display_status_t
               gss_buffer_t            /* status_string */
              );
 
-typedef OM_uint32 _gss_indicate_mechs_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_indicate_mechs_t
              (OM_uint32 *,            /* minor_status */
               gss_OID_set *           /* mech_set */
              );
 
-typedef OM_uint32 _gss_compare_name_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_compare_name_t
              (OM_uint32 *,            /* minor_status */
               const gss_name_t,       /* name1 */
               const gss_name_t,       /* name2 */
               int *                   /* name_equal */
              );
 
-typedef OM_uint32 _gss_display_name_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_display_name_t
              (OM_uint32 *,            /* minor_status */
               const gss_name_t,       /* input_name */
               gss_buffer_t,           /* output_name_buffer */
               gss_OID *               /* output_name_type */
              );
 
-typedef OM_uint32 _gss_import_name_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_import_name_t
              (OM_uint32 *,            /* minor_status */
               const gss_buffer_t,     /* input_name_buffer */
               const gss_OID,          /* input_name_type */
               gss_name_t *            /* output_name */
              );
 
-typedef OM_uint32 _gss_export_name_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_export_name_t
              (OM_uint32 *,            /* minor_status */
               const gss_name_t,       /* input_name */
               gss_buffer_t            /* exported_name */
              );
 
-typedef OM_uint32 _gss_release_name_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_release_name_t
              (OM_uint32 *,            /* minor_status */
               gss_name_t *            /* input_name */
              );
 
-typedef OM_uint32 _gss_inquire_cred_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_cred_t
              (OM_uint32 *,            /* minor_status */
               const gss_cred_id_t,    /* cred_handle */
               gss_name_t *,           /* name */
@@ -187,7 +187,7 @@ typedef OM_uint32 _gss_inquire_cred_t
               gss_OID_set *           /* mechanisms */
              );
 
-typedef OM_uint32 _gss_inquire_context_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_context_t
              (OM_uint32 *,            /* minor_status */
               const gss_ctx_id_t,     /* context_handle */
               gss_name_t *,           /* src_name */
@@ -199,7 +199,7 @@ typedef OM_uint32 _gss_inquire_context_t
               int *                   /* open */
              );
 
-typedef OM_uint32 _gss_wrap_size_limit_t
+typedef OM_uint32 GSSAPI_CALLCONV _gss_wrap_size_limit_t
              (OM_uint32 *,            /* minor_status */
               const gss_ctx_id_t,     /* context_handle */
               int,                    /* conf_req_flag */
@@ -208,7 +208,7 @@ typedef OM_uint32 _gss_wrap_size_limit_t
               OM_uint32 *             /* max_input_size */
              );
 
-typedef OM_uint32 _gss_add_cred_t (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_add_cred_t (
               OM_uint32 *,            /* minor_status */
               const gss_cred_id_t,    /* input_cred_handle */
               const gss_name_t,       /* desired_name */
@@ -222,7 +222,7 @@ typedef OM_uint32 _gss_add_cred_t (
               OM_uint32 *             /* acceptor_time_rec */
              );
 
-typedef OM_uint32 _gss_inquire_cred_by_mech_t (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_cred_by_mech_t (
               OM_uint32 *,            /* minor_status */
               const gss_cred_id_t,    /* cred_handle */
               const gss_OID,          /* mech_type */
@@ -232,65 +232,65 @@ typedef OM_uint32 _gss_inquire_cred_by_mech_t (
               gss_cred_usage_t *      /* cred_usage */
              );
 
-typedef OM_uint32 _gss_export_sec_context_t (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_export_sec_context_t (
               OM_uint32 *,            /* minor_status */
               gss_ctx_id_t *,         /* context_handle */
               gss_buffer_t            /* interprocess_token */
              );
 
-typedef OM_uint32 _gss_import_sec_context_t (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_import_sec_context_t (
               OM_uint32 *,            /* minor_status */
               const gss_buffer_t,     /* interprocess_token */
               gss_ctx_id_t *          /* context_handle */
              );
 
-typedef OM_uint32 _gss_inquire_names_for_mech_t (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_names_for_mech_t (
               OM_uint32 *,            /* minor_status */
               const gss_OID,          /* mechanism */
               gss_OID_set *           /* name_types */
              );
 
-typedef OM_uint32 _gss_inquire_mechs_for_name_t (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_mechs_for_name_t (
               OM_uint32 *,            /* minor_status */
               const gss_name_t,       /* input_name */
               gss_OID_set *           /* mech_types */
              );
 
-typedef OM_uint32 _gss_canonicalize_name_t (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_canonicalize_name_t (
               OM_uint32 *,            /* minor_status */
               const gss_name_t,       /* input_name */
               const gss_OID,          /* mech_type */
               gss_name_t *            /* output_name */
              );
 
-typedef OM_uint32 _gss_duplicate_name_t (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_duplicate_name_t (
               OM_uint32 *,            /* minor_status */
               const gss_name_t,       /* src_name */
               gss_name_t *            /* dest_name */
              );
 
-typedef OM_uint32 _gss_inquire_sec_context_by_oid (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_sec_context_by_oid (
               OM_uint32 *minor_status,
               const gss_ctx_id_t context_handle,
               const gss_OID desired_object,
               gss_buffer_set_t *data_set
              );
 
-typedef OM_uint32 _gss_inquire_cred_by_oid (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_inquire_cred_by_oid (
               OM_uint32 *minor_status,
               const gss_cred_id_t cred,
               const gss_OID desired_object,
               gss_buffer_set_t *data_set
              );
 
-typedef OM_uint32 _gss_set_sec_context_option (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_set_sec_context_option (
               OM_uint32 *minor_status,
               gss_ctx_id_t *cred_handle,
               const gss_OID desired_object,
               const gss_buffer_t value
              );
 
-typedef OM_uint32 _gss_set_cred_option (
+typedef OM_uint32 GSSAPI_CALLCONV _gss_set_cred_option (
               OM_uint32 *minor_status,
               gss_cred_id_t *cred_handle,
               const gss_OID desired_object,
@@ -298,7 +298,7 @@ typedef OM_uint32 _gss_set_cred_option (
              );
 
 
-typedef OM_uint32 _gss_pseudo_random(
+typedef OM_uint32 GSSAPI_CALLCONV _gss_pseudo_random(
               OM_uint32 *minor_status,
               gss_ctx_id_t context,
               int prf_key,
@@ -307,7 +307,7 @@ typedef OM_uint32 _gss_pseudo_random(
               gss_buffer_t prf_out
               );
 
-typedef OM_uint32
+typedef OM_uint32 GSSAPI_CALLCONV
 _gss_wrap_iov_t(OM_uint32 *minor_status,
                gss_ctx_id_t  context_handle,
                int conf_req_flag,
@@ -316,7 +316,7 @@ _gss_wrap_iov_t(OM_uint32 *minor_status,
                gss_iov_buffer_desc *iov,
                int iov_count);
 
-typedef OM_uint32
+typedef OM_uint32 GSSAPI_CALLCONV
 _gss_unwrap_iov_t(OM_uint32 *minor_status,
                  gss_ctx_id_t context_handle,
                  int *conf_state,
@@ -324,7 +324,7 @@ _gss_unwrap_iov_t(OM_uint32 *minor_status,
                  gss_iov_buffer_desc *iov,
                  int iov_count);
 
-typedef OM_uint32
+typedef OM_uint32 GSSAPI_CALLCONV
 _gss_wrap_iov_length_t(OM_uint32 * minor_status,
                       gss_ctx_id_t context_handle,
                       int conf_req_flag,
@@ -333,7 +333,7 @@ _gss_wrap_iov_length_t(OM_uint32 * minor_status,
                       gss_iov_buffer_desc *iov,
                       int iov_count);
 
-typedef OM_uint32
+typedef OM_uint32 GSSAPI_CALLCONV
 _gss_store_cred_t(OM_uint32         *minor_status,
                  gss_cred_id_t     input_cred_handle,
                  gss_cred_usage_t  cred_usage,
@@ -343,12 +343,12 @@ _gss_store_cred_t(OM_uint32         *minor_status,
                  gss_OID_set       *elements_stored,
                  gss_cred_usage_t  *cred_usage_stored);
 
-typedef OM_uint32
+typedef OM_uint32 GSSAPI_CALLCONV
 _gss_export_cred_t(OM_uint32 *minor_status,
                   gss_cred_id_t cred_handle,
                   gss_buffer_t cred_token);
 
-typedef OM_uint32
+typedef OM_uint32 GSSAPI_CALLCONV
 _gss_import_cred_t(OM_uint32 * minor_status,
                   gss_buffer_t cred_token,
                   gss_cred_id_t * cred_handle);
index 2c53d67003f0ff5d68fb78d18c192f9c2620afe9..65db343cad93aad5bb5ebba0fcddd50f24c7d5f6 100644 (file)
@@ -182,11 +182,6 @@ _gsskrb5_verify_8003_checksum(
     int DlgOpt;
     static unsigned char zeros[16];
 
-    if (cksum == NULL) {
-       *minor_status = 0;
-       return GSS_S_BAD_BINDINGS;
-    }
-
     /* XXX should handle checksums > 24 bytes */
     if(cksum->cksumtype != CKSUMTYPE_GSSAPI || cksum->checksum.length < 24) {
        *minor_status = 0;
index e3ba189b361091d779ca0db20f54472f1493a2b3..8ec3a65a31f1cb6ff03fd22130065c2a828307a6 100644 (file)
@@ -55,10 +55,10 @@ _gsskrb5_register_acceptor_identity (const char *identity)
     if (identity == NULL) {
        ret = krb5_kt_default(context, &_gsskrb5_keytab);
     } else {
-       char *p;
+       char *p = NULL;
 
-       asprintf(&p, "FILE:%s", identity);
-       if(p == NULL) {
+       ret = asprintf(&p, "FILE:%s", identity);
+       if(ret < 0 || p == NULL) {
            HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);
            return GSS_S_FAILURE;
        }
@@ -462,6 +462,7 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
     /*
      * We need to get the flags out of the 8003 checksum.
      */
+
     {
        krb5_authenticator authenticator;
 
@@ -474,6 +475,12 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
            return ret;
        }
 
+       if (authenticator->cksum == NULL) {
+           krb5_free_authenticator(context, &authenticator);
+           *minor_status = 0;
+           return GSS_S_BAD_BINDINGS;
+       }
+
         if (authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) {
             ret = _gsskrb5_verify_8003_checksum(minor_status,
                                                input_chan_bindings,
@@ -793,7 +800,7 @@ acceptor_wait_for_dcestyle(OM_uint32 * minor_status,
 }
 
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_accept_sec_context(OM_uint32 * minor_status,
                            gss_ctx_id_t * context_handle,
                            const gss_cred_id_t acceptor_cred_handle,
index 7e448dcfb2464fc1bdab917202f5b97a4319bbda..584ce7711aeca971a69a2dd10d6ef7ea8e5b8d13 100644 (file)
@@ -288,7 +288,7 @@ end:
     return (ret);
 }
 
-OM_uint32 _gsskrb5_acquire_cred
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred
 (OM_uint32 * minor_status,
  const gss_name_t desired_name,
  OM_uint32 time_req,
index adc8a09fa44502d85455eb7edc31586a7a1459f0..a326613eddf067a9755bbc3c81d8aac750ddd8a5 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_add_cred (
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_add_cred (
      OM_uint32           *minor_status,
      const gss_cred_id_t input_cred_handle,
      const gss_name_t    desired_name,
@@ -155,7 +155,7 @@ OM_uint32 _gsskrb5_add_cred (
 
        if (cred->ccache) {
            const char *type, *name;
-           char *type_name;
+           char *type_name = NULL;
 
            ret = GSS_S_FAILURE;
 
@@ -187,8 +187,8 @@ OM_uint32 _gsskrb5_add_cred (
                    goto failure;
                }
                
-               asprintf(&type_name, "%s:%s", type, name);
-               if (type_name == NULL) {
+               kret = asprintf(&type_name, "%s:%s", type, name);
+               if (kret < 0 || type_name == NULL) {
                    *minor_status = ENOMEM;
                    goto failure;
                }
index f1aee4bbbf6e3c075b8ac528944732311fe0ccf8..040cd3ee7686bcd779b149ae93b6c3a469d50809 100644 (file)
@@ -35,7 +35,7 @@
 
 #include <roken.h>
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gk_wrap_iov(OM_uint32 * minor_status,
             gss_ctx_id_t  context_handle,
             int conf_req_flag,
@@ -57,7 +57,7 @@ _gk_wrap_iov(OM_uint32 * minor_status,
     return GSS_S_FAILURE;
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gk_unwrap_iov(OM_uint32 *minor_status,
               gss_ctx_id_t context_handle,
               int *conf_state,
@@ -77,7 +77,7 @@ _gk_unwrap_iov(OM_uint32 *minor_status,
     return GSS_S_FAILURE;
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gk_wrap_iov_length(OM_uint32 * minor_status,
                    gss_ctx_id_t context_handle,
                    int conf_req_flag,
index 3de55d6e32b34a651d3efbc92a5ca217207862be..7fc921bac0958aa06a252ae22c186a0691b8d573 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_canonicalize_name (
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_canonicalize_name (
             OM_uint32 * minor_status,
             const gss_name_t input_name,
             const gss_OID mech_type,
index f45e4df3e2059306821433738b4e91ad12daf0c2..7409d45fcb8936b961066f760777fb1f9ca3e3bc 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_compare_name
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_compare_name
            (OM_uint32 * minor_status,
             const gss_name_t name1,
             const gss_name_t name2,
index 987ceea4aa99717d9c09e17f0e2d02a088df97d0..7b27906b5b12f6efb5ae5713b09ee540002b96e3 100644 (file)
@@ -62,7 +62,7 @@ _gsskrb5_lifetime_left(OM_uint32 *minor_status,
 }
 
 
-OM_uint32 _gsskrb5_context_time
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_context_time
            (OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
             OM_uint32 * time_rec
index fd406170403217197927e45e23d3d5e8e375edfe..d2c253e84bbedde24bd5cc4b48ccaca88faa55a1 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_export_cred(OM_uint32 *minor_status,
                     gss_cred_id_t cred_handle,
                     gss_buffer_t cred_token)
@@ -154,7 +154,7 @@ _gsskrb5_export_cred(OM_uint32 *minor_status,
     return GSS_S_COMPLETE;
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_import_cred(OM_uint32 * minor_status,
                     gss_buffer_t cred_token,
                     gss_cred_id_t * cred_handle)
index e02a4c6a9f6812ce7b5d66f0e9453bd2a0fc4163..83a66cc0ca01cdef0aeebea2319379014291cfdb 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_delete_sec_context(OM_uint32 * minor_status,
                            gss_ctx_id_t * context_handle,
                            gss_buffer_t output_token)
index 6487d8488033c707ba49e30f9e6d07c6347af4a1..a296399cecadb4cabd389c11cb1fea69a4835ba3 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_display_name
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_display_name
            (OM_uint32 * minor_status,
             const gss_name_t input_name,
             gss_buffer_t output_name_buffer,
index f9d84fc762843eee5fe21bbcb01e0b2ec50beb23..c50200672aafa770494b0bd323fa183c7b21fe16 100644 (file)
@@ -125,20 +125,21 @@ _gsskrb5_set_status (int ret, const char *fmt, ...)
     krb5_context context;
     va_list args;
     char *str;
+    int e;
 
     if (_gsskrb5_init (&context) != 0)
        return;
 
     va_start(args, fmt);
-    vasprintf(&str, fmt, args);
+    e = vasprintf(&str, fmt, args);
     va_end(args);
-    if (str) {
+    if (e >= 0 && str) {
        krb5_set_error_message(context, ret, "%s", str);
        free(str);
     }
 }
 
-OM_uint32 _gsskrb5_display_status
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_display_status
 (OM_uint32             *minor_status,
  OM_uint32              status_value,
  int                    status_type,
@@ -147,7 +148,8 @@ OM_uint32 _gsskrb5_display_status
  gss_buffer_t   status_string)
 {
     krb5_context context;
-    char *buf;
+    char *buf = NULL;
+    int e = 0;
 
     GSSAPI_KRB5_INIT (&context);
 
@@ -162,27 +164,27 @@ OM_uint32 _gsskrb5_display_status
 
     if (status_type == GSS_C_GSS_CODE) {
        if (GSS_SUPPLEMENTARY_INFO(status_value))
-           asprintf(&buf, "%s",
-                    supplementary_error(GSS_SUPPLEMENTARY_INFO(status_value)));
+           e = asprintf(&buf, "%s",
+                        supplementary_error(GSS_SUPPLEMENTARY_INFO(status_value)));
        else
-           asprintf (&buf, "%s %s",
-                     calling_error(GSS_CALLING_ERROR(status_value)),
-                     routine_error(GSS_ROUTINE_ERROR(status_value)));
+           e = asprintf (&buf, "%s %s",
+                         calling_error(GSS_CALLING_ERROR(status_value)),
+                         routine_error(GSS_ROUTINE_ERROR(status_value)));
     } else if (status_type == GSS_C_MECH_CODE) {
        const char *buf2 = krb5_get_error_message(context, status_value);
        if (buf2) {
            buf = strdup(buf2);
            krb5_free_error_message(context, buf2);
        } else {
-           asprintf(&buf, "unknown mech error-code %u",
-                    (unsigned)status_value);
+           e = asprintf(&buf, "unknown mech error-code %u",
+                        (unsigned)status_value);
        }
     } else {
        *minor_status = EINVAL;
        return GSS_S_BAD_STATUS;
     }
 
-    if (buf == NULL) {
+    if (e < 0 || buf == NULL) {
        *minor_status = ENOMEM;
        return GSS_S_FAILURE;
     }
index b0188acd517671b9b1a4b0de21d45fa195477694..0bc57e8a03edbd80955d3104d5bad1f35c30d8e9 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_duplicate_name (
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_duplicate_name (
             OM_uint32 * minor_status,
             const gss_name_t src_name,
             gss_name_t * dest_name
index 705bb70d91cb8decb8a88e9b68043268b10d4099..32368d3ccefd456ac75ee4ca976e2d54caf4d69a 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_export_name
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_export_name
            (OM_uint32  * minor_status,
             const gss_name_t input_name,
             gss_buffer_t exported_name
index 3d3870a6b45de0c4487a2037e4aa787433f451eb..eeb2743b4322db6c08fb7737b956495420bd0c33 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_export_sec_context (
     OM_uint32 * minor_status,
     gss_ctx_id_t * context_handle,
index fd81f3ebeb2b643f727a2e4b1ced47d7fa89ec70..ef33c5575a28f8a73476169141a184752ec4d8b1 100644 (file)
  * to that gss_OID_desc.
  */
 
-static gss_OID_desc gss_c_nt_user_name_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_user_name_oid_desc =
     {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x01")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_USER_NAME =
-    &gss_c_nt_user_name_oid_desc;
-
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
@@ -64,12 +61,9 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_USER_NAME =
  * initialized to point to that gss_OID_desc.
  */
 
-static gss_OID_desc gss_c_nt_machine_uid_name_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_machine_uid_name_oid_desc =
     {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x02")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_MACHINE_UID_NAME =
-    &gss_c_nt_machine_uid_name_oid_desc;
-
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
@@ -82,12 +76,9 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_MACHINE_UID_NAME =
  * initialized to point to that gss_OID_desc.
  */
 
-static gss_OID_desc gss_c_nt_string_uid_name_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_string_uid_name_oid_desc =
     {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x03")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_STRING_UID_NAME =
-    &gss_c_nt_string_uid_name_oid_desc;
-
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
@@ -106,12 +97,9 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_STRING_UID_NAME =
  * implementations
  */
 
-static gss_OID_desc gss_c_nt_hostbased_service_x_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_hostbased_service_x_oid_desc =
     {6, rk_UNCONST("\x2b\x06\x01\x05\x06\x02")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_HOSTBASED_SERVICE_X =
-    &gss_c_nt_hostbased_service_x_oid_desc;
-
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
@@ -123,12 +111,9 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_HOSTBASED_SERVICE_X =
  * GSS_C_NT_HOSTBASED_SERVICE should be initialized
  * to point to that gss_OID_desc.
  */
-static gss_OID_desc gss_c_nt_hostbased_service_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_hostbased_service_oid_desc =
     {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x04")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_HOSTBASED_SERVICE =
-    &gss_c_nt_hostbased_service_oid_desc;
-
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
@@ -140,12 +125,9 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_HOSTBASED_SERVICE =
  * to that gss_OID_desc.
  */
 
-static gss_OID_desc gss_c_nt_anonymous_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_anonymous_oid_desc =
     {6, rk_UNCONST("\x2b\x06\01\x05\x06\x03")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_ANONYMOUS =
-    &gss_c_nt_anonymous_oid_desc;
-
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
@@ -157,12 +139,9 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_ANONYMOUS =
  * to that gss_OID_desc.
  */
 
-static gss_OID_desc gss_c_nt_export_name_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_nt_export_name_oid_desc =
     {6, rk_UNCONST("\x2b\x06\x01\x05\x06\x04") };
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_EXPORT_NAME =
-    &gss_c_nt_export_name_oid_desc;
-
 /*
  *   This name form shall be represented by the Object Identifier {iso(1)
  *   member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
@@ -170,12 +149,9 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_C_NT_EXPORT_NAME =
  *   is "GSS_KRB5_NT_PRINCIPAL_NAME".
  */
 
-static gss_OID_desc gss_krb5_nt_principal_name_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_nt_principal_name_oid_desc =
     {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01") };
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_PRINCIPAL_NAME =
-    &gss_krb5_nt_principal_name_oid_desc;
-
 /*
  *   This name form shall be represented by the Object Identifier {iso(1)
  *   member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
@@ -183,9 +159,6 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_PRINCIPAL_NAME =
  *   type is "GSS_KRB5_NT_USER_NAME".
  */
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_USER_NAME =
-    &gss_c_nt_user_name_oid_desc;
-
 /*
  *   This name form shall be represented by the Object Identifier {iso(1)
  *   member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
@@ -193,9 +166,6 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_USER_NAME =
  *   this type is "GSS_KRB5_NT_MACHINE_UID_NAME".
  */
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_MACHINE_UID_NAME =
-    &gss_c_nt_machine_uid_name_oid_desc;
-
 /*
  *   This name form shall be represented by the Object Identifier {iso(1)
  *   member-body(2) United States(840) mit(113554) infosys(1) gssapi(2)
@@ -203,9 +173,6 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_MACHINE_UID_NAME =
  *   this type is "GSS_KRB5_NT_STRING_UID_NAME".
  */
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_STRING_UID_NAME =
-    &gss_c_nt_string_uid_name_oid_desc;
-
 /*
  *   To support ongoing experimentation, testing, and evolution of the
  *   specification, the Kerberos V5 GSS-API mechanism as defined in this
@@ -223,19 +190,9 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_NT_STRING_UID_NAME =
  *   gssapi(2) krb5(2)}
  */
 
-#if 0 /* This is the old OID */
-
-static gss_OID_desc gss_krb5_mechanism_oid_desc =
-    {5, rk_UNCONST("\x2b\x05\x01\x05\x02")};
-
-#endif
-
-static gss_OID_desc gss_krb5_mechanism_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_mechanism_oid_desc =
     {9, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") };
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_MECHANISM =
-    &gss_krb5_mechanism_oid_desc;
-
 /*
  * draft-ietf-cat-iakerb-09, IAKERB:
  *   The mechanism ID for IAKERB proxy GSS-API Kerberos, in accordance
@@ -249,179 +206,107 @@ gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_MECHANISM =
  *   iakerbMinimumMessagesProtocol(2)}.
  */
 
-static gss_OID_desc gss_iakerb_proxy_mechanism_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE  __gss_iakerb_proxy_mechanism_oid_desc =
     {7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0a\x01")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_IAKERB_PROXY_MECHANISM =
-    &gss_iakerb_proxy_mechanism_oid_desc;
-
-static gss_OID_desc gss_iakerb_min_msg_mechanism_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_iakerb_min_msg_mechanism_oid_desc =
     {7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0a\x02") };
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_IAKERB_MIN_MSG_MECHANISM =
-    &gss_iakerb_min_msg_mechanism_oid_desc;
-
 /*
  *
  */
 
-static gss_OID_desc gss_c_peer_has_updated_spnego_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_peer_has_updated_spnego_oid_desc =
     {9, (void *)"\x2b\x06\x01\x04\x01\xa9\x4a\x13\x05"};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_C_PEER_HAS_UPDATED_SPNEGO =
-    &gss_c_peer_has_updated_spnego_oid_desc;
-
 /*
  * 1.2.752.43.13 Heimdal GSS-API Extentions
  */
 
 /* 1.2.752.43.13.1 */
-static gss_OID_desc gss_krb5_copy_ccache_x_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_copy_ccache_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x01")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_COPY_CCACHE_X =
-    &gss_krb5_copy_ccache_x_oid_desc;
-
 /* 1.2.752.43.13.2 */
-static gss_OID_desc gss_krb5_get_tkt_flags_x_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_tkt_flags_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x02")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_TKT_FLAGS_X =
-    &gss_krb5_get_tkt_flags_x_oid_desc;
-
 /* 1.2.752.43.13.3 */
-static gss_OID_desc gss_krb5_extract_authz_data_from_sec_context_x_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_extract_authz_data_from_sec_context_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x03")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X =
-    &gss_krb5_extract_authz_data_from_sec_context_x_oid_desc;
-
 /* 1.2.752.43.13.4 */
-static gss_OID_desc gss_krb5_compat_des3_mic_x_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_compat_des3_mic_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x04")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_COMPAT_DES3_MIC_X =
-    &gss_krb5_compat_des3_mic_x_oid_desc;
-
 /* 1.2.752.43.13.5 */
-static gss_OID_desc gss_krb5_register_acceptor_identity_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_register_acceptor_identity_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x05")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X =
-    &gss_krb5_register_acceptor_identity_x_desc;
-
 /* 1.2.752.43.13.6 */
-static gss_OID_desc gss_krb5_export_lucid_context_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_export_lucid_context_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x06")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_EXPORT_LUCID_CONTEXT_X =
-    &gss_krb5_export_lucid_context_x_desc;
-
 /* 1.2.752.43.13.6.1 */
-static gss_OID_desc gss_krb5_export_lucid_context_v1_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_export_lucid_context_v1_x_oid_desc =
     {7, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x06\x01")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X =
-    &gss_krb5_export_lucid_context_v1_x_desc;
-
 /* 1.2.752.43.13.7 */
-static gss_OID_desc gss_krb5_set_dns_canonicalize_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_set_dns_canonicalize_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x07")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_SET_DNS_CANONICALIZE_X =
-    &gss_krb5_set_dns_canonicalize_x_desc;
-
 /* 1.2.752.43.13.8 */
-static gss_OID_desc gss_krb5_get_subkey_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_subkey_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x08")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_SUBKEY_X =
-    &gss_krb5_get_subkey_x_desc;
-
 /* 1.2.752.43.13.9 */
-static gss_OID_desc gss_krb5_get_initiator_subkey_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_initiator_subkey_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x09")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_INITIATOR_SUBKEY_X =
-    &gss_krb5_get_initiator_subkey_x_desc;
-
 /* 1.2.752.43.13.10 */
-static gss_OID_desc gss_krb5_get_acceptor_subkey_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_acceptor_subkey_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0a")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_ACCEPTOR_SUBKEY_X =
-    &gss_krb5_get_acceptor_subkey_x_desc;
-
 /* 1.2.752.43.13.11 */
-static gss_OID_desc gss_krb5_send_to_kdc_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_send_to_kdc_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0b")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_SEND_TO_KDC_X =
-    &gss_krb5_send_to_kdc_x_desc;
-
 /* 1.2.752.43.13.12 */
-static gss_OID_desc gss_krb5_get_authtime_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_authtime_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0c")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_AUTHTIME_X =
-    &gss_krb5_get_authtime_x_desc;
-
 /* 1.2.752.43.13.13 */
-static gss_OID_desc gss_krb5_get_service_keyblock_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_service_keyblock_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0d")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_SERVICE_KEYBLOCK_X =
-    &gss_krb5_get_service_keyblock_x_desc;
-
 /* 1.2.752.43.13.14 */
-static gss_OID_desc gss_krb5_set_allowable_enctypes_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_set_allowable_enctypes_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0e")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X =
-    &gss_krb5_set_allowable_enctypes_x_desc;
-
 /* 1.2.752.43.13.15 */
-static gss_OID_desc gss_krb5_set_default_realm_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_set_default_realm_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0f")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_SET_DEFAULT_REALM_X =
-    &gss_krb5_set_default_realm_x_desc;
-
 /* 1.2.752.43.13.16 */
-static gss_OID_desc gss_krb5_ccache_name_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_ccache_name_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x10")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_CCACHE_NAME_X =
-    &gss_krb5_ccache_name_x_desc;
-
 /* 1.2.752.43.13.17 */
-static gss_OID_desc gss_krb5_set_time_offset_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_set_time_offset_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x11")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_SET_TIME_OFFSET_X =
-    &gss_krb5_set_time_offset_x_desc;
-
 /* 1.2.752.43.13.18 */
-static gss_OID_desc gss_krb5_get_time_offset_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_get_time_offset_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x12")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_GET_TIME_OFFSET_X =
-    &gss_krb5_get_time_offset_x_desc;
-
 /* 1.2.752.43.13.19 */
-static gss_OID_desc gss_krb5_plugin_register_x_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_plugin_register_x_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x13")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_KRB5_PLUGIN_REGISTER_X =
-    &gss_krb5_plugin_register_x_desc;
-
 /* 1.2.752.43.14.1 */
-static gss_OID_desc gss_sasl_digest_md5_mechanism_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_sasl_digest_md5_mechanism_oid_desc =
     {6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x01") };
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_SASL_DIGEST_MD5_MECHANISM =
-    &gss_sasl_digest_md5_mechanism_desc;
-
 /*
  * Context for krb5 calls.
  */
index f3f7fff8ae5f9fc96329d66fa3322a5114d23a7a..0109ca7c6e76d90e8d229d2069228bc9fe978db4 100644 (file)
@@ -273,7 +273,7 @@ mic_des3
   return GSS_S_COMPLETE;
 }
 
-OM_uint32 _gsskrb5_get_mic
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_get_mic
            (OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
             gss_qop_t qop_req,
index f1aca93ffda479b940e97d231d895837b4c06a24..2a071a305efc8f9c88449687e577035a47c40713 100644 (file)
@@ -215,7 +215,7 @@ import_export_name (OM_uint32 *minor_status,
     return ret;
 }
 
-OM_uint32 _gsskrb5_import_name
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_import_name
            (OM_uint32 * minor_status,
             const gss_buffer_t input_name_buffer,
             const gss_OID input_name_type,
@@ -235,7 +235,7 @@ OM_uint32 _gsskrb5_import_name
                                      context,
                                      input_name_buffer,
                                      output_name);
-    else if (gss_oid_equal(input_name_type, GSS_C_NO_OID)
+    else if (input_name_type == GSS_C_NO_OID
             || gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME)
             || gss_oid_equal(input_name_type, GSS_KRB5_NT_PRINCIPAL_NAME))
        /* default printable syntax */
index 2af942338fb0f8ab2c5f2868900f9ed960609579..c873da9ba9d16f80ffa96845fae544a44e565948 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_import_sec_context (
     OM_uint32 * minor_status,
     const gss_buffer_t interprocess_token,
index b1d18bd244c9c5df0915526ec0ead588f16e4c7b..620137884ae49321c583d61fab2243a350c0bbb6 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_indicate_mechs
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_indicate_mechs
            (OM_uint32 * minor_status,
             gss_OID_set * mech_set
            )
index b513bd2d65a36e060c4df8e4cfa0e83854996d50..f4e103a7a5163a9cd209a54e328d5ad2933bed5e 100644 (file)
@@ -838,7 +838,7 @@ repl_mutual
  * gss_init_sec_context
  */
 
-OM_uint32 _gsskrb5_init_sec_context
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_init_sec_context
 (OM_uint32 * minor_status,
  const gss_cred_id_t cred_handle,
  gss_ctx_id_t * context_handle,
index 381ffc9e6f6bdb9572b7e8be68b737f7574df184..ade8ec4b9cb6e5c689ed18e1ad7952d86979bb90 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_inquire_context (
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_context (
     OM_uint32 * minor_status,
        const gss_ctx_id_t context_handle,
        gss_name_t * src_name,
index 518736d78e4142a90763dc064c548b3121075635..d3798623ff3fceaa091515983da5a1807f1a1362 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_inquire_cred
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred
 (OM_uint32 * minor_status,
  const gss_cred_id_t cred_handle,
  gss_name_t * output_name,
index 9da1ac43f181a13e21f73ffd40fbd899921af2eb..7bd9c11c60563aeef39bbfa1f7932aaf67730e54 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_inquire_cred_by_mech (
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred_by_mech (
     OM_uint32 * minor_status,
        const gss_cred_id_t cred_handle,
        const gss_OID mech_type,
index f32342f1d860993846c6e8fa699688249b14ed48..d560ed4ba1c60be28e3c8bcdd9b9726cd25a812f 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_inquire_cred_by_oid
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred_by_oid
           (OM_uint32 * minor_status,
            const gss_cred_id_t cred_handle,
            const gss_OID desired_object,
index 5fa3c302a28004209f6209ff8832caff3dc8edf6..6197a81b40a7efde4f5a5b56347b1bac0b958126 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_inquire_mechs_for_name (
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_mechs_for_name (
             OM_uint32 * minor_status,
             const gss_name_t input_name,
             gss_OID_set * mech_types
index 591343307e48d5c60764184053daf569fa67a4a5..dc02b99851a31ce8da8182b8637062f6a3343822 100644 (file)
 
 #include "gsskrb5_locl.h"
 
-static gss_OID *name_list[] = {
-    &GSS_C_NT_HOSTBASED_SERVICE,
-    &GSS_C_NT_USER_NAME,
-    &GSS_KRB5_NT_PRINCIPAL_NAME,
-    &GSS_C_NT_EXPORT_NAME,
+static gss_OID name_list[] = {
+    GSS_C_NT_HOSTBASED_SERVICE,
+    GSS_C_NT_USER_NAME,
+    GSS_KRB5_NT_PRINCIPAL_NAME,
+    GSS_C_NT_EXPORT_NAME,
     NULL
 };
 
-OM_uint32 _gsskrb5_inquire_names_for_mech (
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_names_for_mech (
             OM_uint32 * minor_status,
             const gss_OID mechanism,
             gss_OID_set * name_types
@@ -64,7 +64,7 @@ OM_uint32 _gsskrb5_inquire_names_for_mech (
 
     for (i = 0; name_list[i] != NULL; i++) {
        ret = gss_add_oid_set_member(minor_status,
-                                    *(name_list[i]),
+                                    name_list[i],
                                     name_types);
        if (ret != GSS_S_COMPLETE)
            break;
index e0b5553928a43cbb2c35588d57c1388306943713..14816e7a056f216af969aef3340a22413a0e75c3 100644 (file)
@@ -487,7 +487,7 @@ out:
  *
  */
 
-OM_uint32 _gsskrb5_inquire_sec_context_by_oid
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_sec_context_by_oid
            (OM_uint32 *minor_status,
             const gss_ctx_id_t context_handle,
             const gss_OID desired_object,
index 737ccb68345de482651b783cefb89b8130580417..323b4cc722962bc24fe7e15c8294981c3af313d5 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_pseudo_random(OM_uint32 *minor_status,
                       gss_ctx_id_t context_handle,
                       int prf_key,
index 1c9d44588fdea93e5af509c9e71f51bcbee0fe43..4feda0de04a4892807510c854c58c9b1a63de586 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_process_context_token (
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_process_context_token (
        OM_uint32          *minor_status,
        const gss_ctx_id_t context_handle,
        const gss_buffer_t token_buffer
index 5eec3c48cbd89065b3d3950e5a4be0ea4d2ce55c..105a7a6eb223d2091f9c8b4815721b51799ae3cf 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_release_cred
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_release_cred
            (OM_uint32 * minor_status,
             gss_cred_id_t * cred_handle
            )
index 0fafc275d0675aa57b472e49c605b2edab618973..57fc8a4e45eb428ecd432486fe43ac2f46e71597 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32 _gsskrb5_release_name
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_release_name
            (OM_uint32 * minor_status,
             gss_name_t * input_name
            )
index ee29bf8c66d9c762f75d2d4f859fb5f128d5d461..d6255bacb5eee1f5a01662ca49a1fc7eaab2ed6f 100644 (file)
 #include "gsskrb5_locl.h"
 
 /* 1.2.752.43.13.17 */
-static gss_OID_desc gss_krb5_cred_no_ci_flags_x_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_cred_no_ci_flags_x_oid_desc =
 {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x11")};
 
-gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X = &gss_krb5_cred_no_ci_flags_x_oid_desc;
-
 /* 1.2.752.43.13.18 */
-static gss_OID_desc gss_krb5_import_cred_x_oid_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_krb5_import_cred_x_oid_desc =
 {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x12")};
 
-gss_OID GSS_KRB5_IMPORT_CRED_X = &gss_krb5_import_cred_x_oid_desc;
-
-
 
 static OM_uint32
 import_cred(OM_uint32 *minor_status,
@@ -230,7 +225,7 @@ no_ci_flags(OM_uint32 *minor_status,
 }
 
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_set_cred_option
            (OM_uint32 *minor_status,
             gss_cred_id_t *cred_handle,
index 096e83504530aedc2aeffb705d1cec2b0ce592df..237af1a52c87e48f94f8494dffe4cb16f56f2e42 100644 (file)
@@ -98,7 +98,7 @@ set_int32(OM_uint32 *minor_status,
     return GSS_S_COMPLETE;
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_set_sec_context_option
            (OM_uint32 *minor_status,
             gss_ctx_id_t *context_handle,
index 675a1d8e9518301b6af65ac9def9813ebadef256..21f9f6e8aba847d60aa1520b2332d0cd64953108 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "gsskrb5_locl.h"
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_store_cred(OM_uint32         *minor_status,
                    gss_cred_id_t     input_cred_handle,
                    gss_cred_usage_t  cred_usage,
index 5e0042e28b6b7ddaa1f7e7dcf5c4ae6885ba6e2f..7620d691bda6f030105bea25b7fd3e65d3934967 100644 (file)
@@ -379,7 +379,7 @@ unwrap_des3
   return GSS_S_COMPLETE;
 }
 
-OM_uint32 _gsskrb5_unwrap
+OM_uint32 GSSAPI_CALLCONV _gsskrb5_unwrap
            (OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
             const gss_buffer_t input_message_buffer,
index 0b5b6e1ccd852bf751e4c5b818e4187f85647c81..9a5445698bc1eca2718e4f9ee07fb7f4ddbc8f55 100644 (file)
@@ -327,7 +327,7 @@ _gsskrb5_verify_mic_internal
     return ret;
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_verify_mic
            (OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
index 9078fb3dd78627f85cd67bc9d7d9ce58b8257f31..54f92df609930ffd0d662a853f0a59a7e7139b56 100644 (file)
@@ -134,7 +134,7 @@ sub_wrap_size (
     return GSS_S_COMPLETE;
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gsskrb5_wrap_size_limit (
             OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
@@ -524,7 +524,8 @@ wrap_des3
   return GSS_S_COMPLETE;
 }
 
-OM_uint32 _gsskrb5_wrap
+OM_uint32 GSSAPI_CALLCONV
+_gsskrb5_wrap
            (OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
             int conf_req_flag,
index 5775db837b4ba0d44215d4584d8acbd7aadd5104..19f3bc4bf84be10ccdcad68219071c40e5bd717a 100644 (file)
@@ -141,7 +141,8 @@ choose_mech(const gss_buffer_t input, gss_OID mech_oid)
 }
 
 
-OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status,
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
+gss_accept_sec_context(OM_uint32 *minor_status,
     gss_ctx_id_t *context_handle,
     const gss_cred_id_t acceptor_cred_handle,
     const gss_buffer_t input_token,
index 75a7978d895064bed341be7c5745260e97749838..416407a7bfe7efdb47407d4f876ab30fab37e930 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_acquire_cred(OM_uint32 *minor_status,
     const gss_name_t desired_name,
     OM_uint32 time_req,
index 08c78827841eaa7982f2eb2752c96ed2e9046a44..56fb8ec6a9eccb714d2332034dc6bb4d81aff615 100644 (file)
@@ -70,7 +70,7 @@ _gss_copy_cred(struct _gss_mechanism_cred *mc)
        return (new_mc);
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_add_cred(OM_uint32 *minor_status,
     const gss_cred_id_t input_cred_handle,
     const gss_name_t desired_name,
index b866125291bb6e2204b3c4c61990f7be64efc601..191a4a305cb930dca838f7784706877f88bd6ba3 100644 (file)
@@ -51,7 +51,7 @@
  * @ingroup gssapi
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_add_oid_set_member (OM_uint32 * minor_status,
                        const gss_OID member_oid,
                        gss_OID_set * oid_set)
index ee0113d6d3c494e4abcbfa33dff1095c9bb456b3..e98ba970d1a040e2bd0f561b29d8f209beda325d 100644 (file)
@@ -43,7 +43,7 @@
  */
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_wrap_iov(OM_uint32 * minor_status,
             gss_ctx_id_t  context_handle,
             int conf_req_flag,
@@ -81,7 +81,7 @@ gss_wrap_iov(OM_uint32 * minor_status,
  * @ingroup gssapi
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_unwrap_iov(OM_uint32 *minor_status,
               gss_ctx_id_t context_handle,
               int *conf_state,
@@ -124,7 +124,7 @@ gss_unwrap_iov(OM_uint32 *minor_status,
  * @ingroup gssapi
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_wrap_iov_length(OM_uint32 * minor_status,
                    gss_ctx_id_t context_handle,
                    int conf_req_flag,
@@ -162,7 +162,7 @@ gss_wrap_iov_length(OM_uint32 * minor_status,
  * @ingroup gssapi
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_release_iov_buffer(OM_uint32 *minor_status,
                       gss_iov_buffer_desc *iov,
                       int iov_count)
@@ -194,13 +194,10 @@ gss_release_iov_buffer(OM_uint32 *minor_status,
  * @ingroup gssapi
  */
 
-static gss_OID_desc gss_c_attr_stream_sizes_desc =
+gss_OID_desc GSSAPI_LIB_FUNCTION __gss_c_attr_stream_sizes_oid_desc =
     {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03")};
 
-gss_OID GSSAPI_LIB_VARIABLE GSS_C_ATTR_STREAM_SIZES =
-    &gss_c_attr_stream_sizes_desc;
-
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_context_query_attributes(OM_uint32 *minor_status,
                             const gss_ctx_id_t context_handle,
                             const gss_OID attribute,
index 58863c311294c7787206fac96b896d39b5480aa0..3099b163b5170d171b886e9c3d7d9c893b44f6ce 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_create_empty_buffer_set
           (OM_uint32 * minor_status,
            gss_buffer_set_t *buffer_set)
@@ -54,7 +54,7 @@ gss_create_empty_buffer_set
     return GSS_S_COMPLETE;
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_add_buffer_set_member
           (OM_uint32 * minor_status,
            const gss_buffer_t member_buffer,
@@ -96,7 +96,7 @@ gss_add_buffer_set_member
     return GSS_S_COMPLETE;
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_release_buffer_set(OM_uint32 * minor_status,
                       gss_buffer_set_t *buffer_set)
 {
index 1bb94b346883dcad789bf0cd5daad3fcb345c513..fba35c5379b59ffe1318a738e689b839d41d7e08 100644 (file)
@@ -52,7 +52,7 @@
  *  @ingroup gssapi
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_canonicalize_name(OM_uint32 *minor_status,
     const gss_name_t input_name,
     const gss_OID mech_type,
index 9481218de2e284de1fdfa4cbc44349c86a35715d..14593f6def8898ea37a4290fd59cc6815792003a 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_compare_name(OM_uint32 *minor_status,
     const gss_name_t name1_arg,
     const gss_name_t name2_arg,
index d99f71f77a2a0c9e6a097dd44f930b0caf8e869d..69434ee898e5e7be08af0c87ee591578503167e2 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_context_time(OM_uint32 *minor_status,
     const gss_ctx_id_t context_handle,
     OM_uint32 *time_rec)
index 36337a5435f468939cec9f17ef0a9cf8dc142e8c..8d880f5511610ffd3670111f4215f2ef7c6ac472 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_create_empty_oid_set(OM_uint32 *minor_status,
     gss_OID_set *oid_set)
 {
index 66df50b55e7d7f8c2a156d666188db73d12f627b..b52015b6de44a3d29d8b665186fd5a288e2dc5d4 100644 (file)
@@ -42,7 +42,7 @@
  *     cred-data char * (not alligned)
 */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_export_cred(OM_uint32 * minor_status,
                gss_cred_id_t cred_handle,
                gss_buffer_t token)
@@ -107,7 +107,7 @@ gss_export_cred(OM_uint32 * minor_status,
     return GSS_S_COMPLETE;
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_import_cred(OM_uint32 * minor_status,
                gss_buffer_t token,
                gss_cred_id_t * cred_handle)
index 95a6c68445f81a88babf3453a57e739f203b48ec..0fe3b4f5a5743786999b56701ef8d554adbbb37e 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_decapsulate_token(const gss_buffer_t input_token,
                      const gss_OID oid,
                      gss_buffer_t output_token)
index c2575927c37a0c8038228763018d701f8c5b7524..ce57a76682ab306670a2932e203749d3744918c1 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_delete_sec_context(OM_uint32 *minor_status,
     gss_ctx_id_t *context_handle,
     gss_buffer_t output_token)
index 0b7559224619c980814252f7b6f6b5e8d84cfc21..599e79861a7a3fb99ae3231bf44e31ec849aa025 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_display_name(OM_uint32 *minor_status,
     const gss_name_t input_name,
     gss_buffer_t output_name_buffer,
index 60c5b8f5234b29b37d3aa5aac54b36cf116e04fb..d6aaf98827acd79e0bbdf6b35a2d0ff46ba40cad 100644 (file)
@@ -135,7 +135,7 @@ supplementary_error(OM_uint32 v)
 }
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_display_status(OM_uint32 *minor_status,
     OM_uint32 status_value,
     int status_type,
@@ -160,17 +160,18 @@ gss_display_status(OM_uint32 *minor_status,
        *minor_status = 0;
        switch (status_type) {
        case GSS_C_GSS_CODE: {
-               char *buf;
+               char *buf = NULL;
+               int e;
 
                if (GSS_SUPPLEMENTARY_INFO(status_value))
-                   asprintf(&buf, "%s", supplementary_error(
+                   e = asprintf(&buf, "%s", supplementary_error(
                        GSS_SUPPLEMENTARY_INFO(status_value)));
                else
-                   asprintf (&buf, "%s %s",
+                   e = asprintf (&buf, "%s %s",
                        calling_error(GSS_CALLING_ERROR(status_value)),
                        routine_error(GSS_ROUTINE_ERROR(status_value)));
 
-               if (buf == NULL)
+               if (e < 0 || buf == NULL)
                    break;
 
                status_string->length = strlen(buf);
@@ -181,21 +182,22 @@ gss_display_status(OM_uint32 *minor_status,
        case GSS_C_MECH_CODE: {
                OM_uint32 maj_junk, min_junk;
                gss_buffer_desc oid;
-               char *buf;
+               char *buf = NULL;
+               int e;
 
                maj_junk = gss_oid_to_str(&min_junk, mech_type, &oid);
                if (maj_junk != GSS_S_COMPLETE) {
                    oid.value = rk_UNCONST("unknown");
                    oid.length = 7;
                }
-
-               asprintf (&buf, "unknown mech-code %lu for mech %.*s",
+               
+               e = asprintf (&buf, "unknown mech-code %lu for mech %.*s",
                          (unsigned long)status_value,
                          (int)oid.length, (char *)oid.value);
                if (maj_junk == GSS_S_COMPLETE)
                    gss_release_buffer(&min_junk, &oid);
 
-               if (buf == NULL)
+               if (e < 0 || buf == NULL)
                    break;
 
                status_string->length = strlen(buf);
index 87775878efa5bf58d9a1a6afcfe7bc615f7f0125..3d3a56802f53e0edb2b4e2f78ce26b29ddf5ad86 100644 (file)
@@ -28,7 +28,8 @@
 
 #include "mech_locl.h"
 
-OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
+gss_duplicate_name(OM_uint32 *minor_status,
     const gss_name_t src_name,
     gss_name_t *dest_name)
 {
index 165b07e5ae13618f36d1a1cb92fee78ff4f35308..10a200048690168687f23c4844c40661d97cd37c 100644 (file)
@@ -33,7 +33,8 @@
 
 #include "mech_locl.h"
 
-OM_uint32 gss_duplicate_oid (
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
+gss_duplicate_oid (
         OM_uint32 *minor_status,
        gss_OID src_oid,
        gss_OID *dest_oid
index 7a3e165364f062bb3236ef6d745ff501d6b6383e..fc0ec736bbdad16beb77778aefbf458629737e57 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_encapsulate_token(const gss_buffer_t input_token,
                      const gss_OID oid,
                      gss_buffer_t output_token)
index 7f7c1afe685a5f71f9dd1a6b65889f83d3614962..6bc5ee8d1cb85b50eaf40700fe2871c7f54c2f5d 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_export_name(OM_uint32 *minor_status,
     const gss_name_t input_name,
     gss_buffer_t exported_name)
index 0fc19e2af735f9c0e703f8434255652caa7f8865..babc8ebdf48a9be99dc764bbe1e0d046621117c9 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_export_sec_context(OM_uint32 *minor_status,
     gss_ctx_id_t *context_handle,
     gss_buffer_t interprocess_token)
index f4921b60db40b892c377d7d6482b82d449e72456..6eebfe0bbb03d276ea18ff06b7b58197d9b56541 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_get_mic(OM_uint32 *minor_status,
     const gss_ctx_id_t context_handle,
     gss_qop_t qop_req,
index 6ae2302abd90e1b4bef46094316cc7a9f8cd52b0..90dc0c1e9416048f160362c15cf7a9af70821a9e 100644 (file)
@@ -163,7 +163,7 @@ _gss_import_export_name(OM_uint32 *minor_status,
  * @ingroup gssapi
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_import_name(OM_uint32 *minor_status,
     const gss_buffer_t input_name_buffer,
     const gss_OID input_name_type,
index e08d3b7af4c49aabb9bb8c74465c5a7879cb30df..2a376fefeaeacf7ac83c41e3d3f46de9ae5b707f 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_import_sec_context(OM_uint32 *minor_status,
     const gss_buffer_t interprocess_token,
     gss_ctx_id_t *context_handle)
index ab95a18ee6822811c39d3f1a33d310e868618ca6..8560bc7c4110a3a34f249bfe998e6daad8ac8b55 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_indicate_mechs(OM_uint32 *minor_status,
     gss_OID_set *mech_set)
 {
index 1bcc6393452385fbaf2b972a3f0bb848b4408591..5da035d15a70d3af286b4332eafb02e92e352b8d 100644 (file)
@@ -55,6 +55,10 @@ _gss_mech_cred_find(gss_cred_id_t cred_handle, gss_OID mech_type)
  *
  * @param minor_status minor status code.
  *
+ * @param initiator_cred_handle the credential to use when building
+ *        the context, if GSS_C_NO_CREDENTIAL is passed, the default
+ *        credential for the mechanism will be used.
+ *
  * @param context_handle a pointer to a context handle, will be
  *       returned as long as there is not an error.
  *
@@ -69,7 +73,7 @@ _gss_mech_cred_find(gss_cred_id_t cred_handle, gss_OID mech_type)
  *        section.
  *
  * @param req_flags flags using when building the context, see @ref
- *        gssapi_context_ flags
+ *        gssapi_context_flags
  *
  * @param time_req time requested this context should be valid in
  *        seconds, common used value is GSS_C_INDEFINITE
@@ -101,7 +105,7 @@ _gss_mech_cred_find(gss_cred_id_t cred_handle, gss_OID mech_type)
 
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_init_sec_context(OM_uint32 * minor_status,
     const gss_cred_id_t initiator_cred_handle,
     gss_ctx_id_t * context_handle,
index e000af00ef5a9039f8a24cbf4f2df7a2c839acf6..0658267b2fb6dcf5ce01038628a4d51093c4fadc 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_inquire_context(OM_uint32 *minor_status,
     const gss_ctx_id_t context_handle,
     gss_name_t *src_name,
index e5faf587642be86e7229509623c6f32e239d8eb1..50d9c0b8da939b1fa2b87def2e581d4588124ca4 100644 (file)
@@ -42,7 +42,7 @@ updateusage(gss_cred_usage_t usage, int *usagemask)
        *usagemask |= IUSAGE;
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_inquire_cred(OM_uint32 *minor_status,
     const gss_cred_id_t cred_handle,
     gss_name_t *name_ret,
index 39c5e711b72562a932ed16e4387c4eb5bd760b4a..f71bd6993f85b85be703ab11421652e9d60e1a93 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_inquire_cred_by_mech(OM_uint32 *minor_status,
     const gss_cred_id_t cred_handle,
     const gss_OID mech_type,
index 3b821ce823d666f8832eb4eac0ae93af0d4f8739..72d30480398602fd2c6d042b62fb62f4e70e140b 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_inquire_cred_by_oid (OM_uint32 *minor_status,
                         const gss_cred_id_t cred_handle,
                         const gss_OID desired_object,
index f0e23e664a40ea33b436e7d9661bac0a28a3018f..1ad7b58dbb69d69130e685e12850562333cbb9f6 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_inquire_mechs_for_name(OM_uint32 *minor_status,
     const gss_name_t input_name,
     gss_OID_set *mech_types)
index c796f0522763e95644129e8eda7526b56286534e..595ab737f967e073d324f0a57b41aafd12a7aa7a 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_inquire_names_for_mech(OM_uint32 *minor_status,
     const gss_OID mechanism,
     gss_OID_set *name_types)
index ffa0c44fa3b73aba2d45818a2dd9f19ca14135ec..cc6e5c9cb6e2c3592093fe55779e3a427e74b8c8 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,
                                const gss_ctx_id_t context_handle,
                                const gss_OID desired_object,
index 1611d91d02625802855065847af9520b801e8e86..f4290a2a5a982f88c8b6353a3e2cb332dfeb55fa 100644 (file)
@@ -32,7 +32,7 @@
 #include <roken.h>
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_copy_ccache(OM_uint32 *minor_status,
                     gss_cred_id_t cred,
                     krb5_ccache out)
@@ -42,7 +42,7 @@ gss_krb5_copy_ccache(OM_uint32 *minor_status,
     krb5_error_code kret;
     krb5_ccache id;
     OM_uint32 ret;
-    char *str;
+    char *str = NULL;
 
     ret = gss_inquire_cred_by_oid(minor_status,
                                  cred,
@@ -67,7 +67,7 @@ gss_krb5_copy_ccache(OM_uint32 *minor_status,
     kret = asprintf(&str, "%.*s", (int)data_set->elements[0].length,
                    (char *)data_set->elements[0].value);
     gss_release_buffer_set(minor_status, &data_set);
-    if (kret == -1) {
+    if (kret < 0 || str == NULL) {
        *minor_status = ENOMEM;
        return GSS_S_FAILURE;
     }
@@ -90,7 +90,7 @@ gss_krb5_copy_ccache(OM_uint32 *minor_status,
     return ret;
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_import_cred(OM_uint32 *minor_status,
                     krb5_ccache id,
                     krb5_principal keytab_principal,
@@ -185,7 +185,7 @@ out:
     return major_status;
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_register_acceptor_identity(const char *identity)
 {
         struct _gss_mech_switch        *m;
@@ -207,14 +207,14 @@ gsskrb5_register_acceptor_identity(const char *identity)
        return (GSS_S_COMPLETE);
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 krb5_gss_register_acceptor_identity(const char *identity)
 {
     return gsskrb5_register_acceptor_identity(identity);
 }
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_set_dns_canonicalize(int flag)
 {
         struct _gss_mech_switch        *m;
@@ -259,7 +259,7 @@ free_key(gss_krb5_lucid_key_t *key)
     memset(key, 0, sizeof(*key));
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
                                  gss_ctx_id_t *context_handle,
                                  OM_uint32 version,
@@ -402,7 +402,7 @@ out:
     return GSS_S_COMPLETE;
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *c)
 {
     gss_krb5_lucid_context_v1_t *ctx = c;
@@ -430,7 +430,7 @@ gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *c)
  *
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status,
                                gss_cred_id_t cred,
                                OM_uint32 num_enctypes,
@@ -484,7 +484,7 @@ out:
  *
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c)
 {
     struct _gss_mech_switch *m;
@@ -515,7 +515,7 @@ gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c)
  *
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_ccache_name(OM_uint32 *minor_status,
                     const char *name,
                     const char **out_name)
@@ -547,7 +547,7 @@ gss_krb5_ccache_name(OM_uint32 *minor_status,
  *
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status,
                                          gss_ctx_id_t context_handle,
                                          time_t *authtime)
@@ -602,7 +602,7 @@ gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status,
  *
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
                                            gss_ctx_id_t context_handle,
                                            int ad_type,
@@ -775,7 +775,7 @@ out:
  *
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_extract_service_keyblock(OM_uint32 *minor_status,
                                 gss_ctx_id_t context_handle,
                                 krb5_keyblock **keyblock)
@@ -786,7 +786,7 @@ gsskrb5_extract_service_keyblock(OM_uint32 *minor_status,
                               keyblock);
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_get_initiator_subkey(OM_uint32 *minor_status,
                             gss_ctx_id_t context_handle,
                             krb5_keyblock **keyblock)
@@ -797,7 +797,7 @@ gsskrb5_get_initiator_subkey(OM_uint32 *minor_status,
                               keyblock);
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_get_subkey(OM_uint32 *minor_status,
                   gss_ctx_id_t context_handle,
                   krb5_keyblock **keyblock)
@@ -808,7 +808,7 @@ gsskrb5_get_subkey(OM_uint32 *minor_status,
                               keyblock);
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_set_default_realm(const char *realm)
 {
         struct _gss_mech_switch        *m;
@@ -830,7 +830,7 @@ gsskrb5_set_default_realm(const char *realm)
        return (GSS_S_COMPLETE);
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_krb5_get_tkt_flags(OM_uint32 *minor_status,
                       gss_ctx_id_t context_handle,
                       OM_uint32 *tkt_flags)
@@ -869,7 +869,7 @@ gss_krb5_get_tkt_flags(OM_uint32 *minor_status,
     return GSS_S_COMPLETE;
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_set_time_offset(int offset)
 {
         struct _gss_mech_switch        *m;
@@ -892,7 +892,7 @@ gsskrb5_set_time_offset(int offset)
        return (GSS_S_COMPLETE);
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_get_time_offset(int *offset)
 {
         struct _gss_mech_switch        *m;
@@ -920,7 +920,7 @@ gsskrb5_get_time_offset(int *offset)
        return (GSS_S_UNAVAILABLE);
 }
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gsskrb5_plugin_register(struct gsskrb5_krb5_plugin *c)
 {
     struct _gss_mech_switch *m;
index 93ee6b2a2defb3c23ea5db48dc7ee31cd29392d9..3e641350892a162800cec577a3aea5c63343ac1f 100644 (file)
 
 #include "mech_locl.h"
 
-int GSSAPI_LIB_FUNCTION
+/**
+ * Compare two GSS-API OIDs with each other.
+ *
+ * GSS_C_NO_OID matches nothing, not even it-self.
+ *
+ * @param a first oid to compare
+ * @param b second oid to compare
+ *
+ * @return non-zero when both oid are the same OID, zero when they are
+ *         not the same.
+ *         
+ * @ingroup gssapi
+ */
+
+GSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL
 gss_oid_equal(const gss_OID a, const gss_OID b)
 {
-    if (a == b)
+    if (a == b && a != GSS_C_NO_OID)
        return 1;
     if (a == GSS_C_NO_OID || b == GSS_C_NO_OID || a->length != b->length)
        return 0;
index 114e7d63e472257ab3b8f69d30a499709dcc1923..d8e188da0827fe8adf97cabcfdeef61f3d2e3068 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_oid_to_str(OM_uint32 *minor_status, gss_OID oid, gss_buffer_t oid_str)
 {
     int ret;
index 738ff7d8e2bc44265c9be5055959adb74a43bfa3..e8e9b56cdc7f99aad4338ae9c04b43de2e2d8e09 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_process_context_token(OM_uint32 *minor_status,
     const gss_ctx_id_t context_handle,
     const gss_buffer_t token_buffer)
index 96b40a6af613e9edf4ecfea382ca4f8cbb72bbb2..ce4f9a4136a5aa531ed7aae01654250bbc74deaa 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_pseudo_random(OM_uint32 *minor_status,
                  gss_ctx_id_t context,
                  int prf_key,
index 9aad034ab2ac04ad7748c8c7ce743f6b44d2a9fe..c3dd4575b6f4408327b9575cdcff6a2174ba4657 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_release_buffer(OM_uint32 *minor_status,
                   gss_buffer_t buffer)
 {
index 463fddb2ba378d6be70f0dd97291e8be15b85199..591ef49ab2f911821bac163cc4b945425b430cc3 100644 (file)
@@ -50,7 +50,7 @@
  * @ingroup gssapi
  */
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle)
 {
        struct _gss_cred *cred = (struct _gss_cred *) *cred_handle;
index 47786725acc7513e7a97708d0f2df3bedbad8fba..28fb75d9667f1aacc327a65801ff866d36863674 100644 (file)
@@ -43,7 +43,7 @@
  *  
  * @ingroup gssapi
  */
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_release_name(OM_uint32 *minor_status,
     gss_name_t *input_name)
 {
index 458e94d711bbc3fb30071718def90d55f0d0ee5d..610daf229c42cc6b1983a51dfba112e36c999627 100644 (file)
@@ -34,7 +34,7 @@
 #include "mech_locl.h"
 
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_release_oid(OM_uint32 *minor_status, gss_OID *oid)
 {
     gss_OID o = *oid;
index f875d39d0c6d64e01eef79bc9315523d503e2dac..183ddf8c751a5d0180004fd73665bc8d7418b567 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_release_oid_set(OM_uint32 *minor_status,
     gss_OID_set *set)
 {
index 8c1e9eba1c672ea728b02138c0d6ad4a5eb97894..26c65dafc984c7d2b4415d280386cb05ef5b128d 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_seal(OM_uint32 *minor_status,
     gss_ctx_id_t context_handle,
     int conf_req_flag,
index 86a136159e05b3af8ffdba5a1876f8bf699140f3..adae7a622e6a73c8e08a5d1eb0c197d0f12fc2fd 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_set_cred_option (OM_uint32 *minor_status,
                     gss_cred_id_t *cred_handle,
                     const gss_OID object,
index ca0ec00ef7828e8feafc1541d5fed60821897a32..6efe1a0b1718f861d9acf6a39b19c4c7795a6904 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_set_sec_context_option (OM_uint32 *minor_status,
                            gss_ctx_id_t *context_handle,
                            const gss_OID object,
index 8a1b1e363fef6890874b5efeef1017514b127475..4ef99c19878cb71f22bcb34d7144d9dc0abb34b2 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_sign(OM_uint32 *minor_status,
     gss_ctx_id_t context_handle,
     int qop_req,
index 7995f4df000659a5fe09e78f3cd35c93ebc993e7..4c4d34904583446bc4ffce02d439f27f872743d6 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_test_oid_set_member(OM_uint32 *minor_status,
     const gss_OID member,
     const gss_OID_set set,
index 88157905756e1b15f1f1cd30518a5df74b8ebec8..0add03d4ddb9e1a99062958dda74bfdcddb76588 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_unseal(OM_uint32 *minor_status,
     gss_ctx_id_t context_handle,
     gss_buffer_t input_message_buffer,
index 7285e46598a81acda97e53d9d61554cb9be1ee82..d0d18aca25b1c00edee4db80218856164cc522e3 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_unwrap(OM_uint32 *minor_status,
     const gss_ctx_id_t context_handle,
     const gss_buffer_t input_message_buffer,
index e60d6507be85abaaf29d552414a5fecf6dcab7c9..dd53ddbae9091237254e669c27166177a412badb 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_verify(OM_uint32 *minor_status,
     gss_ctx_id_t context_handle,
     gss_buffer_t message_buffer,
index c535e3ffce868e62fc5fc324cbfdfd885bb43a97..a791dc732761302d1bcf7c7aa7105feb0d7fa98d 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_verify_mic(OM_uint32 *minor_status,
     const gss_ctx_id_t context_handle,
     const gss_buffer_t message_buffer,
index fb8a17bbe60acc809bcb4e536bc3dcfed56c6ead..dcbb4fcdfee30eeb54f89c3696c4779b71a569ef 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_wrap(OM_uint32 *minor_status,
     const gss_ctx_id_t context_handle,
     int conf_req_flag,
index 49af3646680bd4300df0f589ff40567b81150334..e79814aea720b4c139d08ec6cb5dd39cf852809a 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "mech_locl.h"
 
-OM_uint32 GSSAPI_LIB_FUNCTION
+GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
 gss_wrap_size_limit(OM_uint32 *minor_status,
     const gss_ctx_id_t context_handle,
     int conf_req_flag,
index ab8a4d1aacd19d4f732912fd9ec5944131d1cd74..35bc56fbb777d93eccb352b0c78285d5dbeaf50d 100644 (file)
@@ -372,7 +372,11 @@ select_mech(OM_uint32 *minor_status, MechType *mechType, int verify_p,
                *minor_status = errno;
                return GSS_S_FAILURE;
            }
-           asprintf(&str, "host@%s", hostname);
+           i = asprintf(&str, "host@%s", hostname);
+           if (i < 0 || str == NULL) {
+               *minor_status = ENOMEM;
+               return GSS_S_FAILURE;
+           }
            host = str;
        }
 
@@ -468,7 +472,7 @@ acceptor_complete(OM_uint32 * minor_status,
 }
 
 
-static OM_uint32
+static OM_uint32 GSSAPI_CALLCONV
 acceptor_start
           (OM_uint32 * minor_status,
            gss_ctx_id_t * context_handle,
@@ -685,7 +689,7 @@ out:
 }
 
 
-static OM_uint32
+static OM_uint32 GSSAPI_CALLCONV
 acceptor_continue
           (OM_uint32 * minor_status,
            gss_ctx_id_t * context_handle,
@@ -872,7 +876,7 @@ acceptor_continue
     return ret;
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_accept_sec_context
           (OM_uint32 * minor_status,
            gss_ctx_id_t * context_handle,
index 673a5df66bd33902cff45b017393683be9156eab..b23658cfd1057121f278c228a0fa3af60b30e885 100644 (file)
@@ -49,8 +49,9 @@ gss_OID_desc _gss_spnego_krb5_mechanism_oid_desc =
 /*
  * Allocate a SPNEGO context handle
  */
-OM_uint32 _gss_spnego_alloc_sec_context (OM_uint32 * minor_status,
-                                        gss_ctx_id_t *context_handle)
+OM_uint32 GSSAPI_CALLCONV
+_gss_spnego_alloc_sec_context (OM_uint32 * minor_status,
+                              gss_ctx_id_t *context_handle)
 {
     gssspnego_ctx ctx;
 
@@ -91,7 +92,7 @@ OM_uint32 _gss_spnego_alloc_sec_context (OM_uint32 * minor_status,
  * Free a SPNEGO context handle. The caller must have acquired
  * the lock before this is called.
  */
-OM_uint32 _gss_spnego_internal_delete_sec_context
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_internal_delete_sec_context
            (OM_uint32 *minor_status,
             gss_ctx_id_t *context_handle,
             gss_buffer_t output_token
@@ -150,7 +151,7 @@ OM_uint32 _gss_spnego_internal_delete_sec_context
  * a non-preferred mechanism was negotiated
  */
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_require_mechlist_mic(OM_uint32 *minor_status,
                                 gssspnego_ctx ctx,
                                 int *require_mic)
@@ -228,7 +229,7 @@ add_mech_type(gss_OID mech_type,
 }
 
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status,
                                   gss_name_t target_name,
                                   OM_uint32 (*func)(gss_name_t, gss_OID),
index 98ab919459dc62f1ad0a3d4ad90f4bd171ed8737..18c13fe29957b87afc1d23d9cdf020a3cbcbe31b 100644 (file)
@@ -66,7 +66,7 @@ spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs)
 
 
 
-OM_uint32 _gss_spnego_process_context_token
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_process_context_token
            (OM_uint32 *minor_status,
             const gss_ctx_id_t context_handle,
             const gss_buffer_t token_buffer
@@ -99,7 +99,7 @@ OM_uint32 _gss_spnego_process_context_token
                                           GSS_C_NO_BUFFER);
 }
 
-OM_uint32 _gss_spnego_delete_sec_context
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_delete_sec_context
            (OM_uint32 *minor_status,
             gss_ctx_id_t *context_handle,
             gss_buffer_t output_token
@@ -119,7 +119,7 @@ OM_uint32 _gss_spnego_delete_sec_context
                                                   output_token);
 }
 
-OM_uint32 _gss_spnego_context_time
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_context_time
            (OM_uint32 *minor_status,
             const gss_ctx_id_t context_handle,
             OM_uint32 *time_rec
@@ -143,7 +143,7 @@ OM_uint32 _gss_spnego_context_time
                            time_rec);
 }
 
-OM_uint32 _gss_spnego_get_mic
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_get_mic
            (OM_uint32 *minor_status,
             const gss_ctx_id_t context_handle,
             gss_qop_t qop_req,
@@ -169,7 +169,7 @@ OM_uint32 _gss_spnego_get_mic
                       qop_req, message_buffer, message_token);
 }
 
-OM_uint32 _gss_spnego_verify_mic
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_verify_mic
            (OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
             const gss_buffer_t message_buffer,
@@ -198,7 +198,7 @@ OM_uint32 _gss_spnego_verify_mic
                          qop_state);
 }
 
-OM_uint32 _gss_spnego_wrap
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_wrap
            (OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
             int conf_req_flag,
@@ -231,7 +231,7 @@ OM_uint32 _gss_spnego_wrap
                    output_message_buffer);
 }
 
-OM_uint32 _gss_spnego_unwrap
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_unwrap
            (OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
             const gss_buffer_t input_message_buffer,
@@ -262,7 +262,7 @@ OM_uint32 _gss_spnego_unwrap
                      qop_state);
 }
 
-OM_uint32 _gss_spnego_compare_name
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_compare_name
            (OM_uint32 *minor_status,
             const gss_name_t name1,
             const gss_name_t name2,
@@ -286,7 +286,7 @@ OM_uint32 _gss_spnego_compare_name
     return GSS_S_COMPLETE;
 }
 
-OM_uint32 _gss_spnego_display_name
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_display_name
            (OM_uint32 * minor_status,
             const gss_name_t input_name,
             gss_buffer_t output_name_buffer,
@@ -304,7 +304,7 @@ OM_uint32 _gss_spnego_display_name
                            output_name_buffer, output_name_type);
 }
 
-OM_uint32 _gss_spnego_import_name
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_name
            (OM_uint32 * minor_status,
             const gss_buffer_t name_buffer,
             const gss_OID name_type,
@@ -340,7 +340,7 @@ OM_uint32 _gss_spnego_import_name
     return GSS_S_COMPLETE;
 }
 
-OM_uint32 _gss_spnego_export_name
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_name
            (OM_uint32  * minor_status,
             const gss_name_t input_name,
             gss_buffer_t exported_name
@@ -359,7 +359,7 @@ OM_uint32 _gss_spnego_export_name
     return gss_export_name(minor_status, name->mech, exported_name);
 }
 
-OM_uint32 _gss_spnego_release_name
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_release_name
            (OM_uint32 * minor_status,
             gss_name_t * input_name
            )
@@ -380,7 +380,7 @@ OM_uint32 _gss_spnego_release_name
     return GSS_S_COMPLETE;
 }
 
-OM_uint32 _gss_spnego_inquire_context (
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_context (
             OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
             gss_name_t * src_name,
@@ -447,7 +447,7 @@ enomem:
     return GSS_S_FAILURE;
 }
 
-OM_uint32 _gss_spnego_wrap_size_limit (
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_wrap_size_limit (
             OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
             int conf_req_flag,
@@ -478,7 +478,7 @@ OM_uint32 _gss_spnego_wrap_size_limit (
                               max_input_size);
 }
 
-OM_uint32 _gss_spnego_export_sec_context (
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_export_sec_context (
             OM_uint32 * minor_status,
             gss_ctx_id_t * context_handle,
             gss_buffer_t interprocess_token
@@ -521,7 +521,7 @@ OM_uint32 _gss_spnego_export_sec_context (
     return ret;
 }
 
-OM_uint32 _gss_spnego_import_sec_context (
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_import_sec_context (
             OM_uint32 * minor_status,
             const gss_buffer_t interprocess_token,
             gss_ctx_id_t *context_handle
@@ -557,7 +557,7 @@ OM_uint32 _gss_spnego_import_sec_context (
     return GSS_S_COMPLETE;
 }
 
-OM_uint32 _gss_spnego_inquire_names_for_mech (
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_names_for_mech (
             OM_uint32 * minor_status,
             const gss_OID mechanism,
             gss_OID_set * name_types
@@ -600,7 +600,7 @@ out:
     return ret;
 }
 
-OM_uint32 _gss_spnego_inquire_mechs_for_name (
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_mechs_for_name (
             OM_uint32 * minor_status,
             const gss_name_t input_name,
             gss_OID_set * mech_types
@@ -621,7 +621,7 @@ OM_uint32 _gss_spnego_inquire_mechs_for_name (
     return ret;
 }
 
-OM_uint32 _gss_spnego_canonicalize_name (
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_canonicalize_name (
             OM_uint32 * minor_status,
             const gss_name_t input_name,
             const gss_OID mech_type,
@@ -632,7 +632,7 @@ OM_uint32 _gss_spnego_canonicalize_name (
     return gss_duplicate_name(minor_status, input_name, output_name);
 }
 
-OM_uint32 _gss_spnego_duplicate_name (
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_duplicate_name (
             OM_uint32 * minor_status,
             const gss_name_t src_name,
             gss_name_t * dest_name
@@ -641,7 +641,7 @@ OM_uint32 _gss_spnego_duplicate_name (
     return gss_duplicate_name(minor_status, src_name, dest_name);
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_wrap_iov(OM_uint32 * minor_status,
                     gss_ctx_id_t  context_handle,
                     int conf_req_flag,
@@ -662,7 +662,7 @@ _gss_spnego_wrap_iov(OM_uint32 * minor_status,
                        iov, iov_count);
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_unwrap_iov(OM_uint32 *minor_status,
                       gss_ctx_id_t context_handle,
                       int *conf_state,
@@ -683,7 +683,7 @@ _gss_spnego_unwrap_iov(OM_uint32 *minor_status,
                          iov, iov_count);
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_wrap_iov_length(OM_uint32 * minor_status,
                            gss_ctx_id_t context_handle,
                            int conf_req_flag,
@@ -705,7 +705,7 @@ _gss_spnego_wrap_iov_length(OM_uint32 * minor_status,
 }
 
 #if 0
-OM_uint32 _gss_spnego_complete_auth_token
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_complete_auth_token
            (OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
            gss_buffer_t input_message_buffer)
@@ -730,7 +730,7 @@ OM_uint32 _gss_spnego_complete_auth_token
 }
 #endif
 
-OM_uint32 _gss_spnego_inquire_sec_context_by_oid
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_sec_context_by_oid
            (OM_uint32 * minor_status,
             const gss_ctx_id_t context_handle,
             const gss_OID desired_object,
@@ -756,7 +756,7 @@ OM_uint32 _gss_spnego_inquire_sec_context_by_oid
                                          data_set);
 }
 
-OM_uint32 _gss_spnego_set_sec_context_option
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_set_sec_context_option
            (OM_uint32 * minor_status,
             gss_ctx_id_t * context_handle,
             const gss_OID desired_object,
@@ -783,7 +783,7 @@ OM_uint32 _gss_spnego_set_sec_context_option
 }
 
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_pseudo_random(OM_uint32 *minor_status,
                          gss_ctx_id_t context_handle,
                          int prf_key,
index f15069362c9fe4e9999c4fdd545de18193910f95..2920f3d9b57c388476bb6a706311d40944b479df 100644 (file)
@@ -32,7 +32,7 @@
 
 #include "spnego_locl.h"
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle)
 {
     OM_uint32 ret;
@@ -54,7 +54,7 @@ _gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle)
  * we support gss_{get,set}_neg_mechs() we will need to expose
  * more functionality.
  */
-OM_uint32 _gss_spnego_acquire_cred
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_acquire_cred
 (OM_uint32 *minor_status,
  const gss_name_t desired_name,
  OM_uint32 time_req,
@@ -127,7 +127,7 @@ out:
     return ret;
 }
 
-OM_uint32 _gss_spnego_inquire_cred
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_cred
            (OM_uint32 * minor_status,
             const gss_cred_id_t cred_handle,
             gss_name_t * name,
@@ -169,7 +169,7 @@ OM_uint32 _gss_spnego_inquire_cred
     return ret;
 }
 
-OM_uint32 _gss_spnego_inquire_cred_by_mech (
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_cred_by_mech (
             OM_uint32 * minor_status,
             const gss_cred_id_t cred_handle,
             const gss_OID mech_type,
@@ -214,7 +214,7 @@ OM_uint32 _gss_spnego_inquire_cred_by_mech (
     return GSS_S_COMPLETE;
 }
 
-OM_uint32 _gss_spnego_inquire_cred_by_oid
+OM_uint32 GSSAPI_CALLCONV _gss_spnego_inquire_cred_by_oid
            (OM_uint32 * minor_status,
             const gss_cred_id_t cred_handle,
             const gss_OID desired_object,
@@ -235,7 +235,7 @@ OM_uint32 _gss_spnego_inquire_cred_by_oid
     return ret;
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_set_cred_option (OM_uint32 *minor_status,
                             gss_cred_id_t *cred_handle,
                             const gss_OID object,
@@ -253,7 +253,7 @@ _gss_spnego_set_cred_option (OM_uint32 *minor_status,
 }
 
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_export_cred (OM_uint32 *minor_status,
                         gss_cred_id_t cred_handle,
                         gss_buffer_t value)
@@ -261,7 +261,7 @@ _gss_spnego_export_cred (OM_uint32 *minor_status,
     return gss_export_cred(minor_status, cred_handle, value);
 }
 
-OM_uint32
+OM_uint32 GSSAPI_CALLCONV
 _gss_spnego_import_cred (OM_uint32 *minor_status,
                         gss_buffer_t value,
                         gss_cred_id_t *cred_handle)
index 2a6002b8ea9b772731a669f51fc1c8d995b9060b..d21e4dc7feb41f4756452e948e72a76b9b0517a7 100644 (file)
@@ -93,7 +93,5 @@ __gss_spnego_initialize(void)
        return &spnego_mech;
 }
 
-static gss_OID_desc _gss_spnego_mechanism_desc =
+gss_OID_desc GSSAPI_LIB_VARIABLE __gss_spnego_mechanism_oid_desc =
     {6, (void *)"\x2b\x06\x01\x05\x05\x02"};
-
-gss_OID GSS_SPNEGO_MECHANISM = &_gss_spnego_mechanism_desc;
index 75a925497ea8af165912ef27a9403ce5a53bbc12..c9e182129dd38e4273a167eeb5e477ddfc325279 100644 (file)
@@ -609,7 +609,8 @@ spnego_reply
     return ret;
 }
 
-OM_uint32 _gss_spnego_init_sec_context
+OM_uint32 GSSAPI_CALLCONV
+_gss_spnego_init_sec_context
            (OM_uint32 * minor_status,
             const gss_cred_id_t initiator_cred_handle,
             gss_ctx_id_t * context_handle,
index b3049c165a0256377328f92a26196753dab25de1..77847e460e3b150f16338da18ec234d4529041b0 100644 (file)
@@ -119,3 +119,26 @@ AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
        }
     }
 }
+
+void
+AES_cfb8_encrypt(const unsigned char *in, unsigned char *out,
+                 unsigned long size, const AES_KEY *key,
+                 unsigned char *iv, int forward_encrypt)
+{
+    int i;
+
+    for (i = 0; i < size; i++) {
+        unsigned char tmp[AES_BLOCK_SIZE + 1];
+
+        memcpy(tmp, iv, AES_BLOCK_SIZE);
+        AES_encrypt(iv, iv, key);
+        if (!forward_encrypt) {
+            tmp[AES_BLOCK_SIZE] = in[i];
+        }
+        out[i] = in[i] ^ iv[0];
+        if (forward_encrypt) {
+            tmp[AES_BLOCK_SIZE] = out[i];
+        }
+        memcpy(iv, &tmp[1], AES_BLOCK_SIZE);
+    }
+}
index 273f1dd5696595a4333edc0d1757a73348ecf049..4ba4516519fda57ea6b302cc75cb9ca331ab6ff6 100644 (file)
@@ -42,6 +42,7 @@
 #define AES_encrypt hc_AES_encrypt
 #define AES_decrypt hc_AES_decrypt
 #define AES_cbc_encrypt hc_AES_cbc_encrypt
+#define AES_cfb8_encrypt hc_AES_cfb8_encrypt
 
 /*
  *
@@ -71,6 +72,9 @@ void AES_decrypt(const unsigned char *, unsigned char *, const AES_KEY *);
 void AES_cbc_encrypt(const unsigned char *, unsigned char *,
                     unsigned long, const AES_KEY *,
                     unsigned char *, int);
+void AES_cfb8_encrypt(const unsigned char *, unsigned char *,
+                     unsigned long, const AES_KEY *,
+                     unsigned char *, int);
 
 #ifdef  __cplusplus
 }
index feabae1aa30e2e12da022dcc521f5bbd3d0037af..6661f3bf07ce87e05623ae3be8efe474491104fa 100644 (file)
@@ -66,7 +66,7 @@ void CAMELLIA_decrypt(const unsigned char *, unsigned char *,
                      const CAMELLIA_KEY *);
 
 void CAMELLIA_cbc_encrypt(const unsigned char *, unsigned char *,
-                         const unsigned long, const CAMELLIA_KEY *,
+                         unsigned long, const CAMELLIA_KEY *,
                          unsigned char *, int);
 
 #endif /* HEIM_CAMELLIA_H */
diff --git a/source4/heimdal/lib/hcrypto/common.c b/source4/heimdal/lib/hcrypto/common.c
new file mode 100644 (file)
index 0000000..136bf1d
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <krb5-types.h>
+#include <rfc2459_asn1.h>
+#include <hcrypto/bn.h>
+
+
+#include "common.h"
+
+int
+_hc_BN_to_integer(BIGNUM *bn, heim_integer *integer)
+{
+    integer->length = BN_num_bytes(bn);
+    integer->data = malloc(integer->length);
+    if (integer->data == NULL)
+       return ENOMEM;
+    BN_bn2bin(bn, integer->data);
+    integer->negative = BN_is_negative(bn);
+    return 0;
+}
+
+BIGNUM *
+_hc_integer_to_BN(const heim_integer *i, BIGNUM *bn)
+{
+    bn = BN_bin2bn(i->data, i->length, bn);
+    if (bn)
+       BN_set_negative(bn, i->negative);
+    return bn;
+}
diff --git a/source4/heimdal/lib/hcrypto/common.h b/source4/heimdal/lib/hcrypto/common.h
new file mode 100644 (file)
index 0000000..f78f544
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef HCRYPTO_COMMON_H
+#define HCRYPTO_COMMON_H 1
+
+int
+_hc_BN_to_integer(BIGNUM *, heim_integer *);
+
+BIGNUM *
+_hc_integer_to_BN(const heim_integer *i, BIGNUM *bn);
+
+#endif /* HCRYPTO_COMMON_H */
index 822d5a328bc5cb1af3a9f0c928860689115bca47..c2e86fa2fa69f77e0d396882dcaaef811c320ff0 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-#endif
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <dh.h>
 
+#ifdef USE_HCRYPTO_IMATH
+
 #include <roken.h>
 
 #include "imath/imath.h"
@@ -233,6 +233,7 @@ const DH_METHOD _hc_dh_imath_method = {
     NULL,
     dh_generate_params
 };
+#endif /* USE_HCRYPTO_DH_IMATH */
 
 /**
  * DH implementation using libimath.
@@ -245,5 +246,9 @@ const DH_METHOD _hc_dh_imath_method = {
 const DH_METHOD *
 DH_imath_method(void)
 {
+#ifdef USE_HCRYPTO_DH_IMATH
     return &_hc_dh_imath_method;
+#else
+    return NULL;
+#endif
 }
diff --git a/source4/heimdal/lib/hcrypto/dh-ltm.c b/source4/heimdal/lib/hcrypto/dh-ltm.c
new file mode 100644 (file)
index 0000000..6166100
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dh.h>
+
+#include <roken.h>
+
+#include "tommath.h"
+
+static void
+BN2mpz(mp_int *s, const BIGNUM *bn)
+{
+    size_t len;
+    void *p;
+
+    len = BN_num_bytes(bn);
+    p = malloc(len);
+    BN_bn2bin(bn, p);
+    mp_read_unsigned_bin(s, p, len);
+    free(p);
+}
+
+
+static BIGNUM *
+mpz2BN(mp_int *s)
+{
+    size_t size;
+    BIGNUM *bn;
+    void *p;
+
+    size = mp_unsigned_bin_size(s);
+    p = malloc(size);
+    if (p == NULL && size != 0)
+       return NULL;
+    mp_to_unsigned_bin(s, p);
+
+    bn = BN_bin2bn(p, size, NULL);
+    free(p);
+    return bn;
+}
+
+/*
+ *
+ */
+
+#define DH_NUM_TRIES 10
+
+static int
+ltm_dh_generate_key(DH *dh)
+{
+    mp_int pub, priv_key, g, p;
+    int have_private_key = (dh->priv_key != NULL);
+    int codes, times = 0;
+    int res;
+
+    if (dh->p == NULL || dh->g == NULL)
+       return 0;
+
+    while (times++ < DH_NUM_TRIES) {
+       if (!have_private_key) {
+           size_t bits = BN_num_bits(dh->p);
+
+           if (dh->priv_key)
+               BN_free(dh->priv_key);
+
+           dh->priv_key = BN_new();
+           if (dh->priv_key == NULL)
+               return 0;
+           if (!BN_rand(dh->priv_key, bits - 1, 0, 0)) {
+               BN_clear_free(dh->priv_key);
+               dh->priv_key = NULL;
+               return 0;
+           }
+       }
+       if (dh->pub_key)
+           BN_free(dh->pub_key);
+
+       mp_init_multi(&pub, &priv_key, &g, &p, NULL);
+       
+       BN2mpz(&priv_key, dh->priv_key);
+       BN2mpz(&g, dh->g);
+       BN2mpz(&p, dh->p);
+       
+       res = mp_exptmod(&g, &priv_key, &p, &pub);
+
+       mp_zero(&priv_key);
+       mp_zero(&g);
+       mp_zero(&p);
+       if (res != 0)
+           continue;
+
+       dh->pub_key = mpz2BN(&pub);
+       mp_zero(&pub);
+       if (dh->pub_key == NULL)
+           return 0;
+       
+       if (DH_check_pubkey(dh, dh->pub_key, &codes) && codes == 0)
+           break;
+       if (have_private_key)
+           return 0;
+    }
+
+    if (times >= DH_NUM_TRIES) {
+       if (!have_private_key && dh->priv_key) {
+           BN_free(dh->priv_key);
+           dh->priv_key = NULL;
+       }
+       if (dh->pub_key) {
+           BN_free(dh->pub_key);
+           dh->pub_key = NULL;
+       }
+       return 0;
+    }
+
+    return 1;
+}
+
+static int
+ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh)
+{
+    mp_int s, priv_key, p, peer_pub;
+    size_t size = 0;
+    int ret;
+
+    if (dh->pub_key == NULL || dh->g == NULL || dh->priv_key == NULL)
+       return -1;
+
+    mp_init(&p);
+    BN2mpz(&p, dh->p);
+
+    mp_init(&peer_pub);
+    BN2mpz(&peer_pub, pub);
+
+    /* check if peers pubkey is reasonable */
+    if (mp_isneg(&peer_pub)
+       || mp_cmp(&peer_pub, &p) >= 0
+       || mp_cmp_d(&peer_pub, 1) <= 0)
+    {
+       mp_zero(&p);
+       mp_zero(&peer_pub);
+       return -1;
+    }
+
+    mp_init(&priv_key);
+    BN2mpz(&priv_key, dh->priv_key);
+
+    mp_init(&s);
+
+    ret = mp_exptmod(&peer_pub, &priv_key, &p, &s);
+
+    mp_zero(&p);
+    mp_zero(&peer_pub);
+    mp_zero(&priv_key);
+
+    if (ret != 0)
+       return -1;
+
+    size = mp_unsigned_bin_size(&s);
+    mp_to_unsigned_bin(&s, shared);
+    mp_zero(&s);
+
+    return size;
+}
+
+static int
+ltm_dh_generate_params(DH *dh, int a, int b, BN_GENCB *callback)
+{
+    /* groups should already be known, we don't care about this */
+    return 0;
+}
+
+static int
+ltm_dh_init(DH *dh)
+{
+    return 1;
+}
+
+static int
+ltm_dh_finish(DH *dh)
+{
+    return 1;
+}
+
+
+/*
+ *
+ */
+
+const DH_METHOD _hc_dh_ltm_method = {
+    "hcrypto ltm DH",
+    ltm_dh_generate_key,
+    ltm_dh_compute_key,
+    NULL,
+    ltm_dh_init,
+    ltm_dh_finish,
+    0,
+    NULL,
+    ltm_dh_generate_params
+};
+
+/**
+ * DH implementation using libimath.
+ *
+ * @return the DH_METHOD for the DH implementation using libimath.
+ *
+ * @ingroup hcrypto_dh
+ */
+
+const DH_METHOD *
+DH_ltm_method(void)
+{
+    return &_hc_dh_ltm_method;
+}
index d42ac34fd22533bdaa14c6791fe3d259a843782d..3ad37f87a78c7ded677b28b522817909959edaa0 100644 (file)
@@ -37,6 +37,9 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <krb5-types.h>
+#include <rfc2459_asn1.h>
+
 #include <dh.h>
 
 #include <roken.h>
@@ -487,3 +490,63 @@ DH_get_default_method(void)
     return dh_default_method;
 }
 
+/*
+ *
+ */
+
+static int
+bn2heim_int(BIGNUM *bn, heim_integer *integer)
+{
+    integer->length = BN_num_bytes(bn);
+    integer->data = malloc(integer->length);
+    if (integer->data == NULL) {
+       integer->length = 0;
+       return ENOMEM;
+    }
+    BN_bn2bin(bn, integer->data);
+    integer->negative = BN_is_negative(bn);
+    return 0;
+}
+
+/**
+ *
+ */
+
+int
+i2d_DHparams(DH *dh, unsigned char **pp)
+{
+    DHParameter data;
+    size_t size;
+    int ret;
+
+    memset(&data, 0, sizeof(data));
+
+    if (bn2heim_int(dh->p, &data.prime) ||
+       bn2heim_int(dh->g, &data.base))
+    {
+       free_DHParameter(&data);
+       return -1;
+    }
+
+    if (pp == NULL) {
+       size = length_DHParameter(&data);
+       free_DHParameter(&data);
+    } else {
+       void *p;
+       size_t len;
+
+       ASN1_MALLOC_ENCODE(DHParameter, p, len, &data, &size, ret);
+       free_DHParameter(&data);
+       if (ret)
+           return -1;
+       if (len != size)
+           abort();
+
+       memcpy(*pp, p, size);
+       free(p);
+
+       *pp += size;
+    }
+
+    return size;
+}
index 2522bfe39f5d8935708986e45eeb3e523aba4a88..3a24f9dfdfcbb9ad6e5825006e06a76272328c18 100644 (file)
@@ -41,6 +41,8 @@
 /* symbol renaming */
 #define DH_null_method hc_DH_null_method
 #define DH_imath_method hc_DH_imath_method
+#define DH_tfm_method hc_DH_tfm_method
+#define DH_ltm_method hc_DH_ltm_method
 #define DH_new hc_DH_new
 #define DH_new_method hc_DH_new_method
 #define DH_free hc_DH_free
@@ -56,6 +58,7 @@
 #define DH_check_pubkey hc_DH_check_pubkey
 #define DH_generate_key hc_DH_generate_key
 #define DH_compute_key hc_DH_compute_key
+#define        i2d_DHparams hc_i2d_DHparams
 
 /*
  *
@@ -114,6 +117,8 @@ struct DH {
  */
 
 const DH_METHOD *DH_null_method(void);
+const DH_METHOD *DH_tfm_method(void);
+const DH_METHOD *DH_ltm_method(void);
 const DH_METHOD *DH_imath_method(void);
 
 DH *   DH_new(void);
@@ -137,5 +142,7 @@ int DH_check_pubkey(const DH *, const BIGNUM *, int *);
 int    DH_generate_key(DH *);
 int    DH_compute_key(unsigned char *,const BIGNUM *,DH *);
 
+int    i2d_DHparams(DH *, unsigned char **);
+
 #endif /* _HEIM_DH_H */
 
index 8066d59cf89f2350c42524cbb2d8d83cd5692a7d..6e3e5e3939632b8ef02c34fd3ce75eea8f81ee7f 100644 (file)
@@ -56,6 +56,23 @@ struct hc_engine {
     const RAND_METHOD *rand;
 };
 
+ENGINE *
+ENGINE_new(void)
+{
+    ENGINE *engine;
+
+    engine = calloc(1, sizeof(*engine));
+    engine->references = 1;
+
+    return engine;
+}
+
+int
+ENGINE_free(ENGINE *engine)
+{
+    return ENGINE_finish(engine);
+}
+
 int
 ENGINE_finish(ENGINE *engine)
 {
@@ -195,10 +212,8 @@ add_engine(ENGINE *engine)
     ENGINE **d, *dup;
 
     dup = ENGINE_by_id(engine->id);
-    if (dup) {
-       ENGINE_finish(dup);
+    if (dup)
        return 0;
-    }
 
     d = realloc(engines, (num_engines + 1) * sizeof(*engines));
     if (d == NULL)
@@ -215,19 +230,98 @@ ENGINE_load_builtin_engines(void)
     ENGINE *engine;
     int ret;
 
-    engine = calloc(1, sizeof(*engine));
+    engine = ENGINE_new();
     if (engine == NULL)
        return;
 
     ENGINE_set_id(engine, "builtin");
     ENGINE_set_name(engine,
-                   "Heimdal crypto builtin engine version " PACKAGE_VERSION);
+                   "Heimdal crypto builtin (ltm) engine version " PACKAGE_VERSION);
+    ENGINE_set_RSA(engine, RSA_ltm_method());
+    ENGINE_set_DH(engine, DH_ltm_method());
+
+    ret = add_engine(engine);
+    if (ret != 1)
+       ENGINE_finish(engine);
+
+#ifdef USE_HCRYPTO_TFM
+    /*
+     * TFM
+     */
+
+    engine = ENGINE_new();
+    if (engine == NULL)
+       return;
+
+    ENGINE_set_id(engine, "tfm");
+    ENGINE_set_name(engine,
+                   "Heimdal crypto tfm engine version " PACKAGE_VERSION);
+    ENGINE_set_RSA(engine, RSA_tfm_method());
+    ENGINE_set_DH(engine, DH_tfm_method());
+
+    ret = add_engine(engine);
+    if (ret != 1)
+       ENGINE_finish(engine);
+#endif /* USE_HCRYPTO_TFM */
+
+#ifdef USE_HCRYPTO_LTM
+    /*
+     * ltm
+     */
+
+    engine = ENGINE_new();
+    if (engine == NULL)
+       return;
+
+    ENGINE_set_id(engine, "ltm");
+    ENGINE_set_name(engine,
+                   "Heimdal crypto ltm engine version " PACKAGE_VERSION);
+    ENGINE_set_RSA(engine, RSA_ltm_method());
+    ENGINE_set_DH(engine, DH_ltm_method());
+
+    ret = add_engine(engine);
+    if (ret != 1)
+       ENGINE_finish(engine);
+#endif
+
+#ifdef USE_HCRYPTO_IMATH
+    /*
+     * imath
+     */
+
+    engine = ENGINE_new();
+    if (engine == NULL)
+       return;
+
+    ENGINE_set_id(engine, "imath");
+    ENGINE_set_name(engine,
+                   "Heimdal crypto imath engine version " PACKAGE_VERSION);
     ENGINE_set_RSA(engine, RSA_imath_method());
     ENGINE_set_DH(engine, DH_imath_method());
 
     ret = add_engine(engine);
     if (ret != 1)
        ENGINE_finish(engine);
+#endif
+
+#ifdef HAVE_GMP
+    /*
+     * gmp
+     */
+
+    engine = ENGINE_new();
+    if (engine == NULL)
+       return;
+
+    ENGINE_set_id(engine, "gmp");
+    ENGINE_set_name(engine,
+                   "Heimdal crypto gmp engine version " PACKAGE_VERSION);
+    ENGINE_set_RSA(engine, RSA_gmp_method());
+
+    ret = add_engine(engine);
+    if (ret != 1)
+       ENGINE_finish(engine);
+#endif
 }
 
 ENGINE *
index d3a1479ce234f68de48e11116bb00f8b964d0fda..7fd8f3e1e5a2bbde889c28d4293834ca7a373db0 100644 (file)
@@ -54,6 +54,8 @@
 #define ENGINE_set_id hc_ENGINE_set_id
 #define ENGINE_set_name hc_ENGINE_set_name
 #define ENGINE_set_destroy_function hc_ENGINE_set_destroy_function
+#define ENGINE_new hc_ENGINE_new
+#define ENGINE_free hc_ENGINE_free
 #define ENGINE_up_ref hc_ENGINE_up_ref
 #define ENGINE_get_default_DH hc_ENGINE_get_default_DH
 #define ENGINE_get_default_RSA hc_ENGINE_get_default_RSA
 
 typedef struct hc_engine ENGINE;
 
+#define NID_md2                        0
+#define NID_md4                        1
+#define NID_md5                        2
+#define NID_sha1               4
+#define NID_sha256             5
+
+/*
+ *
+ */
+
 #include <hcrypto/rsa.h>
 #include <hcrypto/dsa.h>
 #include <hcrypto/dh.h>
@@ -76,6 +88,9 @@ typedef struct hc_engine ENGINE;
 typedef int (*openssl_bind_engine)(ENGINE *, const char *, const void *);
 typedef unsigned long (*openssl_v_check)(unsigned long);
 
+ENGINE *
+       ENGINE_new(void);
+int ENGINE_free(ENGINE *);
 void   ENGINE_add_conf_module(void);
 void   ENGINE_load_builtin_engines(void);
 ENGINE *ENGINE_by_id(const char *);
diff --git a/source4/heimdal/lib/hcrypto/evp-cc.c b/source4/heimdal/lib/hcrypto/evp-cc.c
new file mode 100644 (file)
index 0000000..bd084a2
--- /dev/null
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 2008 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* CommonCrypto provider */
+
+#ifdef __APPLE__
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
+#include <CommonCrypto/CommonDigest.h>
+#endif
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+#include <CommonCrypto/CommonCryptor.h>
+#endif
+
+#include <evp.h>
+#include <evp-cc.h>
+
+/*
+ *
+ */
+
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+
+struct cc_key {
+    CCCryptorRef href;
+};
+
+static int
+cc_do_cipher(EVP_CIPHER_CTX *ctx,
+            unsigned char *out,
+            const unsigned char *in,
+            unsigned int size)
+{
+    struct cc_key *cc = ctx->cipher_data;
+    CCCryptorStatus ret;
+    size_t moved;
+
+    memcpy(out, in, size);
+
+    ret = CCCryptorUpdate(cc->href, in, size, out, size, &moved);
+    if (ret)
+       return 0;
+
+    if (moved != size)
+       return 0;
+
+    return 1;
+}
+
+static int
+cc_do_cfb8_cipher(EVP_CIPHER_CTX *ctx,
+                  unsigned char *out,
+                  const unsigned char *in,
+                  unsigned int size)
+{
+    struct cc_key *cc = ctx->cipher_data;
+    CCCryptorStatus ret;
+    size_t moved;
+    unsigned int i;
+
+    for (i = 0; i < size; i++) {
+        unsigned char oiv[EVP_MAX_IV_LENGTH + 1];
+
+        assert(ctx->cipher->iv_len + 1 <= sizeof(oiv));
+        memcpy(oiv, ctx->iv, ctx->cipher->iv_len);
+
+        ret = CCCryptorUpdate(cc->href, ctx->iv, ctx->cipher->iv_len,
+                              ctx->iv, ctx->cipher->iv_len, &moved);
+        if (ret)
+            return 0;
+
+        if (moved != ctx->cipher->iv_len)
+            return 0;
+
+        if (!ctx->encrypt)
+            oiv[ctx->cipher->iv_len] = in[i];
+        out[i] = in[i] ^ ctx->iv[0];
+        if (ctx->encrypt)
+            oiv[ctx->cipher->iv_len] = out[i];
+
+        memcpy(ctx->iv, &oiv[1], ctx->cipher->iv_len);
+    }
+
+    return 1;
+}
+
+static int
+cc_cleanup(EVP_CIPHER_CTX *ctx)
+{
+    struct cc_key *cc = ctx->cipher_data;
+    if (cc->href)
+       CCCryptorRelease(cc->href);
+    return 1;
+}
+
+static int
+init_cc_key(int encp, CCAlgorithm alg, CCOptions opts, const void *key,
+           size_t keylen, const void *iv, CCCryptorRef *ref)
+{
+    CCOperation op = encp ? kCCEncrypt : kCCDecrypt;
+    CCCryptorStatus ret;
+
+    if (*ref) {
+       if (key == NULL && iv) {
+           CCCryptorReset(*ref, iv);
+           return 1;
+       }
+       CCCryptorRelease(*ref);
+    }
+
+    ret = CCCryptorCreate(op, alg, opts, key, keylen, iv, ref);
+    if (ret)
+       return 0;
+    return 1;
+}
+
+static int
+cc_des_ede3_cbc_init(EVP_CIPHER_CTX *ctx,
+                    const unsigned char * key,
+                    const unsigned char * iv,
+                    int encp)
+{
+    struct cc_key *cc = ctx->cipher_data;
+    return init_cc_key(encp, kCCAlgorithm3DES, 0, key, kCCKeySize3DES, iv, &cc->href);
+}
+
+#endif /* HAVE_COMMONCRYPTO_COMMONCRYPTOR_H */
+
+/**
+ * The tripple DES cipher type (Apple CommonCrypto provider)
+ *
+ * @return the DES-EDE3-CBC EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_des_ede3_cbc(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+    static const EVP_CIPHER des_ede3_cbc = {
+       0,
+       8,
+       24,
+       8,
+       EVP_CIPH_CBC_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_des_ede3_cbc_init,
+       cc_do_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &des_ede3_cbc;
+#else
+    return NULL;
+#endif
+}
+
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+/*
+ *
+ */
+
+static int
+cc_des_cbc_init(EVP_CIPHER_CTX *ctx,
+               const unsigned char * key,
+               const unsigned char * iv,
+               int encp)
+{
+    struct cc_key *cc = ctx->cipher_data;
+    return init_cc_key(encp, kCCAlgorithmDES, 0, key, kCCBlockSizeDES, iv, &cc->href);
+}
+#endif
+
+/**
+ * The DES cipher type (Apple CommonCrypto provider)
+ *
+ * @return the DES-CBC EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_des_cbc(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+    static const EVP_CIPHER des_ede3_cbc = {
+       0,
+       kCCBlockSizeDES,
+       kCCBlockSizeDES,
+       kCCBlockSizeDES,
+       EVP_CIPH_CBC_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_des_cbc_init,
+       cc_do_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &des_ede3_cbc;
+#else
+    return NULL;
+#endif
+}
+
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+/*
+ *
+ */
+
+static int
+cc_aes_cbc_init(EVP_CIPHER_CTX *ctx,
+               const unsigned char * key,
+               const unsigned char * iv,
+               int encp)
+{
+    struct cc_key *cc = ctx->cipher_data;
+    return init_cc_key(encp, kCCAlgorithmAES128, 0, key, ctx->cipher->key_len, iv, &cc->href);
+}
+#endif
+
+/**
+ * The AES-128 cipher type (Apple CommonCrypto provider)
+ *
+ * @return the AES-128-CBC EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_aes_128_cbc(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+    static const EVP_CIPHER c = {
+       0,
+       kCCBlockSizeAES128,
+       kCCKeySizeAES128,
+       kCCBlockSizeAES128,
+       EVP_CIPH_CBC_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_aes_cbc_init,
+       cc_do_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &c;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The AES-192 cipher type (Apple CommonCrypto provider)
+ *
+ * @return the AES-192-CBC EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_aes_192_cbc(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+    static const EVP_CIPHER c = {
+       0,
+       kCCBlockSizeAES128,
+       kCCKeySizeAES192,
+       kCCBlockSizeAES128,
+       EVP_CIPH_CBC_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_aes_cbc_init,
+       cc_do_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &c;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The AES-256 cipher type (Apple CommonCrypto provider)
+ *
+ * @return the AES-256-CBC EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_aes_256_cbc(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+    static const EVP_CIPHER c = {
+       0,
+       kCCBlockSizeAES128,
+       kCCKeySizeAES256,
+       kCCBlockSizeAES128,
+       EVP_CIPH_CBC_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_aes_cbc_init,
+       cc_do_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &c;
+#else
+    return NULL;
+#endif
+}
+
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+/*
+ *
+ */
+
+static int
+cc_aes_cfb8_init(EVP_CIPHER_CTX *ctx,
+               const unsigned char * key,
+               const unsigned char * iv,
+               int encp)
+{
+    struct cc_key *cc = ctx->cipher_data;
+    memcpy(ctx->iv, iv, ctx->cipher->iv_len);
+    return init_cc_key(1, kCCAlgorithmAES128, kCCOptionECBMode,
+                      key, ctx->cipher->key_len, NULL, &cc->href);
+}
+#endif
+
+/**
+ * The AES-128 CFB8 cipher type (Apple CommonCrypto provider)
+ *
+ * @return the AES-128-CFB8 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_aes_128_cfb8(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+    static const EVP_CIPHER c = {
+       0,
+       1,
+       kCCKeySizeAES128,
+       kCCBlockSizeAES128,
+       EVP_CIPH_CFB8_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_aes_cfb8_init,
+       cc_do_cfb8_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &c;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The AES-192 CFB8 cipher type (Apple CommonCrypto provider)
+ *
+ * @return the AES-192-CFB8 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_aes_192_cfb8(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+    static const EVP_CIPHER c = {
+       0,
+       1,
+       kCCKeySizeAES192,
+       kCCBlockSizeAES128,
+       EVP_CIPH_CFB8_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_aes_cfb8_init,
+       cc_do_cfb8_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &c;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The AES-256 CFB8 cipher type (Apple CommonCrypto provider)
+ *
+ * @return the AES-256-CFB8 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_aes_256_cfb8(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+    static const EVP_CIPHER c = {
+       0,
+       kCCBlockSizeAES128,
+       kCCKeySizeAES256,
+       kCCBlockSizeAES128,
+       EVP_CIPH_CFB8_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_aes_cfb8_init,
+       cc_do_cfb8_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &c;
+#else
+    return NULL;
+#endif
+}
+
+/*
+ *
+ */
+
+#ifdef COMMONCRYPTO_SUPPORTS_RC2
+static int
+cc_rc2_cbc_init(EVP_CIPHER_CTX *ctx,
+               const unsigned char * key,
+               const unsigned char * iv,
+               int encp)
+{
+    struct cc_key *cc = ctx->cipher_data;
+    return init_cc_key(encp, kCCAlgorithmRC2, 0, key, ctx->cipher->key_len, iv, &cc->href);
+}
+#endif
+
+/**
+ * The RC2 cipher type - common crypto
+ *
+ * @return the RC2 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+
+const EVP_CIPHER *
+EVP_cc_rc2_cbc(void)
+{
+#ifdef COMMONCRYPTO_SUPPORTS_RC2
+    static const EVP_CIPHER rc2_cbc = {
+       0,
+       kCCBlockSizeRC2,
+       16,
+       kCCBlockSizeRC2,
+       EVP_CIPH_CBC_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_rc2_cbc_init,
+       cc_do_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &rc2_cbc;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The RC2-40 cipher type - common crypto
+ *
+ * @return the RC2-40 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+
+const EVP_CIPHER *
+EVP_cc_rc2_40_cbc(void)
+{
+#ifdef COMMONCRYPTO_SUPPORTS_RC2
+    static const EVP_CIPHER rc2_40_cbc = {
+       0,
+       kCCBlockSizeRC2,
+       5,
+       kCCBlockSizeRC2,
+       EVP_CIPH_CBC_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_rc2_cbc_init,
+       cc_do_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &rc2_40_cbc;
+#else
+    return NULL;
+#endif
+}
+
+
+/**
+ * The RC2-64 cipher type - common crypto
+ *
+ * @return the RC2-64 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+
+const EVP_CIPHER *
+EVP_cc_rc2_64_cbc(void)
+{
+#ifdef COMMONCRYPTO_SUPPORTS_RC2
+    static const EVP_CIPHER rc2_64_cbc = {
+       0,
+       kCCBlockSizeRC2,
+       8,
+       kCCBlockSizeRC2,
+       EVP_CIPH_CBC_MODE|EVP_CIPH_ALWAYS_CALL_INIT,
+       cc_rc2_cbc_init,
+       cc_do_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &rc2_64_cbc;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The CommonCrypto md2 provider
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_MD *
+EVP_cc_md2(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
+    static const struct hc_evp_md md2 = {
+       CC_MD2_DIGEST_LENGTH,
+       CC_MD2_BLOCK_BYTES,
+       sizeof(CC_MD2_CTX),
+       (hc_evp_md_init)CC_MD2_Init,
+       (hc_evp_md_update)CC_MD2_Update,
+       (hc_evp_md_final)CC_MD2_Final,
+       (hc_evp_md_cleanup)NULL
+    };
+    return &md2;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The CommonCrypto md4 provider
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_MD *
+EVP_cc_md4(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
+    static const struct hc_evp_md md4 = {
+       CC_MD4_DIGEST_LENGTH,
+       CC_MD4_BLOCK_BYTES,
+       sizeof(CC_MD4_CTX),
+       (hc_evp_md_init)CC_MD4_Init,
+       (hc_evp_md_update)CC_MD4_Update,
+       (hc_evp_md_final)CC_MD4_Final,
+       (hc_evp_md_cleanup)NULL
+    };
+    return &md4;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The CommonCrypto md5 provider
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_MD *
+EVP_cc_md5(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
+    static const struct hc_evp_md md5 = {
+       CC_MD5_DIGEST_LENGTH,
+       CC_MD5_BLOCK_BYTES,
+       sizeof(CC_MD5_CTX),
+       (hc_evp_md_init)CC_MD5_Init,
+       (hc_evp_md_update)CC_MD5_Update,
+       (hc_evp_md_final)CC_MD5_Final,
+       (hc_evp_md_cleanup)NULL
+    };
+    return &md5;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The CommonCrypto sha1 provider
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_MD *
+EVP_cc_sha1(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
+    static const struct hc_evp_md sha1 = {
+       CC_SHA1_DIGEST_LENGTH,
+       CC_SHA1_BLOCK_BYTES,
+       sizeof(CC_SHA1_CTX),
+       (hc_evp_md_init)CC_SHA1_Init,
+       (hc_evp_md_update)CC_SHA1_Update,
+       (hc_evp_md_final)CC_SHA1_Final,
+       (hc_evp_md_cleanup)NULL
+    };
+    return &sha1;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The CommonCrypto sha256 provider
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_MD *
+EVP_cc_sha256(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONDIGEST_H
+    static const struct hc_evp_md sha256 = {
+       CC_SHA256_DIGEST_LENGTH,
+       CC_SHA256_BLOCK_BYTES,
+       sizeof(CC_SHA256_CTX),
+       (hc_evp_md_init)CC_SHA256_Init,
+       (hc_evp_md_update)CC_SHA256_Update,
+       (hc_evp_md_final)CC_SHA256_Final,
+       (hc_evp_md_cleanup)NULL
+    };
+    return &sha256;
+#else
+    return NULL;
+#endif
+}
+
+/**
+ * The Camellia-128 cipher type - CommonCrypto
+ *
+ * @return the Camellia-128 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_camellia_128_cbc(void)
+{
+    return NULL;
+}
+
+/**
+ * The Camellia-198 cipher type - CommonCrypto
+ *
+ * @return the Camellia-198 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_camellia_192_cbc(void)
+{
+    return NULL;
+}
+
+/**
+ * The Camellia-256 cipher type - CommonCrypto
+ *
+ * @return the Camellia-256 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_camellia_256_cbc(void)
+{
+    return NULL;
+}
+
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+
+/*
+ *
+ */
+
+static int
+cc_rc4_init(EVP_CIPHER_CTX *ctx,
+           const unsigned char * key,
+           const unsigned char * iv,
+           int encp)
+{
+    struct cc_key *cc = ctx->cipher_data;
+    return init_cc_key(encp, kCCAlgorithmRC4, 0, key, ctx->key_len, iv, &cc->href);
+}
+
+#endif
+
+/**
+
+ * The RC4 cipher type (Apple CommonCrypto provider)
+ *
+ * @return the RC4 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_rc4(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+    static const EVP_CIPHER rc4 = {
+       0,
+       1,
+       16,
+       0,
+       EVP_CIPH_STREAM_CIPHER|EVP_CIPH_VARIABLE_LENGTH,
+       cc_rc4_init,
+       cc_do_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &rc4;
+#else
+    return NULL;
+#endif
+}
+
+
+/**
+ * The RC4-40 cipher type (Apple CommonCrypto provider)
+ *
+ * @return the RC4 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_cc_rc4_40(void)
+{
+#ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
+    static const EVP_CIPHER rc4_40 = {
+       0,
+       1,
+       5,
+       0,
+       EVP_CIPH_STREAM_CIPHER|EVP_CIPH_VARIABLE_LENGTH,
+       cc_rc4_init,
+       cc_do_cipher,
+       cc_cleanup,
+       sizeof(struct cc_key),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &rc4_40;
+#else
+    return NULL;
+#endif
+}
+
+#endif /* __APPLE__ */
+
index 0febd21e98ab6e8a6a2c21009e5246c04f5e1583..9249bb226e1e042a0f86b64513182272d450571e 100644 (file)
@@ -47,6 +47,9 @@
 #define EVP_cc_aes_128_cbc hc_EVP_cc_aes_128_cbc
 #define EVP_cc_aes_192_cbc hc_EVP_cc_aes_192_cbc
 #define EVP_cc_aes_256_cbc hc_EVP_cc_aes_256_cbc
+#define EVP_cc_aes_128_cfb8 hc_EVP_cc_aes_128_cfb8
+#define EVP_cc_aes_192_cfb8 hc_EVP_cc_aes_192_cfb8
+#define EVP_cc_aes_256_cfb8 hc_EVP_cc_aes_256_cfb8
 #define EVP_cc_rc4 hc_EVP_cc_rc4
 #define EVP_cc_rc4_40 hc_EVP_cc_rc4_40
 #define EVP_cc_rc2_40_cbc hc_EVP_cc_rc2_40_cbc
@@ -82,6 +85,10 @@ const EVP_CIPHER * EVP_cc_aes_128_cbc(void);
 const EVP_CIPHER * EVP_cc_aes_192_cbc(void);
 const EVP_CIPHER * EVP_cc_aes_256_cbc(void);
 
+const EVP_CIPHER * EVP_cc_aes_128_cfb8(void);
+const EVP_CIPHER * EVP_cc_aes_192_cfb8(void);
+const EVP_CIPHER * EVP_cc_aes_256_cfb8(void);
+
 const EVP_CIPHER * EVP_cc_camellia_128_cbc(void);
 const EVP_CIPHER * EVP_cc_camellia_192_cbc(void);
 const EVP_CIPHER * EVP_cc_camellia_256_cbc(void);
index 699fc667b09a0c9fa98eb01030d84fdd3cf97e47..9e063545e168342462156568b95de987be53e3ba 100644 (file)
@@ -83,7 +83,10 @@ aes_do_cipher(EVP_CIPHER_CTX *ctx,
              unsigned int size)
 {
     AES_KEY *k = ctx->cipher_data;
-    AES_cbc_encrypt(in, out, size, k, ctx->iv, ctx->encrypt);
+    if (ctx->flags & EVP_CIPH_CFB8_MODE)
+        AES_cfb8_encrypt(in, out, size, k, ctx->iv, ctx->encrypt);
+    else
+        AES_cbc_encrypt(in, out, size, k, ctx->iv, ctx->encrypt);
     return 1;
 }
 
@@ -175,6 +178,94 @@ EVP_hcrypto_aes_256_cbc(void)
     return &aes_256_cbc;
 }
 
+/**
+ * The AES-128 CFB8 cipher type (hcrypto)
+ *
+ * @return the AES-128 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_hcrypto_aes_128_cfb8(void)
+{
+    static const EVP_CIPHER aes_128_cfb8 = {
+       0,
+       1,
+       16,
+       16,
+       EVP_CIPH_CFB8_MODE,
+       aes_init,
+       aes_do_cipher,
+       NULL,
+       sizeof(AES_KEY),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+
+    return &aes_128_cfb8;
+}
+
+/**
+ * The AES-192 CFB8 cipher type (hcrypto)
+ *
+ * @return the AES-192 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_hcrypto_aes_192_cfb8(void)
+{
+    static const EVP_CIPHER aes_192_cfb8 = {
+       0,
+       1,
+       24,
+       16,
+       EVP_CIPH_CFB8_MODE,
+       aes_init,
+       aes_do_cipher,
+       NULL,
+       sizeof(AES_KEY),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &aes_192_cfb8;
+}
+
+/**
+ * The AES-256 CFB8 cipher type (hcrypto)
+ *
+ * @return the AES-256 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_hcrypto_aes_256_cfb8(void)
+{
+    static const EVP_CIPHER aes_256_cfb8 = {
+       0,
+       1,
+       32,
+       16,
+       EVP_CIPH_CFB8_MODE,
+       aes_init,
+       aes_do_cipher,
+       NULL,
+       sizeof(AES_KEY),
+       NULL,
+       NULL,
+       NULL,
+       NULL
+    };
+    return &aes_256_cfb8;
+}
+
 /**
  * The message digest SHA256 - hcrypto
  *
index c0fb89af7177327744fc97df48c269e641d6971a..7915046bdcea12852c8fc67585e20f79cf225055 100644 (file)
@@ -47,6 +47,9 @@
 #define EVP_hcrypto_aes_128_cbc hc_EVP_hcrypto_aes_128_cbc
 #define EVP_hcrypto_aes_192_cbc hc_EVP_hcrypto_aes_192_cbc
 #define EVP_hcrypto_aes_256_cbc hc_EVP_hcrypto_aes_256_cbc
+#define EVP_hcrypto_aes_128_cfb8 hc_EVP_hcrypto_aes_128_cfb8
+#define EVP_hcrypto_aes_192_cfb8 hc_EVP_hcrypto_aes_192_cfb8
+#define EVP_hcrypto_aes_256_cfb8 hc_EVP_hcrypto_aes_256_cfb8
 #define EVP_hcrypto_rc4 hc_EVP_hcrypto_rc4
 #define EVP_hcrypto_rc4_40 hc_EVP_hcrypto_rc4_40
 #define EVP_hcrypto_rc2_40_cbc hc_EVP_hcrypto_rc2_40_cbc
@@ -82,6 +85,10 @@ const EVP_CIPHER * EVP_hcrypto_aes_128_cbc(void);
 const EVP_CIPHER * EVP_hcrypto_aes_192_cbc(void);
 const EVP_CIPHER * EVP_hcrypto_aes_256_cbc(void);
 
+const EVP_CIPHER * EVP_hcrypto_aes_128_cfb8(void);
+const EVP_CIPHER * EVP_hcrypto_aes_192_cfb8(void);
+const EVP_CIPHER * EVP_hcrypto_aes_256_cfb8(void);
+
 const EVP_CIPHER * EVP_hcrypto_camellia_128_cbc(void);
 const EVP_CIPHER * EVP_hcrypto_camellia_192_cbc(void);
 const EVP_CIPHER * EVP_hcrypto_camellia_256_cbc(void);
index 72787e185f8a2602d17f8d1ebc0fe5079a0ee881..da1a8940be865962f20a75b18832c436d9d932c0 100644 (file)
@@ -356,6 +356,7 @@ EVP_Digest(const void *data, size_t dsize, void *hash, unsigned int *hsize,
 const EVP_MD *
 EVP_sha256(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, sha256);
 }
 
@@ -370,6 +371,7 @@ EVP_sha256(void)
 const EVP_MD *
 EVP_sha1(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, sha1);
 }
 
@@ -385,6 +387,7 @@ const EVP_MD *
 EVP_sha(void) HC_DEPRECATED
     
 {
+    hcrypto_validate();
     return EVP_sha1();
 }
 
@@ -399,6 +402,7 @@ EVP_sha(void) HC_DEPRECATED
 const EVP_MD *
 EVP_md5(void) HC_DEPRECATED_CRYPTO
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, md5);
 }
 
@@ -413,6 +417,7 @@ EVP_md5(void) HC_DEPRECATED_CRYPTO
 const EVP_MD *
 EVP_md4(void) HC_DEPRECATED_CRYPTO
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, md4);
 }
 
@@ -427,6 +432,7 @@ EVP_md4(void) HC_DEPRECATED_CRYPTO
 const EVP_MD *
 EVP_md2(void) HC_DEPRECATED_CRYPTO
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, md2);
 }
 
@@ -768,6 +774,10 @@ EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *c, ENGINE *engine,
 
     case EVP_CIPH_STREAM_CIPHER:
        break;
+    case EVP_CIPH_CFB8_MODE:
+       if (iv)
+           memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx));
+       break;
 
     default:
        return 0;
@@ -996,6 +1006,7 @@ EVP_enc_null(void)
 const EVP_CIPHER *
 EVP_rc2_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, rc2_cbc);
 }
 
@@ -1010,6 +1021,7 @@ EVP_rc2_cbc(void)
 const EVP_CIPHER *
 EVP_rc2_40_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, rc2_40_cbc);
 }
 
@@ -1024,6 +1036,7 @@ EVP_rc2_40_cbc(void)
 const EVP_CIPHER *
 EVP_rc2_64_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, rc2_64_cbc);
 }
 
@@ -1038,6 +1051,7 @@ EVP_rc2_64_cbc(void)
 const EVP_CIPHER *
 EVP_rc4(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, rc4);
 }
 
@@ -1052,6 +1066,7 @@ EVP_rc4(void)
 const EVP_CIPHER *
 EVP_rc4_40(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, rc4_40);
 }
 
@@ -1066,6 +1081,7 @@ EVP_rc4_40(void)
 const EVP_CIPHER *
 EVP_des_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, des_cbc);
 }
 
@@ -1080,6 +1096,7 @@ EVP_des_cbc(void)
 const EVP_CIPHER *
 EVP_des_ede3_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, des_ede3_cbc);
 }
 
@@ -1094,6 +1111,7 @@ EVP_des_ede3_cbc(void)
 const EVP_CIPHER *
 EVP_aes_128_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, aes_128_cbc);
 }
 
@@ -1108,6 +1126,7 @@ EVP_aes_128_cbc(void)
 const EVP_CIPHER *
 EVP_aes_192_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, aes_192_cbc);
 }
 
@@ -1122,9 +1141,55 @@ EVP_aes_192_cbc(void)
 const EVP_CIPHER *
 EVP_aes_256_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, aes_256_cbc);
 }
 
+/**
+ * The AES-128 cipher type
+ *
+ * @return the AES-128 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_aes_128_cfb8(void)
+{
+    hcrypto_validate();
+    return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, aes_128_cfb8);
+}
+
+/**
+ * The AES-192 cipher type
+ *
+ * @return the AES-192 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_aes_192_cfb8(void)
+{
+    hcrypto_validate();
+    return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, aes_192_cfb8);
+}
+
+/**
+ * The AES-256 cipher type
+ *
+ * @return the AES-256 EVP_CIPHER pointer.
+ *
+ * @ingroup hcrypto_evp
+ */
+
+const EVP_CIPHER *
+EVP_aes_256_cfb8(void)
+{
+    hcrypto_validate();
+    return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, aes_256_cfb8);
+}
+
 /**
  * The Camellia-128 cipher type
  *
@@ -1136,6 +1201,7 @@ EVP_aes_256_cbc(void)
 const EVP_CIPHER *
 EVP_camellia_128_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, camellia_128_cbc);
 }
 
@@ -1150,6 +1216,7 @@ EVP_camellia_128_cbc(void)
 const EVP_CIPHER *
 EVP_camellia_192_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, camellia_192_cbc);
 }
 
@@ -1164,6 +1231,7 @@ EVP_camellia_192_cbc(void)
 const EVP_CIPHER *
 EVP_camellia_256_cbc(void)
 {
+    hcrypto_validate();
     return EVP_DEF_OP(HCRYPTO_DEF_PROVIDER, camellia_256_cbc);
 }
 
@@ -1179,6 +1247,9 @@ static const struct cipher_name {
     { "aes-128-cbc", EVP_aes_128_cbc },
     { "aes-192-cbc", EVP_aes_192_cbc },
     { "aes-256-cbc", EVP_aes_256_cbc },
+    { "aes-128-cfb8", EVP_aes_128_cfb8 },
+    { "aes-192-cfb8", EVP_aes_192_cfb8 },
+    { "aes-256-cfb8", EVP_aes_256_cfb8 },
     { "camellia-128-cbc", EVP_camellia_128_cbc },
     { "camellia-192-cbc", EVP_camellia_192_cbc },
     { "camellia-256-cbc", EVP_camellia_256_cbc }
@@ -1243,7 +1314,8 @@ EVP_BytesToKey(const EVP_CIPHER *type,
               void *keydata,
               void *ivdata)
 {
-    int ivlen, keylen, first = 0;
+    unsigned int ivlen, keylen;
+    int first = 0;
     unsigned int mds = 0, i;
     unsigned char *key = keydata;
     unsigned char *iv = ivdata;
index ae92ab4899818b6ca12c1839db8b4753e03921f6..03ec175d5976784eaa7774d76bf9b5d8b221f308 100644 (file)
@@ -74,6 +74,9 @@
 #define EVP_aes_128_cbc hc_EVP_aes_128_cbc
 #define EVP_aes_192_cbc hc_EVP_aes_192_cbc
 #define EVP_aes_256_cbc hc_EVP_aes_256_cbc
+#define EVP_aes_128_cfb8 hc_EVP_aes_128_cfb8
+#define EVP_aes_192_cfb8 hc_EVP_aes_192_cfb8
+#define EVP_aes_256_cfb8 hc_EVP_aes_256_cfb8
 
 #define EVP_des_cbc hc_EVP_des_cbc
 #define EVP_des_ede3_cbc hc_EVP_des_ede3_cbc
 #define        OpenSSL_add_all_algorithms_noconf hc_OpenSSL_add_all_algorithms_noconf
 #define EVP_CIPHER_CTX_ctrl hc_EVP_CIPHER_CTX_ctrl
 #define EVP_CIPHER_CTX_rand_key hc_EVP_CIPHER_CTX_rand_key
+#define hcrypto_validate hc_hcrypto_validate
 
 /*
  *
@@ -129,6 +133,7 @@ struct hc_CIPHER {
      */
 #define EVP_CIPH_STREAM_CIPHER         0
 #define EVP_CIPH_CBC_MODE              2
+#define EVP_CIPH_CFB8_MODE              4
 #define EVP_CIPH_MODE                  0x7
 
 #define EVP_CIPH_VARIABLE_LENGTH       0x008 /* variable key length */
@@ -224,6 +229,9 @@ const EVP_MD *EVP_sha256(void);
 const EVP_CIPHER * EVP_aes_128_cbc(void);
 const EVP_CIPHER * EVP_aes_192_cbc(void);
 const EVP_CIPHER * EVP_aes_256_cbc(void);
+const EVP_CIPHER * EVP_aes_128_cfb8(void);
+const EVP_CIPHER * EVP_aes_192_cfb8(void);
+const EVP_CIPHER * EVP_aes_256_cfb8(void);
 HC_DEPRECATED_CRYPTO const EVP_CIPHER * EVP_des_cbc(void);
 const EVP_CIPHER * EVP_des_ede3_cbc(void);
 const EVP_CIPHER * EVP_enc_null(void);
@@ -309,6 +317,9 @@ void        OpenSSL_add_all_algorithms(void);
 void   OpenSSL_add_all_algorithms_conf(void);
 void   OpenSSL_add_all_algorithms_noconf(void);
 
+void
+hcrypto_validate(void);
+
 HC_CPP_END
 
 #endif /* HEIM_EVP_H */
index 78a795f2a7ae9dfaba7d306b3d9826342a62a8b7..cfec9cf3f34deffa27b6282c3386376a0b4d145e 100644 (file)
@@ -37,9 +37,6 @@
 #ifndef __hash_h__
 #define __hash_h__
 
-#include <stdlib.h>
-#include <string.h>
-#include <stddef.h>
 #ifdef KRB5
 #include <krb5-types.h>
 #endif
index 4e47a76ce2970e6e277fb3e76641115290170f8d..0079bafd02a39402a716e8efaca031e1152a0e92 100644 (file)
@@ -3016,7 +3016,7 @@ STATIC mp_result s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
 {
   mp_digit  *db, *dbt, umu, d;
   mpz_t     temp[3]; 
-  mp_result res;
+  mp_result res = 0;
   int       last = 0;
 
   umu = MP_USED(mu); db = MP_DIGITS(b); dbt = db + MP_USED(b) - 1;
diff --git a/source4/heimdal/lib/hcrypto/libtommath/LICENSE b/source4/heimdal/lib/hcrypto/libtommath/LICENSE
new file mode 100644 (file)
index 0000000..5baa792
--- /dev/null
@@ -0,0 +1,4 @@
+LibTomMath is hereby released into the Public Domain.  
+
+-- Tom St Denis
+
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn.ilg b/source4/heimdal/lib/hcrypto/libtommath/bn.ilg
new file mode 100644 (file)
index 0000000..3c859f0
--- /dev/null
@@ -0,0 +1,6 @@
+This is makeindex, version 2.14 [02-Oct-2002] (kpathsea + Thai support).
+Scanning input file bn.idx....done (79 entries accepted, 0 rejected).
+Sorting entries....done (511 comparisons).
+Generating output file bn.ind....done (82 lines written, 0 warnings).
+Output written in bn.ind.
+Transcript written in bn.ilg.
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn.ind b/source4/heimdal/lib/hcrypto/libtommath/bn.ind
new file mode 100644 (file)
index 0000000..c099b52
--- /dev/null
@@ -0,0 +1,82 @@
+\begin{theindex}
+
+  \item mp\_add, \hyperpage{31}
+  \item mp\_add\_d, \hyperpage{56}
+  \item mp\_and, \hyperpage{31}
+  \item mp\_clear, \hyperpage{12}
+  \item mp\_clear\_multi, \hyperpage{13}
+  \item mp\_cmp, \hyperpage{25}
+  \item mp\_cmp\_d, \hyperpage{26}
+  \item mp\_cmp\_mag, \hyperpage{23}
+  \item mp\_div, \hyperpage{32}
+  \item mp\_div\_2, \hyperpage{28}
+  \item mp\_div\_2d, \hyperpage{30}
+  \item mp\_div\_d, \hyperpage{56}
+  \item mp\_dr\_reduce, \hyperpage{45}
+  \item mp\_dr\_setup, \hyperpage{45}
+  \item MP\_EQ, \hyperpage{23}
+  \item mp\_error\_to\_string, \hyperpage{9}
+  \item mp\_expt\_d, \hyperpage{47}
+  \item mp\_exptmod, \hyperpage{47}
+  \item mp\_exteuclid, \hyperpage{55}
+  \item mp\_gcd, \hyperpage{55}
+  \item mp\_get\_int, \hyperpage{20}
+  \item mp\_grow, \hyperpage{17}
+  \item MP\_GT, \hyperpage{23}
+  \item mp\_init, \hyperpage{11}
+  \item mp\_init\_copy, \hyperpage{14}
+  \item mp\_init\_multi, \hyperpage{13}
+  \item mp\_init\_set, \hyperpage{21}
+  \item mp\_init\_set\_int, \hyperpage{21}
+  \item mp\_init\_size, \hyperpage{15}
+  \item mp\_int, \hyperpage{10}
+  \item mp\_invmod, \hyperpage{56}
+  \item mp\_jacobi, \hyperpage{56}
+  \item mp\_lcm, \hyperpage{56}
+  \item mp\_lshd, \hyperpage{30}
+  \item MP\_LT, \hyperpage{23}
+  \item MP\_MEM, \hyperpage{9}
+  \item mp\_mod, \hyperpage{39}
+  \item mp\_mod\_d, \hyperpage{56}
+  \item mp\_montgomery\_calc\_normalization, \hyperpage{42}
+  \item mp\_montgomery\_reduce, \hyperpage{42}
+  \item mp\_montgomery\_setup, \hyperpage{42}
+  \item mp\_mul, \hyperpage{33}
+  \item mp\_mul\_2, \hyperpage{28}
+  \item mp\_mul\_2d, \hyperpage{29}
+  \item mp\_mul\_d, \hyperpage{56}
+  \item mp\_n\_root, \hyperpage{48}
+  \item mp\_neg, \hyperpage{31, 32}
+  \item MP\_NO, \hyperpage{9}
+  \item MP\_OKAY, \hyperpage{9}
+  \item mp\_or, \hyperpage{31}
+  \item mp\_prime\_fermat, \hyperpage{49}
+  \item mp\_prime\_is\_divisible, \hyperpage{49}
+  \item mp\_prime\_is\_prime, \hyperpage{51}
+  \item mp\_prime\_miller\_rabin, \hyperpage{50}
+  \item mp\_prime\_next\_prime, \hyperpage{51}
+  \item mp\_prime\_rabin\_miller\_trials, \hyperpage{50}
+  \item mp\_prime\_random, \hyperpage{51}
+  \item mp\_prime\_random\_ex, \hyperpage{52}
+  \item mp\_radix\_size, \hyperpage{53}
+  \item mp\_read\_radix, \hyperpage{53}
+  \item mp\_read\_unsigned\_bin, \hyperpage{54}
+  \item mp\_reduce, \hyperpage{40}
+  \item mp\_reduce\_2k, \hyperpage{46}
+  \item mp\_reduce\_2k\_setup, \hyperpage{46}
+  \item mp\_reduce\_setup, \hyperpage{40}
+  \item mp\_rshd, \hyperpage{30}
+  \item mp\_set, \hyperpage{19}
+  \item mp\_set\_int, \hyperpage{20}
+  \item mp\_shrink, \hyperpage{16}
+  \item mp\_sqr, \hyperpage{35}
+  \item mp\_sub, \hyperpage{31}
+  \item mp\_sub\_d, \hyperpage{56}
+  \item mp\_to\_unsigned\_bin, \hyperpage{54}
+  \item mp\_toradix, \hyperpage{53}
+  \item mp\_unsigned\_bin\_size, \hyperpage{54}
+  \item MP\_VAL, \hyperpage{9}
+  \item mp\_xor, \hyperpage{31}
+  \item MP\_YES, \hyperpage{9}
+
+\end{theindex}
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_error.c b/source4/heimdal/lib/hcrypto/libtommath/bn_error.c
new file mode 100644 (file)
index 0000000..b1b7177
--- /dev/null
@@ -0,0 +1,47 @@
+#include <tommath.h>
+#ifdef BN_ERROR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+static const struct {
+     int code;
+     char *msg;
+} msgs[] = {
+     { MP_OKAY, "Successful" },
+     { MP_MEM,  "Out of heap" },
+     { MP_VAL,  "Value out of range" }
+};
+
+/* return a char * string for a given code */
+char *mp_error_to_string(int code)
+{
+   int x;
+
+   /* scan the lookup table for the given message */
+   for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
+       if (msgs[x].code == code) {
+          return msgs[x].msg;
+       }
+   }
+
+   /* generic reply for invalid code */
+   return "Invalid error code";
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_error.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_fast_mp_invmod.c b/source4/heimdal/lib/hcrypto/libtommath/bn_fast_mp_invmod.c
new file mode 100644 (file)
index 0000000..ff03dff
--- /dev/null
@@ -0,0 +1,148 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c b/source4/heimdal/lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c
new file mode 100644 (file)
index 0000000..b6c0694
--- /dev/null
@@ -0,0 +1,172 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c b/source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c
new file mode 100644 (file)
index 0000000..91e10d6
--- /dev/null
@@ -0,0 +1,107 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c b/source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c
new file mode 100644 (file)
index 0000000..5b114d7
--- /dev/null
@@ -0,0 +1,98 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c b/source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c
new file mode 100644 (file)
index 0000000..19e92ef
--- /dev/null
@@ -0,0 +1,114 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_2expt.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_2expt.c
new file mode 100644 (file)
index 0000000..f422ffc
--- /dev/null
@@ -0,0 +1,48 @@
+#include <tommath.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
+ */
+
+/* computes a = 2**b 
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+int
+mp_2expt (mp_int * a, int b)
+{
+  int     res;
+
+  /* zero a as per default */
+  mp_zero (a);
+
+  /* grow a to accomodate the single bit */
+  if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* set the used count of where the bit will go */
+  a->used = b / DIGIT_BIT + 1;
+
+  /* put the single bit in its place */
+  a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_2expt.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_abs.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_abs.c
new file mode 100644 (file)
index 0000000..09dd722
--- /dev/null
@@ -0,0 +1,43 @@
+#include <tommath.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
+ */
+
+/* b = |a| 
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+int
+mp_abs (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  /* copy a to b */
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* force the sign of b to positive */
+  b->sign = MP_ZPOS;
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_abs.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_add.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_add.c
new file mode 100644 (file)
index 0000000..be20644
--- /dev/null
@@ -0,0 +1,53 @@
+#include <tommath.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
+ */
+
+/* high level addition (handles signs) */
+int mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  /* get sign of both inputs */
+  sa = a->sign;
+  sb = b->sign;
+
+  /* handle two cases, not four */
+  if (sa == sb) {
+    /* both positive or both negative */
+    /* add their magnitudes, copy the sign */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* one positive, the other negative */
+    /* subtract the one with the greater magnitude from */
+    /* the one of the lesser magnitude.  The result gets */
+    /* the sign of the one with the greater magnitude. */
+    if (mp_cmp_mag (a, b) == MP_LT) {
+      c->sign = sb;
+      res = s_mp_sub (b, a, c);
+    } else {
+      c->sign = sa;
+      res = s_mp_sub (a, b, c);
+    }
+  }
+  return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_add.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_add_d.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_add_d.c
new file mode 100644 (file)
index 0000000..8ca36c1
--- /dev/null
@@ -0,0 +1,112 @@
+#include <tommath.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
+ */
+
+/* single digit addition */
+int
+mp_add_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  int     res, ix, oldused;
+  mp_digit *tmpa, *tmpc, mu;
+
+  /* grow c as required */
+  if (c->alloc < a->used + 1) {
+     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* if a is negative and |a| >= b, call c = |a| - b */
+  if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
+     /* temporarily fix sign of a */
+     a->sign = MP_ZPOS;
+
+     /* c = |a| - b */
+     res = mp_sub_d(a, b, c);
+
+     /* fix sign  */
+     a->sign = c->sign = MP_NEG;
+
+     /* clamp */
+     mp_clamp(c);
+
+     return res;
+  }
+
+  /* old number of used digits in c */
+  oldused = c->used;
+
+  /* sign always positive */
+  c->sign = MP_ZPOS;
+
+  /* source alias */
+  tmpa    = a->dp;
+
+  /* destination alias */
+  tmpc    = c->dp;
+
+  /* if a is positive */
+  if (a->sign == MP_ZPOS) {
+     /* add digit, after this we're propagating
+      * the carry.
+      */
+     *tmpc   = *tmpa++ + b;
+     mu      = *tmpc >> DIGIT_BIT;
+     *tmpc++ &= MP_MASK;
+
+     /* now handle rest of the digits */
+     for (ix = 1; ix < a->used; ix++) {
+        *tmpc   = *tmpa++ + mu;
+        mu      = *tmpc >> DIGIT_BIT;
+        *tmpc++ &= MP_MASK;
+     }
+     /* set final carry */
+     ix++;
+     *tmpc++  = mu;
+
+     /* setup size */
+     c->used = a->used + 1;
+  } else {
+     /* a was negative and |a| < b */
+     c->used  = 1;
+
+     /* the result is a single digit */
+     if (a->used == 1) {
+        *tmpc++  =  b - a->dp[0];
+     } else {
+        *tmpc++  =  b;
+     }
+
+     /* setup count so the clearing of oldused
+      * can fall through correctly
+      */
+     ix       = 1;
+  }
+
+  /* now zero to oldused */
+  while (ix++ < oldused) {
+     *tmpc++ = 0;
+  }
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_add_d.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_addmod.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_addmod.c
new file mode 100644 (file)
index 0000000..6d8afe1
--- /dev/null
@@ -0,0 +1,41 @@
+#include <tommath.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
+ */
+
+/* d = a + b (mod c) */
+int
+mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_add (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_addmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_and.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_and.c
new file mode 100644 (file)
index 0000000..8ea2287
--- /dev/null
@@ -0,0 +1,57 @@
+#include <tommath.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
+ */
+
+/* AND two ints together */
+int
+mp_and (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+    t.dp[ix] &= x->dp[ix];
+  }
+
+  /* zero digits above the last from the smallest mp_int */
+  for (; ix < t.used; ix++) {
+    t.dp[ix] = 0;
+  }
+
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_and.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_clamp.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_clamp.c
new file mode 100644 (file)
index 0000000..359c2ff
--- /dev/null
@@ -0,0 +1,44 @@
+#include <tommath.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
+ */
+
+/* trim unused digits 
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast.  Also fixes the sign if there
+ * are no more leading digits
+ */
+void
+mp_clamp (mp_int * a)
+{
+  /* decrease used while the most significant digit is
+   * zero.
+   */
+  while (a->used > 0 && a->dp[a->used - 1] == 0) {
+    --(a->used);
+  }
+
+  /* reset the sign flag if used == 0 */
+  if (a->used == 0) {
+    a->sign = MP_ZPOS;
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_clamp.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_clear.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_clear.c
new file mode 100644 (file)
index 0000000..a65f0a3
--- /dev/null
@@ -0,0 +1,44 @@
+#include <tommath.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
+ */
+
+/* clear one (frees)  */
+void
+mp_clear (mp_int * a)
+{
+  int i;
+
+  /* only do anything if a hasn't been freed previously */
+  if (a->dp != NULL) {
+    /* first zero the digits */
+    for (i = 0; i < a->used; i++) {
+        a->dp[i] = 0;
+    }
+
+    /* free ram */
+    XFREE(a->dp);
+
+    /* reset members to make debugging easier */
+    a->dp    = NULL;
+    a->alloc = a->used = 0;
+    a->sign  = MP_ZPOS;
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_clear.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_clear_multi.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_clear_multi.c
new file mode 100644 (file)
index 0000000..daaea79
--- /dev/null
@@ -0,0 +1,34 @@
+#include <tommath.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
+ */
+#include <stdarg.h>
+
+void mp_clear_multi(mp_int *mp, ...) 
+{
+    mp_int* next_mp = mp;
+    va_list args;
+    va_start(args, mp);
+    while (next_mp != NULL) {
+        mp_clear(next_mp);
+        next_mp = va_arg(args, mp_int*);
+    }
+    va_end(args);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_clear_multi.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp.c
new file mode 100644 (file)
index 0000000..533f36b
--- /dev/null
@@ -0,0 +1,43 @@
+#include <tommath.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
+ */
+
+/* compare two ints (signed)*/
+int
+mp_cmp (mp_int * a, mp_int * b)
+{
+  /* compare based on sign */
+  if (a->sign != b->sign) {
+     if (a->sign == MP_NEG) {
+        return MP_LT;
+     } else {
+        return MP_GT;
+     }
+  }
+  
+  /* compare digits */
+  if (a->sign == MP_NEG) {
+     /* if negative compare opposite direction */
+     return mp_cmp_mag(b, a);
+  } else {
+     return mp_cmp_mag(a, b);
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cmp.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp_d.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp_d.c
new file mode 100644 (file)
index 0000000..724c1c3
--- /dev/null
@@ -0,0 +1,44 @@
+#include <tommath.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
+ */
+
+/* compare a digit */
+int mp_cmp_d(mp_int * a, mp_digit b)
+{
+  /* compare based on sign */
+  if (a->sign == MP_NEG) {
+    return MP_LT;
+  }
+
+  /* compare based on magnitude */
+  if (a->used > 1) {
+    return MP_GT;
+  }
+
+  /* compare the only digit of a to b */
+  if (a->dp[0] > b) {
+    return MP_GT;
+  } else if (a->dp[0] < b) {
+    return MP_LT;
+  } else {
+    return MP_EQ;
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp_mag.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp_mag.c
new file mode 100644 (file)
index 0000000..693eb7c
--- /dev/null
@@ -0,0 +1,55 @@
+#include <tommath.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
+ */
+
+/* compare maginitude of two ints (unsigned) */
+int mp_cmp_mag (mp_int * a, mp_int * b)
+{
+  int     n;
+  mp_digit *tmpa, *tmpb;
+
+  /* compare based on # of non-zero digits */
+  if (a->used > b->used) {
+    return MP_GT;
+  }
+  
+  if (a->used < b->used) {
+    return MP_LT;
+  }
+
+  /* alias for a */
+  tmpa = a->dp + (a->used - 1);
+
+  /* alias for b */
+  tmpb = b->dp + (a->used - 1);
+
+  /* compare based on digits  */
+  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+    if (*tmpa > *tmpb) {
+      return MP_GT;
+    }
+
+    if (*tmpa < *tmpb) {
+      return MP_LT;
+    }
+  }
+  return MP_EQ;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cmp_mag.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c
new file mode 100644 (file)
index 0000000..66d1a74
--- /dev/null
@@ -0,0 +1,53 @@
+#include <tommath.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
+ */
+
+static const int lnz[16] = { 
+   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a)
+{
+   int x;
+   mp_digit q, qq;
+
+   /* easy out */
+   if (mp_iszero(a) == 1) {
+      return 0;
+   }
+
+   /* scan lower digits until non-zero */
+   for (x = 0; x < a->used && a->dp[x] == 0; x++);
+   q = a->dp[x];
+   x *= DIGIT_BIT;
+
+   /* now scan this digit until a 1 is found */
+   if ((q & 1) == 0) {
+      do {
+         qq  = q & 15;
+         x  += lnz[qq];
+         q >>= 4;
+      } while (qq == 0);
+   }
+   return x;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_cnt_lsb.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_copy.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_copy.c
new file mode 100644 (file)
index 0000000..b0de16d
--- /dev/null
@@ -0,0 +1,68 @@
+#include <tommath.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
+ */
+
+/* copy, b = a */
+int
+mp_copy (mp_int * a, mp_int * b)
+{
+  int     res, n;
+
+  /* if dst == src do nothing */
+  if (a == b) {
+    return MP_OKAY;
+  }
+
+  /* grow dest */
+  if (b->alloc < a->used) {
+     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero b and copy the parameters over */
+  {
+    register mp_digit *tmpa, *tmpb;
+
+    /* pointer aliases */
+
+    /* source */
+    tmpa = a->dp;
+
+    /* destination */
+    tmpb = b->dp;
+
+    /* copy all the digits */
+    for (n = 0; n < a->used; n++) {
+      *tmpb++ = *tmpa++;
+    }
+
+    /* clear high digits */
+    for (; n < b->used; n++) {
+      *tmpb++ = 0;
+    }
+  }
+
+  /* copy used count and sign */
+  b->used = a->used;
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_copy.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_count_bits.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_count_bits.c
new file mode 100644 (file)
index 0000000..8bc5657
--- /dev/null
@@ -0,0 +1,45 @@
+#include <tommath.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
+ */
+
+/* returns the number of bits in an int */
+int
+mp_count_bits (mp_int * a)
+{
+  int     r;
+  mp_digit q;
+
+  /* shortcut */
+  if (a->used == 0) {
+    return 0;
+  }
+
+  /* get number of digits and add that */
+  r = (a->used - 1) * DIGIT_BIT;
+  
+  /* take the last digit and count the bits in it */
+  q = a->dp[a->used - 1];
+  while (q > ((mp_digit) 0)) {
+    ++r;
+    q >>= ((mp_digit) 1);
+  }
+  return r;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_count_bits.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div.c
new file mode 100644 (file)
index 0000000..aee9c94
--- /dev/null
@@ -0,0 +1,292 @@
+#include <tommath.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
+ */
+
+#ifdef BN_MP_DIV_SMALL
+
+/* slower bit-bang division... also smaller */
+int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+   mp_int ta, tb, tq, q;
+   int    res, n, n2;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+       
+  /* init our temps */
+  if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
+     return res;
+  }
+
+
+  mp_set(&tq, 1);
+  n = mp_count_bits(a) - mp_count_bits(b);
+  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+      ((res = mp_abs(b, &tb)) != MP_OKAY) || 
+      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+      goto LBL_ERR;
+  }
+
+  while (n-- >= 0) {
+     if (mp_cmp(&tb, &ta) != MP_GT) {
+        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+           goto LBL_ERR;
+        }
+     }
+     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+           goto LBL_ERR;
+     }
+  }
+
+  /* now q == quotient and ta == remainder */
+  n  = a->sign;
+  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+  if (c != NULL) {
+     mp_exch(c, &q);
+     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+  }
+  if (d != NULL) {
+     mp_exch(d, &ta);
+     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+  }
+LBL_ERR:
+   mp_clear_multi(&ta, &tb, &tq, &q, NULL);
+   return res;
+}
+
+#else
+
+/* integer signed division. 
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly 
+ * incomplete.  For example, it doesn't consider 
+ * the case where digits are removed from 'x' in 
+ * the inner loop.  It also doesn't consider the 
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as 
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  mp_int  q, x, y, t1, t2;
+  int     res, n, t, i, norm, neg;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+
+  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+    return res;
+  }
+  q.used = a->used + 2;
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    goto LBL_Q;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto LBL_T1;
+  }
+
+  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+    goto LBL_T2;
+  }
+
+  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+    goto LBL_X;
+  }
+
+  /* fix the sign */
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+  x.sign = y.sign = MP_ZPOS;
+
+  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+  norm = mp_count_bits(&y) % DIGIT_BIT;
+  if (norm < (int)(DIGIT_BIT-1)) {
+     norm = (DIGIT_BIT-1) - norm;
+     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+  } else {
+     norm = 0;
+  }
+
+  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+  n = x.used - 1;
+  t = y.used - 1;
+
+  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+    goto LBL_Y;
+  }
+
+  while (mp_cmp (&x, &y) != MP_LT) {
+    ++(q.dp[n - t]);
+    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+  }
+
+  /* reset y by shifting it back down */
+  mp_rshd (&y, n - t);
+
+  /* step 3. for i from n down to (t + 1) */
+  for (i = n; i >= (t + 1); i--) {
+    if (i > x.used) {
+      continue;
+    }
+
+    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
+     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+    if (x.dp[i] == y.dp[t]) {
+      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+    } else {
+      mp_word tmp;
+      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+      tmp |= ((mp_word) x.dp[i - 1]);
+      tmp /= ((mp_word) y.dp[t]);
+      if (tmp > (mp_word) MP_MASK)
+        tmp = MP_MASK;
+      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+    }
+
+    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
+             xi * b**2 + xi-1 * b + xi-2 
+     
+       do q{i-t-1} -= 1; 
+    */
+    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+    do {
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+      /* find left hand */
+      mp_zero (&t1);
+      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+      t1.dp[1] = y.dp[t];
+      t1.used = 2;
+      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      /* find right hand */
+      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+      t2.dp[2] = x.dp[i];
+      t2.used = 3;
+    } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+    if (x.sign == MP_NEG) {
+      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+    }
+  }
+
+  /* now q is the quotient and x is the remainder 
+   * [which we have to normalize] 
+   */
+  
+  /* get sign before writing to c */
+  x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+  if (c != NULL) {
+    mp_clamp (&q);
+    mp_exch (&q, c);
+    c->sign = neg;
+  }
+
+  if (d != NULL) {
+    mp_div_2d (&x, norm, &x, NULL);
+    mp_exch (&x, d);
+  }
+
+  res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+  return res;
+}
+
+#endif
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_2.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_2.c
new file mode 100644 (file)
index 0000000..7ee3e5b
--- /dev/null
@@ -0,0 +1,68 @@
+#include <tommath.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
+ */
+
+/* b = a/2 */
+int mp_div_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* copy */
+  if (b->alloc < a->used) {
+    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* source alias */
+    tmpa = a->dp + b->used - 1;
+
+    /* dest alias */
+    tmpb = b->dp + b->used - 1;
+
+    /* carry */
+    r = 0;
+    for (x = b->used - 1; x >= 0; x--) {
+      /* get the carry for the next iteration */
+      rr = *tmpa & 1;
+
+      /* shift the current digit, add in carry and store */
+      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+      /* forward carry to next iteration */
+      r = rr;
+    }
+
+    /* zero excess digits */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_2.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_2d.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_2d.c
new file mode 100644 (file)
index 0000000..4f7fa59
--- /dev/null
@@ -0,0 +1,97 @@
+#include <tommath.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
+ */
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+  mp_digit D, r, rr;
+  int     x, res;
+  mp_int  t;
+
+
+  /* if the shift count is <= 0 then we do no work */
+  if (b <= 0) {
+    res = mp_copy (a, c);
+    if (d != NULL) {
+      mp_zero (d);
+    }
+    return res;
+  }
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  /* get the remainder */
+  if (d != NULL) {
+    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    mp_rshd (c, b / DIGIT_BIT);
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  D = (mp_digit) (b % DIGIT_BIT);
+  if (D != 0) {
+    register mp_digit *tmpc, mask, shift;
+
+    /* mask */
+    mask = (((mp_digit)1) << D) - 1;
+
+    /* shift for lsb */
+    shift = DIGIT_BIT - D;
+
+    /* alias */
+    tmpc = c->dp + (c->used - 1);
+
+    /* carry */
+    r = 0;
+    for (x = c->used - 1; x >= 0; x--) {
+      /* get the lower  bits of this word in a temp */
+      rr = *tmpc & mask;
+
+      /* shift the current word and mix in the carry bits from the previous word */
+      *tmpc = (*tmpc >> D) | (r << shift);
+      --tmpc;
+
+      /* set the carry to the carry bits of the current word found above */
+      r = rr;
+    }
+  }
+  mp_clamp (c);
+  if (d != NULL) {
+    mp_exch (&t, d);
+  }
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_2d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_3.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_3.c
new file mode 100644 (file)
index 0000000..3c60269
--- /dev/null
@@ -0,0 +1,79 @@
+#include <tommath.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
+ */
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+int
+mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
+{
+  mp_int   q;
+  mp_word  w, t;
+  mp_digit b;
+  int      res, ix;
+  
+  /* b = 2**DIGIT_BIT / 3 */
+  b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
+
+  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+     return res;
+  }
+  
+  q.used = a->used;
+  q.sign = a->sign;
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+     if (w >= 3) {
+        /* multiply w by [1/3] */
+        t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
+
+        /* now subtract 3 * [w/3] from w, to get the remainder */
+        w -= t+t+t;
+
+        /* fixup the remainder as required since
+         * the optimization is not exact.
+         */
+        while (w >= 3) {
+           t += 1;
+           w -= 3;
+        }
+      } else {
+        t = 0;
+      }
+      q.dp[ix] = (mp_digit)t;
+  }
+
+  /* [optional] store the remainder */
+  if (d != NULL) {
+     *d = (mp_digit)w;
+  }
+
+  /* [optional] store the quotient */
+  if (c != NULL) {
+     mp_clamp(&q);
+     mp_exch(&q, c);
+  }
+  mp_clear(&q);
+  
+  return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_3.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c
new file mode 100644 (file)
index 0000000..6a26d4f
--- /dev/null
@@ -0,0 +1,115 @@
+#include <tommath.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)<<x)) {
+         *p = x;
+         return 1;
+      }
+   }
+   return 0;
+}
+
+/* single digit division (based on routine from MPI) */
+int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
+{
+  mp_int  q;
+  mp_word w;
+  mp_digit t;
+  int     res, ix;
+
+  /* cannot divide by zero */
+  if (b == 0) {
+     return MP_VAL;
+  }
+
+  /* quick outs */
+  if (b == 1 || mp_iszero(a) == 1) {
+     if (d != NULL) {
+        *d = 0;
+     }
+     if (c != NULL) {
+        return mp_copy(a, c);
+     }
+     return MP_OKAY;
+  }
+
+  /* power of two ? */
+  if (s_is_power_of_two(b, &ix) == 1) {
+     if (d != NULL) {
+        *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
+     }
+     if (c != NULL) {
+        return mp_div_2d(a, ix, c, NULL);
+     }
+     return MP_OKAY;
+  }
+
+#ifdef BN_MP_DIV_3_C
+  /* three? */
+  if (b == 3) {
+     return mp_div_3(a, c, d);
+  }
+#endif
+
+  /* no easy answer [c'est la vie].  Just division */
+  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+     return res;
+  }
+  
+  q.used = a->used;
+  q.sign = a->sign;
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+     
+     if (w >= b) {
+        t = (mp_digit)(w / b);
+        w -= ((mp_word)t) * ((mp_word)b);
+      } else {
+        t = 0;
+      }
+      q.dp[ix] = (mp_digit)t;
+  }
+  
+  if (d != NULL) {
+     *d = (mp_digit)w;
+  }
+  
+  if (c != NULL) {
+     mp_clamp(&q);
+     mp_exch(&q, c);
+  }
+  mp_clear(&q);
+  
+  return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_div_d.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2007/01/09 04:44:32 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c
new file mode 100644 (file)
index 0000000..5237344
--- /dev/null
@@ -0,0 +1,43 @@
+#include <tommath.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
+ */
+
+/* determines if a number is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a)
+{
+   int ix;
+
+   /* must be at least two digits */
+   if (a->used < 2) {
+      return 0;
+   }
+
+   /* must be of the form b**k - a [a <= b] so all
+    * but the first digit must be equal to -1 (mod b).
+    */
+   for (ix = 1; ix < a->used; ix++) {
+       if (a->dp[ix] != MP_MASK) {
+          return 0;
+       }
+   }
+   return 1;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_dr_is_modulus.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_reduce.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_reduce.c
new file mode 100644 (file)
index 0000000..e60b578
--- /dev/null
@@ -0,0 +1,94 @@
+#include <tommath.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
+ */
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ *                 Chae Hoon Lim, Pil Joong Lee,
+ *          POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input x must be in the range 0 <= x <= (n-1)**2
+ */
+int
+mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
+{
+  int      err, i, m;
+  mp_word  r;
+  mp_digit mu, *tmpx1, *tmpx2;
+
+  /* m = digits in modulus */
+  m = n->used;
+
+  /* ensure that "x" has at least 2m digits */
+  if (x->alloc < m + m) {
+    if ((err = mp_grow (x, m + m)) != MP_OKAY) {
+      return err;
+    }
+  }
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+  /* aliases for digits */
+  /* alias for lower half of x */
+  tmpx1 = x->dp;
+
+  /* alias for upper half of x, or x/B**m */
+  tmpx2 = x->dp + m;
+
+  /* set carry to zero */
+  mu = 0;
+
+  /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
+  for (i = 0; i < m; i++) {
+      r         = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
+      *tmpx1++  = (mp_digit)(r & MP_MASK);
+      mu        = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
+  }
+
+  /* set final carry */
+  *tmpx1++ = mu;
+
+  /* zero words above m */
+  for (i = m + 1; i < x->used; i++) {
+      *tmpx1++ = 0;
+  }
+
+  /* clamp, sub and return */
+  mp_clamp (x);
+
+  /* if x >= n then subtract and reduce again
+   * Each successive "recursion" makes the input smaller and smaller.
+   */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    s_mp_sub(x, n, x);
+    goto top;
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_dr_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_setup.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_setup.c
new file mode 100644 (file)
index 0000000..1d7d856
--- /dev/null
@@ -0,0 +1,32 @@
+#include <tommath.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
+ */
+
+/* determines the setup value */
+void mp_dr_setup(mp_int *a, mp_digit *d)
+{
+   /* the casts are required if DIGIT_BIT is one less than
+    * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
+    */
+   *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - 
+        ((mp_word)a->dp[0]));
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_dr_setup.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exch.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exch.c
new file mode 100644 (file)
index 0000000..38574e0
--- /dev/null
@@ -0,0 +1,34 @@
+#include <tommath.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
+ */
+
+/* swap the elements of two integers, for cases where you can't simply swap the 
+ * mp_int pointers around
+ */
+void
+mp_exch (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+
+  t  = *a;
+  *a = *b;
+  *b = t;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exch.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_expt_d.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_expt_d.c
new file mode 100644 (file)
index 0000000..4bdc2d1
--- /dev/null
@@ -0,0 +1,57 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exptmod.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exptmod.c
new file mode 100644 (file)
index 0000000..0231916
--- /dev/null
@@ -0,0 +1,112 @@
+#include <tommath.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
+ */
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions.  Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted alot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+  int dr;
+
+  /* modulus P must be positive */
+  if (P->sign == MP_NEG) {
+     return MP_VAL;
+  }
+
+  /* if exponent X is negative we have to recurse */
+  if (X->sign == MP_NEG) {
+#ifdef BN_MP_INVMOD_C
+     mp_int tmpG, tmpX;
+     int err;
+
+     /* first compute 1/G mod P */
+     if ((err = mp_init(&tmpG)) != MP_OKAY) {
+        return err;
+     }
+     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+
+     /* now get |X| */
+     if ((err = mp_init(&tmpX)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+        mp_clear_multi(&tmpG, &tmpX, NULL);
+        return err;
+     }
+
+     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+     err = mp_exptmod(&tmpG, &tmpX, P, Y);
+     mp_clear_multi(&tmpG, &tmpX, NULL);
+     return err;
+#else 
+     /* no invmod */
+     return MP_VAL;
+#endif
+  }
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
+  if (mp_reduce_is_2k_l(P) == MP_YES) {
+     return s_mp_exptmod(G, X, P, Y, 1);
+  }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+  /* is it a DR modulus? */
+  dr = mp_dr_is_modulus(P);
+#else
+  /* default to no */
+  dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+  /* if not, is it a unrestricted DR modulus? */
+  if (dr == 0) {
+     dr = mp_reduce_is_2k(P) << 1;
+  }
+#endif
+    
+  /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+  if (mp_isodd (P) == 1 || dr !=  0) {
+    return mp_exptmod_fast (G, X, P, Y, dr);
+  } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+    /* otherwise use the generic Barrett reduction technique */
+    return s_mp_exptmod (G, X, P, Y, 0);
+#else
+    /* no exptmod for evens */
+    return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+  }
+#endif
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exptmod.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exptmod_fast.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exptmod_fast.c
new file mode 100644 (file)
index 0000000..2a3b3c9
--- /dev/null
@@ -0,0 +1,321 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exteuclid.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exteuclid.c
new file mode 100644 (file)
index 0000000..e6c4ce2
--- /dev/null
@@ -0,0 +1,82 @@
+#include <tommath.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
+ */
+
+/* Extended euclidean algorithm of (a, b) produces 
+   a*u1 + b*u2 = u3
+ */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
+{
+   mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
+   int err;
+
+   if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
+      return err;
+   }
+
+   /* initialize, (u1,u2,u3) = (1,0,a) */
+   mp_set(&u1, 1);
+   if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto _ERR; }
+
+   /* initialize, (v1,v2,v3) = (0,1,b) */
+   mp_set(&v2, 1);
+   if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto _ERR; }
+
+   /* loop while v3 != 0 */
+   while (mp_iszero(&v3) == MP_NO) {
+       /* q = u3/v3 */
+       if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto _ERR; }
+
+       /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
+       if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto _ERR; }
+       if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto _ERR; }
+       if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto _ERR; }
+
+       /* (u1,u2,u3) = (v1,v2,v3) */
+       if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto _ERR; }
+
+       /* (v1,v2,v3) = (t1,t2,t3) */
+       if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; }
+   }
+
+   /* make sure U3 >= 0 */
+   if (u3.sign == MP_NEG) {
+      mp_neg(&u1, &u1);
+      mp_neg(&u2, &u2);
+      mp_neg(&u3, &u3);
+   }
+
+   /* copy result out */
+   if (U1 != NULL) { mp_exch(U1, &u1); }
+   if (U2 != NULL) { mp_exch(U2, &u2); }
+   if (U3 != NULL) { mp_exch(U3, &u3); }
+
+   err = MP_OKAY;
+_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
+   return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_exteuclid.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_find_prime.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_find_prime.c
new file mode 100644 (file)
index 0000000..0458744
--- /dev/null
@@ -0,0 +1,26 @@
+/* TomsFastMath, a fast ISO C bignum library.
+ * 
+ * This project is public domain and free for all purposes.
+ * 
+ * Love Hornquist Astrand <lha@h5l.org>
+ */
+#include <tommath.h>
+
+int mp_find_prime(mp_int *a)
+{
+  int res;
+
+  if (mp_iseven(a))
+    mp_add_d(a, 1, a);
+
+  do {
+
+    if ((res = mp_isprime(a)) == MP_NO) {
+      mp_add_d(a, 2, a);
+      continue;
+    }
+
+  } while (res != MP_YES);
+
+  return res;
+}
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_fread.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_fread.c
new file mode 100644 (file)
index 0000000..b344b6f
--- /dev/null
@@ -0,0 +1,67 @@
+#include <tommath.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
+ */
+
+/* read a bigint from a file stream in ASCII */
+int mp_fread(mp_int *a, int radix, FILE *stream)
+{
+   int err, ch, neg, y;
+   
+   /* clear a */
+   mp_zero(a);
+   
+   /* if first digit is - then set negative */
+   ch = fgetc(stream);
+   if (ch == '-') {
+      neg = MP_NEG;
+      ch = fgetc(stream);
+   } else {
+      neg = MP_ZPOS;
+   }
+   
+   for (;;) {
+      /* find y in the radix map */
+      for (y = 0; y < radix; y++) {
+          if (mp_s_rmap[y] == ch) {
+             break;
+          }
+      }
+      if (y == radix) {
+         break;
+      }
+      
+      /* shift up and add */
+      if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
+         return err;
+      }
+      if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
+         return err;
+      }
+      
+      ch = fgetc(stream);
+   }
+   if (mp_cmp_d(a, 0) != MP_EQ) {
+      a->sign = neg;
+   }
+   
+   return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_fread.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_fwrite.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_fwrite.c
new file mode 100644 (file)
index 0000000..a0b4c6b
--- /dev/null
@@ -0,0 +1,52 @@
+#include <tommath.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
+ */
+
+int mp_fwrite(mp_int *a, int radix, FILE *stream)
+{
+   char *buf;
+   int err, len, x;
+   
+   if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
+      return err;
+   }
+
+   buf = OPT_CAST(char) XMALLOC (len);
+   if (buf == NULL) {
+      return MP_MEM;
+   }
+   
+   if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
+      XFREE (buf);
+      return err;
+   }
+   
+   for (x = 0; x < len; x++) {
+       if (fputc(buf[x], stream) == EOF) {
+          XFREE (buf);
+          return MP_VAL;
+       }
+   }
+   
+   XFREE (buf);
+   return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_fwrite.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_gcd.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_gcd.c
new file mode 100644 (file)
index 0000000..b39ba90
--- /dev/null
@@ -0,0 +1,105 @@
+#include <tommath.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
+ */
+
+/* Greatest Common Divisor using the binary method */
+int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  u, v;
+  int     k, u_lsb, v_lsb, res;
+
+  /* either zero than gcd is the largest */
+  if (mp_iszero (a) == MP_YES) {
+    return mp_abs (b, c);
+  }
+  if (mp_iszero (b) == MP_YES) {
+    return mp_abs (a, c);
+  }
+
+  /* get copies of a and b we can modify */
+  if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
+    goto LBL_U;
+  }
+
+  /* must be positive for the remainder of the algorithm */
+  u.sign = v.sign = MP_ZPOS;
+
+  /* B1.  Find the common power of two for u and v */
+  u_lsb = mp_cnt_lsb(&u);
+  v_lsb = mp_cnt_lsb(&v);
+  k     = MIN(u_lsb, v_lsb);
+
+  if (k > 0) {
+     /* divide the power of two out */
+     if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+
+     if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+  }
+
+  /* divide any remaining factors of two out */
+  if (u_lsb != k) {
+     if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+  }
+
+  if (v_lsb != k) {
+     if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+  }
+
+  while (mp_iszero(&v) == 0) {
+     /* make sure v is the largest */
+     if (mp_cmp_mag(&u, &v) == MP_GT) {
+        /* swap u and v to make sure v is >= u */
+        mp_exch(&u, &v);
+     }
+     
+     /* subtract smallest from largest */
+     if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
+        goto LBL_V;
+     }
+     
+     /* Divide out all factors of two */
+     if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     } 
+  } 
+
+  /* multiply by 2**k which we divided out at the beginning */
+  if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
+     goto LBL_V;
+  }
+  c->sign = MP_ZPOS;
+  res = MP_OKAY;
+LBL_V:mp_clear (&u);
+LBL_U:mp_clear (&v);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_gcd.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_get_int.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_get_int.c
new file mode 100644 (file)
index 0000000..17162e2
--- /dev/null
@@ -0,0 +1,45 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_grow.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_grow.c
new file mode 100644 (file)
index 0000000..cf2b949
--- /dev/null
@@ -0,0 +1,57 @@
+#include <tommath.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
+ */
+
+/* grow as required */
+int mp_grow (mp_int * a, int size)
+{
+  int     i;
+  mp_digit *tmp;
+
+  /* if the alloc size is smaller alloc more ram */
+  if (a->alloc < size) {
+    /* ensure there are always at least MP_PREC digits extra on top */
+    size += (MP_PREC * 2) - (size % MP_PREC);
+
+    /* reallocate the array a->dp
+     *
+     * We store the return in a temporary variable
+     * in case the operation failed we don't want
+     * to overwrite the dp member of a.
+     */
+    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
+    if (tmp == NULL) {
+      /* reallocation failed but "a" is still valid [can be freed] */
+      return MP_MEM;
+    }
+
+    /* reallocation succeeded so set a->dp */
+    a->dp = tmp;
+
+    /* zero excess digits */
+    i        = a->alloc;
+    a->alloc = size;
+    for (; i < a->alloc; i++) {
+      a->dp[i] = 0;
+    }
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_grow.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init.c
new file mode 100644 (file)
index 0000000..8be27f5
--- /dev/null
@@ -0,0 +1,46 @@
+#include <tommath.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
+ */
+
+/* init a new mp_int */
+int mp_init (mp_int * a)
+{
+  int i;
+
+  /* allocate memory required and clear it */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the digits to zero */
+  for (i = 0; i < MP_PREC; i++) {
+      a->dp[i] = 0;
+  }
+
+  /* set the used to zero, allocated digits to the default precision
+   * and sign to positive */
+  a->used  = 0;
+  a->alloc = MP_PREC;
+  a->sign  = MP_ZPOS;
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_copy.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_copy.c
new file mode 100644 (file)
index 0000000..0160811
--- /dev/null
@@ -0,0 +1,32 @@
+#include <tommath.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
+ */
+
+/* creates "a" then copies b into it */
+int mp_init_copy (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  if ((res = mp_init (a)) != MP_OKAY) {
+    return res;
+  }
+  return mp_copy (b, a);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_copy.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_multi.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_multi.c
new file mode 100644 (file)
index 0000000..59dc3a9
--- /dev/null
@@ -0,0 +1,59 @@
+#include <tommath.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
+ */
+#include <stdarg.h>
+
+int mp_init_multi(mp_int *mp, ...) 
+{
+    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
+    int n = 0;                 /* Number of ok inits */
+    mp_int* cur_arg = mp;
+    va_list args;
+
+    va_start(args, mp);        /* init args to next argument from caller */
+    while (cur_arg != NULL) {
+        if (mp_init(cur_arg) != MP_OKAY) {
+            /* Oops - error! Back-track and mp_clear what we already
+               succeeded in init-ing, then return error.
+            */
+            va_list clean_args;
+            
+            /* end the current list */
+            va_end(args);
+            
+            /* now start cleaning up */            
+            cur_arg = mp;
+            va_start(clean_args, mp);
+            while (n--) {
+                mp_clear(cur_arg);
+                cur_arg = va_arg(clean_args, mp_int*);
+            }
+            va_end(clean_args);
+            res = MP_MEM;
+            break;
+        }
+        n++;
+        cur_arg = va_arg(args, mp_int*);
+    }
+    va_end(args);
+    return res;                /* Assumed ok, if error flagged above. */
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_multi.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_set.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_set.c
new file mode 100644 (file)
index 0000000..34edad9
--- /dev/null
@@ -0,0 +1,32 @@
+#include <tommath.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
+ */
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b)
+{
+  int err;
+  if ((err = mp_init(a)) != MP_OKAY) {
+     return err;
+  }
+  mp_set(a, b);
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_set.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_set_int.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_set_int.c
new file mode 100644 (file)
index 0000000..5c55993
--- /dev/null
@@ -0,0 +1,31 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_size.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_size.c
new file mode 100644 (file)
index 0000000..8e01418
--- /dev/null
@@ -0,0 +1,48 @@
+#include <tommath.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
+ */
+
+/* init an mp_init for a given size */
+int mp_init_size (mp_int * a, int size)
+{
+  int x;
+
+  /* pad size so there are always extra digits */
+  size += (MP_PREC * 2) - (size % MP_PREC);    
+  
+  /* alloc mem */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the members */
+  a->used  = 0;
+  a->alloc = size;
+  a->sign  = MP_ZPOS;
+
+  /* zero the digits */
+  for (x = 0; x < size; x++) {
+      a->dp[x] = 0;
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_init_size.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_invmod.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_invmod.c
new file mode 100644 (file)
index 0000000..1546514
--- /dev/null
@@ -0,0 +1,43 @@
+#include <tommath.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
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+#ifdef BN_FAST_MP_INVMOD_C
+  /* if the modulus is odd we can use a faster routine instead */
+  if (mp_isodd (b) == 1) {
+    return fast_mp_invmod (a, b, c);
+  }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+  return mp_invmod_slow(a, b, c);
+#endif
+
+  return MP_VAL;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_invmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_invmod_slow.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_invmod_slow.c
new file mode 100644 (file)
index 0000000..eedd47d
--- /dev/null
@@ -0,0 +1,175 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_is_square.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_is_square.c
new file mode 100644 (file)
index 0000000..50c5244
--- /dev/null
@@ -0,0 +1,109 @@
+#include <tommath.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
+ */
+
+/* Check if remainders are possible squares - fast exclude non-squares */
+static const char rem_128[128] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
+};
+
+static const char rem_105[105] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
+};
+
+/* Store non-zero to ret if arg is square, and zero if not */
+int mp_is_square(mp_int *arg,int *ret) 
+{
+  int           res;
+  mp_digit      c;
+  mp_int        t;
+  unsigned long r;
+
+  /* Default to Non-square :) */
+  *ret = MP_NO; 
+
+  if (arg->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  /* digits used?  (TSD) */
+  if (arg->used == 0) {
+     return MP_OKAY;
+  }
+
+  /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
+  if (rem_128[127 & DIGIT(arg,0)] == 1) {
+     return MP_OKAY;
+  }
+
+  /* Next check mod 105 (3*5*7) */
+  if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
+     return res;
+  }
+  if (rem_105[c] == 1) {
+     return MP_OKAY;
+  }
+
+
+  if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
+     return res;
+  }
+  if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+  r = mp_get_int(&t);
+  /* Check for other prime modules, note it's not an ERROR but we must
+   * free "t" so the easiest way is to goto ERR.  We know that res
+   * is already equal to MP_OKAY from the mp_mod call 
+   */ 
+  if ( (1L<<(r%11)) & 0x5C4L )             goto ERR;
+  if ( (1L<<(r%13)) & 0x9E4L )             goto ERR;
+  if ( (1L<<(r%17)) & 0x5CE8L )            goto ERR;
+  if ( (1L<<(r%19)) & 0x4F50CL )           goto ERR;
+  if ( (1L<<(r%23)) & 0x7ACCA0L )          goto ERR;
+  if ( (1L<<(r%29)) & 0xC2EDD0CL )         goto ERR;
+  if ( (1L<<(r%31)) & 0x6DE2B848L )        goto ERR;
+
+  /* Final check - is sqr(sqrt(arg)) == arg ? */
+  if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+  if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+
+  *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
+ERR:mp_clear(&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_is_square.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_isprime.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_isprime.c
new file mode 100644 (file)
index 0000000..07ce86f
--- /dev/null
@@ -0,0 +1,75 @@
+/* TomsFastMath, a fast ISO C bignum library.
+ * 
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ * 
+ * Tom St Denis, tomstdenis@gmail.com
+ */
+#include <tommath.h>
+
+/* a few primes */
+static const mp_digit primes[256] = {
+  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, 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
+};
+
+int mp_isprime(mp_int *a)
+{
+   mp_int   b;
+   mp_digit d;
+   int      r, res;
+
+   /* do trial division */
+   for (r = 0; r < 256; r++) {
+       mp_mod_d(a, primes[r], &d);
+       if (d == 0) {
+          return MP_NO;
+       }
+   }
+
+   /* now do 8 miller rabins */
+   mp_init(&b);
+   for (r = 0; r < 128; r++) {
+       mp_set(&b, primes[r]);
+       mp_prime_miller_rabin(a, &b, &res);
+       if (res == MP_NO) {
+          return MP_NO;
+       }
+   }
+   return MP_YES;
+}
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_jacobi.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_jacobi.c
new file mode 100644 (file)
index 0000000..91cfeea
--- /dev/null
@@ -0,0 +1,105 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c
new file mode 100644 (file)
index 0000000..8ea2c27
--- /dev/null
@@ -0,0 +1,167 @@
+#include <tommath.h>
+#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))<<B */
+  if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
+    goto X1Y1;          /* x1y1 = x1y1 << 2*B */
+
+  if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = x0y0 + t1 */
+  if (mp_add (&t1, &x1y1, c) != MP_OKAY)
+    goto X1Y1;          /* t1 = x0y0 + t1 + x1y1 */
+
+  /* Algorithm succeeded set the return code to MP_OKAY */
+  err = MP_OKAY;
+
+X1Y1:mp_clear (&x1y1);
+X0Y0:mp_clear (&x0y0);
+T1:mp_clear (&t1);
+Y1:mp_clear (&y1);
+Y0:mp_clear (&y0);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_karatsuba_mul.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_karatsuba_sqr.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_karatsuba_sqr.c
new file mode 100644 (file)
index 0000000..a5e198b
--- /dev/null
@@ -0,0 +1,121 @@
+#include <tommath.h>
+#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))<<B */
+  if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
+    goto X1X1;           /* x1x1 = x1x1 << 2*B */
+
+  if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = x0x0 + t1 */
+  if (mp_add (&t1, &x1x1, b) != MP_OKAY)
+    goto X1X1;           /* t1 = x0x0 + t1 + x1x1 */
+
+  err = MP_OKAY;
+
+X1X1:mp_clear (&x1x1);
+X0X0:mp_clear (&x0x0);
+T2:mp_clear (&t2);
+T1:mp_clear (&t1);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_karatsuba_sqr.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_lcm.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_lcm.c
new file mode 100644 (file)
index 0000000..781eef5
--- /dev/null
@@ -0,0 +1,60 @@
+#include <tommath.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
+ */
+
+/* computes least common multiple as |a*b|/(a, b) */
+int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res;
+  mp_int  t1, t2;
+
+
+  if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
+    return res;
+  }
+
+  /* t1 = get the GCD of the two inputs */
+  if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
+    goto LBL_T;
+  }
+
+  /* divide the smallest by the GCD */
+  if (mp_cmp_mag(a, b) == MP_LT) {
+     /* store quotient in t2 such that t2 * b is the LCM */
+     if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
+        goto LBL_T;
+     }
+     res = mp_mul(b, &t2, c);
+  } else {
+     /* store quotient in t2 such that t2 * a is the LCM */
+     if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
+        goto LBL_T;
+     }
+     res = mp_mul(a, &t2, c);
+  }
+
+  /* fix the sign to positive */
+  c->sign = MP_ZPOS;
+
+LBL_T:
+  mp_clear_multi (&t1, &t2, NULL);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_lcm.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_lshd.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_lshd.c
new file mode 100644 (file)
index 0000000..f118cf1
--- /dev/null
@@ -0,0 +1,67 @@
+#include <tommath.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
+ */
+
+/* shift left a certain amount of digits */
+int mp_lshd (mp_int * a, int b)
+{
+  int     x, res;
+
+  /* if its less than zero return */
+  if (b <= 0) {
+    return MP_OKAY;
+  }
+
+  /* grow to fit the new digits */
+  if (a->alloc < a->used + b) {
+     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  {
+    register mp_digit *top, *bottom;
+
+    /* increment the used by the shift amount then copy upwards */
+    a->used += b;
+
+    /* top */
+    top = a->dp + a->used - 1;
+
+    /* base */
+    bottom = a->dp + a->used - 1 - b;
+
+    /* much like mp_rshd this is implemented using a sliding window
+     * except the window goes the otherway around.  Copying from
+     * the bottom to the top.  see bn_mp_rshd.c for more info.
+     */
+    for (x = a->used - 1; x >= b; x--) {
+      *top-- = *bottom--;
+    }
+
+    /* zero the lower digits */
+    top = a->dp;
+    for (x = 0; x < b; x++) {
+      *top++ = 0;
+    }
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_lshd.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod.c
new file mode 100644 (file)
index 0000000..f5cf8d0
--- /dev/null
@@ -0,0 +1,48 @@
+#include <tommath.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
+ */
+
+/* c = a mod b, 0 <= c < b */
+int
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  t;
+  int     res;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  if (t.sign != b->sign) {
+    res = mp_add (b, &t, c);
+  } else {
+    res = MP_OKAY;
+    mp_exch (&t, c);
+  }
+
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod_2d.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod_2d.c
new file mode 100644 (file)
index 0000000..e194a06
--- /dev/null
@@ -0,0 +1,55 @@
+#include <tommath.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
+ */
+
+/* calc a value mod 2**b */
+int
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+  int     x, res;
+
+  /* if b is <= 0 then zero the int */
+  if (b <= 0) {
+    mp_zero (c);
+    return MP_OKAY;
+  }
+
+  /* if the modulus is larger than the value than return */
+  if (b >= (int) (a->used * DIGIT_BIT)) {
+    res = mp_copy (a, c);
+    return res;
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    return res;
+  }
+
+  /* zero digits above the last digit of the modulus */
+  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+    c->dp[x] = 0;
+  }
+  /* clear the digit that is not completely outside/inside the modulus */
+  c->dp[b / DIGIT_BIT] &=
+    (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mod_2d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod_d.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod_d.c
new file mode 100644 (file)
index 0000000..9ca37e6
--- /dev/null
@@ -0,0 +1,27 @@
+#include <tommath.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
+ */
+
+int
+mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
+{
+  return mp_div_d(a, b, NULL, c);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mod_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c
new file mode 100644 (file)
index 0000000..c669fe0
--- /dev/null
@@ -0,0 +1,59 @@
+#include <tommath.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
+ */
+
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b.  This saves alot of multiple precision shifting.
+ */
+int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+  int     x, bits, res;
+
+  /* how many bits of last digit does b use */
+  bits = mp_count_bits (b) % DIGIT_BIT;
+
+  if (b->used > 1) {
+     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+        return res;
+     }
+  } else {
+     mp_set(a, 1);
+     bits = 1;
+  }
+
+
+  /* now compute C = A * B mod b */
+  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+      return res;
+    }
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+        return res;
+      }
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_calc_normalization.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c
new file mode 100644 (file)
index 0000000..b765090
--- /dev/null
@@ -0,0 +1,118 @@
+#include <tommath.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
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+int
+mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, digs;
+  mp_digit mu;
+
+  /* can the fast reduction [comba] method be used?
+   *
+   * Note that unlike in mul you're safely allowed *less*
+   * than the available columns [255 per default] since carries
+   * are fixed up in the inner loop.
+   */
+  digs = n->used * 2 + 1;
+  if ((digs < MP_WARRAY) &&
+      n->used <
+      (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_mp_montgomery_reduce (x, n, rho);
+  }
+
+  /* grow the input as required */
+  if (x->alloc < digs) {
+    if ((res = mp_grow (x, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+  x->used = digs;
+
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * rho mod b
+     *
+     * The value of rho must be precalculated via
+     * montgomery_setup() such that
+     * it equals -1/n0 mod b this allows the
+     * following inner loop to reduce the
+     * input one digit at a time
+     */
+    mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i */
+    {
+      register int iy;
+      register mp_digit *tmpn, *tmpx, u;
+      register mp_word r;
+
+      /* alias for digits of the modulus */
+      tmpn = n->dp;
+
+      /* alias for the digits of x [the input] */
+      tmpx = x->dp + ix;
+
+      /* set the carry to zero */
+      u = 0;
+
+      /* Multiply and add in place */
+      for (iy = 0; iy < n->used; iy++) {
+        /* compute product and sum */
+        r       = ((mp_word)mu) * ((mp_word)*tmpn++) +
+                  ((mp_word) u) + ((mp_word) * tmpx);
+
+        /* get carry */
+        u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+        /* fix digit */
+        *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
+      }
+      /* At this point the ix'th digit of x should be zero */
+
+
+      /* propagate carries upwards as required*/
+      while (u) {
+        *tmpx   += u;
+        u        = *tmpx >> DIGIT_BIT;
+        *tmpx++ &= MP_MASK;
+      }
+    }
+  }
+
+  /* at this point the n.used'th least
+   * significant digits of x are all zero
+   * which means we can shift x to the
+   * right by n.used digits and the
+   * residue is unchanged.
+   */
+
+  /* x = x/b**n.used */
+  mp_clamp(x);
+  mp_rshd (x, n->used);
+
+  /* if x >= n then x = x - n */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c
new file mode 100644 (file)
index 0000000..f082749
--- /dev/null
@@ -0,0 +1,59 @@
+#include <tommath.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
+ */
+
+/* setups the montgomery reduction stuff */
+int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+  mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+ *                    =>  2*X*A - X*X*A*A = 1
+ *                    =>  2*(1) - (1)     = 1
+ */
+  b = n->dp[0];
+
+  if ((b & 1) == 0) {
+    return MP_VAL;
+  }
+
+  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+#endif
+
+  /* rho = -1/m mod b */
+  *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_montgomery_setup.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul.c
new file mode 100644 (file)
index 0000000..8b1117a
--- /dev/null
@@ -0,0 +1,66 @@
+#include <tommath.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
+ */
+
+/* high level multiplication (handles sign) */
+int mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, neg;
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+  /* use Toom-Cook? */
+#ifdef BN_MP_TOOM_MUL_C
+  if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+    res = mp_toom_mul(a, b, c);
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_MUL_C
+  /* use Karatsuba? */
+  if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+    res = mp_karatsuba_mul (a, b, c);
+  } else 
+#endif
+  {
+    /* can we use the fast multiplier?
+     *
+     * The fast multiplier can be used if the output will 
+     * have less than MP_WARRAY digits and the number of 
+     * digits won't affect carry propagation
+     */
+    int     digs = a->used + b->used + 1;
+
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+    if ((digs < MP_WARRAY) &&
+        MIN(a->used, b->used) <= 
+        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+      res = fast_s_mp_mul_digs (a, b, c, digs);
+    } else 
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+      res = MP_VAL;
+#endif
+
+  }
+  c->sign = (c->used > 0) ? neg : MP_ZPOS;
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2.c
new file mode 100644 (file)
index 0000000..02455fc
--- /dev/null
@@ -0,0 +1,82 @@
+#include <tommath.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
+ */
+
+/* b = a*2 */
+int mp_mul_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* grow to accomodate result */
+  if (b->alloc < a->used + 1) {
+    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+    
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+    
+      /* get what will be the *next* carry bit from the 
+       * MSB of the current digit 
+       */
+      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+      
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+      
+      /* copy the carry that would be from the source 
+       * digit into the next iteration 
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination 
+     * that we didn't write to 
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2d.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2d.c
new file mode 100644 (file)
index 0000000..efeff2e
--- /dev/null
@@ -0,0 +1,85 @@
+#include <tommath.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
+ */
+
+/* shift left by a certain bit count */
+int mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+  mp_digit d;
+  int      res;
+
+  /* copy */
+  if (a != c) {
+     if ((res = mp_copy (a, c)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  d = (mp_digit) (b % DIGIT_BIT);
+  if (d != 0) {
+    register mp_digit *tmpc, shift, mask, r, rr;
+    register int x;
+
+    /* bitmask for carries */
+    mask = (((mp_digit)1) << d) - 1;
+
+    /* shift for msbs */
+    shift = DIGIT_BIT - d;
+
+    /* alias */
+    tmpc = c->dp;
+
+    /* carry */
+    r    = 0;
+    for (x = 0; x < c->used; x++) {
+      /* get the higher bits of the current word */
+      rr = (*tmpc >> shift) & mask;
+
+      /* shift the current word and OR in the carry */
+      *tmpc = ((*tmpc << d) | r) & MP_MASK;
+      ++tmpc;
+
+      /* set the carry to the carry bits of the current word */
+      r = rr;
+    }
+    
+    /* set final carry */
+    if (r != 0) {
+       c->dp[(c->used)++] = r;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul_2d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_d.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_d.c
new file mode 100644 (file)
index 0000000..00f9a89
--- /dev/null
@@ -0,0 +1,79 @@
+#include <tommath.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
+ */
+
+/* multiply by a digit */
+int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit u, *tmpa, *tmpc;
+  mp_word  r;
+  int      ix, res, olduse;
+
+  /* make sure c is big enough to hold a*b */
+  if (c->alloc < a->used + 1) {
+    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get the original destinations used count */
+  olduse = c->used;
+
+  /* set the sign */
+  c->sign = a->sign;
+
+  /* alias for a->dp [source] */
+  tmpa = a->dp;
+
+  /* alias for c->dp [dest] */
+  tmpc = c->dp;
+
+  /* zero carry */
+  u = 0;
+
+  /* compute columns */
+  for (ix = 0; ix < a->used; ix++) {
+    /* compute product and carry sum for this term */
+    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+    /* mask off higher bits to get a single digit */
+    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* send carry into next iteration */
+    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+  }
+
+  /* store final carry [if any] and increment ix offset  */
+  *tmpc++ = u;
+  ++ix;
+
+  /* now zero digits above the top */
+  while (ix++ < olduse) {
+     *tmpc++ = 0;
+  }
+
+  /* set used count */
+  c->used = a->used + 1;
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mul_d.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mulmod.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mulmod.c
new file mode 100644 (file)
index 0000000..003ceb9
--- /dev/null
@@ -0,0 +1,40 @@
+#include <tommath.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
+ */
+
+/* d = a * b (mod c) */
+int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_mulmod.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_n_root.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_n_root.c
new file mode 100644 (file)
index 0000000..0e7bedc
--- /dev/null
@@ -0,0 +1,132 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_neg.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_neg.c
new file mode 100644 (file)
index 0000000..a7d035a
--- /dev/null
@@ -0,0 +1,40 @@
+#include <tommath.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
+ */
+
+/* b = -a */
+int mp_neg (mp_int * a, mp_int * b)
+{
+  int     res;
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  if (mp_iszero(b) != MP_YES) {
+     b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+  } else {
+     b->sign = MP_ZPOS;
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_neg.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_or.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_or.c
new file mode 100644 (file)
index 0000000..bff4995
--- /dev/null
@@ -0,0 +1,50 @@
+#include <tommath.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
+ */
+
+/* OR two ints together */
+int mp_or (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+    t.dp[ix] |= x->dp[ix];
+  }
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_or.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_fermat.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_fermat.c
new file mode 100644 (file)
index 0000000..c23d77f
--- /dev/null
@@ -0,0 +1,62 @@
+#include <tommath.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
+ */
+
+/* performs one Fermat test.
+ * 
+ * If "a" were prime then b**a == b (mod a) since the order of
+ * the multiplicative sub-group would be phi(a) = a-1.  That means
+ * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
+ *
+ * Sets result to 1 if the congruence holds, or zero otherwise.
+ */
+int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
+{
+  mp_int  t;
+  int     err;
+
+  /* default to composite  */
+  *result = MP_NO;
+
+  /* ensure b > 1 */
+  if (mp_cmp_d(b, 1) != MP_GT) {
+     return MP_VAL;
+  }
+
+  /* init t */
+  if ((err = mp_init (&t)) != MP_OKAY) {
+    return err;
+  }
+
+  /* compute t = b**a mod a */
+  if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
+    goto LBL_T;
+  }
+
+  /* is it equal to b? */
+  if (mp_cmp (&t, b) == MP_EQ) {
+    *result = MP_YES;
+  }
+
+  err = MP_OKAY;
+LBL_T:mp_clear (&t);
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_fermat.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c
new file mode 100644 (file)
index 0000000..8e7871c
--- /dev/null
@@ -0,0 +1,50 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c
new file mode 100644 (file)
index 0000000..c316d62
--- /dev/null
@@ -0,0 +1,83 @@
+#include <tommath.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
+ */
+
+/* performs a variable number of rounds of Miller-Rabin
+ *
+ * Probability of error after t rounds is no more than
+
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime (mp_int * a, int t, int *result)
+{
+  mp_int  b;
+  int     ix, err, res;
+
+  /* default to no */
+  *result = MP_NO;
+
+  /* valid value of t? */
+  if (t <= 0 || t > PRIME_SIZE) {
+    return MP_VAL;
+  }
+
+  /* is the input equal to one of the primes in the table? */
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+      if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
+         *result = 1;
+         return MP_OKAY;
+      }
+  }
+
+  /* first perform trial division */
+  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+    return err;
+  }
+
+  /* return if it was trivially divisible */
+  if (res == MP_YES) {
+    return MP_OKAY;
+  }
+
+  /* now perform the miller-rabin rounds */
+  if ((err = mp_init (&b)) != MP_OKAY) {
+    return err;
+  }
+
+  for (ix = 0; ix < t; ix++) {
+    /* set the prime */
+    mp_set (&b, ltm_prime_tab[ix]);
+
+    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+      goto LBL_B;
+    }
+
+    if (res == MP_NO) {
+      goto LBL_B;
+    }
+  }
+
+  /* passed the test */
+  *result = MP_YES;
+LBL_B:mp_clear (&b);
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_is_prime.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c
new file mode 100644 (file)
index 0000000..ddf0358
--- /dev/null
@@ -0,0 +1,103 @@
+#include <tommath.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
+ */
+
+/* Miller-Rabin test of "a" to the base of "b" as described in 
+ * HAC pp. 139 Algorithm 4.24
+ *
+ * Sets result to 0 if definitely composite or 1 if probably prime.
+ * Randomly the chance of error is no more than 1/4 and often 
+ * very much lower.
+ */
+int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
+{
+  mp_int  n1, y, r;
+  int     s, j, err;
+
+  /* default */
+  *result = MP_NO;
+
+  /* ensure b > 1 */
+  if (mp_cmp_d(b, 1) != MP_GT) {
+     return MP_VAL;
+  }     
+
+  /* get n1 = a - 1 */
+  if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
+    return err;
+  }
+  if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
+    goto LBL_N1;
+  }
+
+  /* set 2**s * r = n1 */
+  if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
+    goto LBL_N1;
+  }
+
+  /* count the number of least significant bits
+   * which are zero
+   */
+  s = mp_cnt_lsb(&r);
+
+  /* now divide n - 1 by 2**s */
+  if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
+    goto LBL_R;
+  }
+
+  /* compute y = b**r mod a */
+  if ((err = mp_init (&y)) != MP_OKAY) {
+    goto LBL_R;
+  }
+  if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
+    goto LBL_Y;
+  }
+
+  /* if y != 1 and y != n1 do */
+  if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
+    j = 1;
+    /* while j <= s-1 and y != n1 */
+    while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
+      if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
+         goto LBL_Y;
+      }
+
+      /* if y == 1 then composite */
+      if (mp_cmp_d (&y, 1) == MP_EQ) {
+         goto LBL_Y;
+      }
+
+      ++j;
+    }
+
+    /* if y != n1 then composite */
+    if (mp_cmp (&y, &n1) != MP_EQ) {
+      goto LBL_Y;
+    }
+  }
+
+  /* probably prime now */
+  *result = MP_YES;
+LBL_Y:mp_clear (&y);
+LBL_R:mp_clear (&r);
+LBL_N1:mp_clear (&n1);
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_miller_rabin.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c
new file mode 100644 (file)
index 0000000..daf2ec7
--- /dev/null
@@ -0,0 +1,170 @@
+#include <tommath.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
+ */
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
+{
+   int      err, res, x, y;
+   mp_digit res_tab[PRIME_SIZE], step, kstep;
+   mp_int   b;
+
+   /* ensure t is valid */
+   if (t <= 0 || t > PRIME_SIZE) {
+      return MP_VAL;
+   }
+
+   /* force positive */
+   a->sign = MP_ZPOS;
+
+   /* simple algo if a is less than the largest prime in the table */
+   if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) {
+      /* find which prime it is bigger than */
+      for (x = PRIME_SIZE - 2; x >= 0; x--) {
+          if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) {
+             if (bbs_style == 1) {
+                /* ok we found a prime smaller or
+                 * equal [so the next is larger]
+                 *
+                 * however, the prime must be
+                 * congruent to 3 mod 4
+                 */
+                if ((ltm_prime_tab[x + 1] & 3) != 3) {
+                   /* scan upwards for a prime congruent to 3 mod 4 */
+                   for (y = x + 1; y < PRIME_SIZE; y++) {
+                       if ((ltm_prime_tab[y] & 3) == 3) {
+                          mp_set(a, ltm_prime_tab[y]);
+                          return MP_OKAY;
+                       }
+                   }
+                }
+             } else {
+                mp_set(a, ltm_prime_tab[x + 1]);
+                return MP_OKAY;
+             }
+          }
+      }
+      /* at this point a maybe 1 */
+      if (mp_cmp_d(a, 1) == MP_EQ) {
+         mp_set(a, 2);
+         return MP_OKAY;
+      }
+      /* fall through to the sieve */
+   }
+
+   /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
+   if (bbs_style == 1) {
+      kstep   = 4;
+   } else {
+      kstep   = 2;
+   }
+
+   /* at this point we will use a combination of a sieve and Miller-Rabin */
+
+   if (bbs_style == 1) {
+      /* if a mod 4 != 3 subtract the correct value to make it so */
+      if ((a->dp[0] & 3) != 3) {
+         if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
+      }
+   } else {
+      if (mp_iseven(a) == 1) {
+         /* force odd */
+         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
+            return err;
+         }
+      }
+   }
+
+   /* generate the restable */
+   for (x = 1; x < PRIME_SIZE; x++) {
+      if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) {
+         return err;
+      }
+   }
+
+   /* init temp used for Miller-Rabin Testing */
+   if ((err = mp_init(&b)) != MP_OKAY) {
+      return err;
+   }
+
+   for (;;) {
+      /* skip to the next non-trivially divisible candidate */
+      step = 0;
+      do {
+         /* y == 1 if any residue was zero [e.g. cannot be prime] */
+         y     =  0;
+
+         /* increase step to next candidate */
+         step += kstep;
+
+         /* compute the new residue without using division */
+         for (x = 1; x < PRIME_SIZE; x++) {
+             /* add the step to each residue */
+             res_tab[x] += kstep;
+
+             /* subtract the modulus [instead of using division] */
+             if (res_tab[x] >= ltm_prime_tab[x]) {
+                res_tab[x]  -= ltm_prime_tab[x];
+             }
+
+             /* set flag if zero */
+             if (res_tab[x] == 0) {
+                y = 1;
+             }
+         }
+      } while (y == 1 && step < ((((mp_digit)1)<<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 == MAX then skip test */
+      if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
+         continue;
+      }
+
+      /* is this prime? */
+      for (x = 0; x < t; x++) {
+          mp_set(&b, ltm_prime_tab[t]);
+          if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
+             goto LBL_ERR;
+          }
+          if (res == MP_NO) {
+             break;
+          }
+      }
+
+      if (res == MP_YES) {
+         break;
+      }
+   }
+
+   err = MP_OKAY;
+LBL_ERR:
+   mp_clear(&b);
+   return 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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c
new file mode 100644 (file)
index 0000000..248c2fd
--- /dev/null
@@ -0,0 +1,52 @@
+#include <tommath.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
+ */
+
+
+static const struct {
+   int k, t;
+} sizes[] = {
+{   128,    28 },
+{   256,    16 },
+{   384,    10 },
+{   512,     7 },
+{   640,     6 },
+{   768,     5 },
+{   896,     4 },
+{  1024,     4 }
+};
+
+/* returns # of RM trials required for a given bit size */
+int mp_prime_rabin_miller_trials(int size)
+{
+   int x;
+
+   for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
+       if (sizes[x].k == size) {
+          return sizes[x].t;
+       } else if (sizes[x].k > size) {
+          return (x == 0) ? sizes[0].t : sizes[x - 1].t;
+       }
+   }
+   return sizes[x-1].t + 1;
+}
+
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_prime_rabin_miller_trials.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_random_ex.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_random_ex.c
new file mode 100644 (file)
index 0000000..07aae4b
--- /dev/null
@@ -0,0 +1,125 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_radix_size.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_radix_size.c
new file mode 100644 (file)
index 0000000..1b61e3a
--- /dev/null
@@ -0,0 +1,78 @@
+#include <tommath.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
+ */
+
+/* returns size of ASCII reprensentation */
+int mp_radix_size (mp_int * a, int radix, int *size)
+{
+  int     res, digs;
+  mp_int  t;
+  mp_digit d;
+
+  *size = 0;
+
+  /* special case for binary */
+  if (radix == 2) {
+    *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
+    return MP_OKAY;
+  }
+
+  /* make sure the radix is in range */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  if (mp_iszero(a) == MP_YES) {
+    *size = 2;
+    return MP_OKAY;
+  }
+
+  /* digs is the digit count */
+  digs = 0;
+
+  /* if it's negative add one for the sign */
+  if (a->sign == MP_NEG) {
+    ++digs;
+  }
+
+  /* init a copy of the input */
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* force temp to positive */
+  t.sign = MP_ZPOS; 
+
+  /* fetch out all of the digits */
+  while (mp_iszero (&t) == MP_NO) {
+    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+    ++digs;
+  }
+  mp_clear (&t);
+
+  /* return digs + 1, the 1 is for the NULL byte that would be required. */
+  *size = digs + 1;
+  return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_radix_size.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_radix_smap.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_radix_smap.c
new file mode 100644 (file)
index 0000000..7d72feb
--- /dev/null
@@ -0,0 +1,24 @@
+#include <tommath.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
+ */
+
+/* chars used in radix conversions */
+const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_radix_smap.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_rand.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_rand.c
new file mode 100644 (file)
index 0000000..af66a67
--- /dev/null
@@ -0,0 +1,55 @@
+#include <tommath.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
+ */
+
+/* makes a pseudo-random int of a given size */
+int
+mp_rand (mp_int * a, int digits)
+{
+  int     res;
+  mp_digit d;
+
+  mp_zero (a);
+  if (digits <= 0) {
+    return MP_OKAY;
+  }
+
+  /* first place a random non-zero digit */
+  do {
+    d = ((mp_digit) abs (rand ())) & MP_MASK;
+  } while (d == 0);
+
+  if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
+    return res;
+  }
+
+  while (--digits > 0) {
+    if ((res = mp_lshd (a, 1)) != MP_OKAY) {
+      return res;
+    }
+
+    if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_rand.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_radix.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_radix.c
new file mode 100644 (file)
index 0000000..91c46c2
--- /dev/null
@@ -0,0 +1,85 @@
+#include <tommath.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
+ */
+
+/* read a string [ASCII] in a given radix */
+int mp_read_radix (mp_int * a, const char *str, int radix)
+{
+  int     y, res, neg;
+  char    ch;
+
+  /* zero the digit bignum */
+  mp_zero(a);
+
+  /* make sure the radix is ok */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* if the leading digit is a 
+   * minus set the sign to negative. 
+   */
+  if (*str == '-') {
+    ++str;
+    neg = MP_NEG;
+  } else {
+    neg = MP_ZPOS;
+  }
+
+  /* set the integer to the default of zero */
+  mp_zero (a);
+  
+  /* process each digit of the string */
+  while (*str) {
+    /* if the radix < 36 the conversion is case insensitive
+     * this allows numbers like 1AB and 1ab to represent the same  value
+     * [e.g. in hex]
+     */
+    ch = (char) ((radix < 36) ? toupper (*str) : *str);
+    for (y = 0; y < 64; y++) {
+      if (ch == mp_s_rmap[y]) {
+         break;
+      }
+    }
+
+    /* if the char was found in the map 
+     * and is less than the given radix add it
+     * to the number, otherwise exit the loop. 
+     */
+    if (y < radix) {
+      if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
+         return res;
+      }
+      if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
+         return res;
+      }
+    } else {
+      break;
+    }
+    ++str;
+  }
+  
+  /* set the sign only if a != 0 */
+  if (mp_iszero(a) != 1) {
+     a->sign = neg;
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_read_radix.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_signed_bin.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_signed_bin.c
new file mode 100644 (file)
index 0000000..8da651c
--- /dev/null
@@ -0,0 +1,41 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c
new file mode 100644 (file)
index 0000000..1ebba13
--- /dev/null
@@ -0,0 +1,55 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce.c
new file mode 100644 (file)
index 0000000..21d0730
--- /dev/null
@@ -0,0 +1,100 @@
+#include <tommath.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
+ */
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is 
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+  mp_int  q;
+  int     res, um = m->used;
+
+  /* q = x */
+  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+    return res;
+  }
+
+  /* q1 = x / b**(k-1)  */
+  mp_rshd (&q, um - 1);         
+
+  /* according to HAC this optimization is ok */
+  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+    if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#else 
+    { 
+      res = MP_VAL;
+      goto CLEANUP;
+    }
+#endif
+  }
+
+  /* q3 = q2 / b**(k+1) */
+  mp_rshd (&q, um + 1);         
+
+  /* x = x mod b**(k+1), quick (no division) */
+  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* q = q * m mod b**(k+1), quick (no division) */
+  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* x = x - q */
+  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* If x < 0, add b**(k+1) to it */
+  if (mp_cmp_d (x, 0) == MP_LT) {
+    mp_set (&q, 1);
+    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
+      goto CLEANUP;
+    if ((res = mp_add (x, &q, x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  /* Back off if it's too big */
+  while (mp_cmp (x, m) != MP_LT) {
+    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+  
+CLEANUP:
+  mp_clear (&q);
+
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k.c
new file mode 100644 (file)
index 0000000..d9620c2
--- /dev/null
@@ -0,0 +1,61 @@
+#include <tommath.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
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
+{
+   mp_int q;
+   int    p, res;
+   
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(n);    
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (d != 1) {
+      /* q = q * d */
+      if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { 
+         goto ERR;
+      }
+   }
+   
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      s_mp_sub(a, n, a);
+      goto top;
+   }
+   
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c
new file mode 100644 (file)
index 0000000..f06103d
--- /dev/null
@@ -0,0 +1,62 @@
+#include <tommath.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
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d 
+   This differs from reduce_2k since "d" can be larger
+   than a single digit.
+*/
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+   mp_int q;
+   int    p, res;
+   
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(n);    
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   /* q = q * d */
+   if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { 
+      goto ERR;
+   }
+   
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      s_mp_sub(a, n, a);
+      goto top;
+   }
+   
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_l.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c
new file mode 100644 (file)
index 0000000..a80e7a2
--- /dev/null
@@ -0,0 +1,47 @@
+#include <tommath.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
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
+{
+   int res, p;
+   mp_int tmp;
+   
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(a);
+   if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return res;
+   }
+   
+   if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return res;
+   }
+   
+   *d = tmp.dp[0];
+   mp_clear(&tmp);
+   return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c
new file mode 100644 (file)
index 0000000..7cf002e
--- /dev/null
@@ -0,0 +1,44 @@
+#include <tommath.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
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+   int    res;
+   mp_int tmp;
+   
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+   
+   if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+ERR:
+   mp_clear(&tmp);
+   return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_2k_setup_l.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c
new file mode 100644 (file)
index 0000000..7308be7
--- /dev/null
@@ -0,0 +1,52 @@
+#include <tommath.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
+ */
+
+/* determines if mp_reduce_2k can be used */
+int mp_reduce_is_2k(mp_int *a)
+{
+   int ix, iy, iw;
+   mp_digit iz;
+   
+   if (a->used == 0) {
+      return MP_NO;
+   } else if (a->used == 1) {
+      return MP_YES;
+   } else if (a->used > 1) {
+      iy = mp_count_bits(a);
+      iz = 1;
+      iw = 1;
+    
+      /* Test every bit from the second digit up, must be 1 */
+      for (ix = DIGIT_BIT; ix < iy; ix++) {
+          if ((a->dp[iw] & iz) == 0) {
+             return MP_NO;
+          }
+          iz <<= 1;
+          if (iz > (mp_digit)MP_MASK) {
+             ++iw;
+             iz = 1;
+          }
+      }
+   }
+   return MP_YES;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c
new file mode 100644 (file)
index 0000000..14a4d21
--- /dev/null
@@ -0,0 +1,44 @@
+#include <tommath.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
+ */
+
+/* determines if reduce_2k_l can be used */
+int mp_reduce_is_2k_l(mp_int *a)
+{
+   int ix, iy;
+   
+   if (a->used == 0) {
+      return MP_NO;
+   } else if (a->used == 1) {
+      return MP_YES;
+   } else if (a->used > 1) {
+      /* if more than half of the digits are -1 we're sold */
+      for (iy = ix = 0; ix < a->used; ix++) {
+          if (a->dp[ix] == MP_MASK) {
+              ++iy;
+          }
+      }
+      return (iy >= (a->used/2)) ? MP_YES : MP_NO;
+      
+   }
+   return MP_NO;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_is_2k_l.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_setup.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_setup.c
new file mode 100644 (file)
index 0000000..370f20b
--- /dev/null
@@ -0,0 +1,34 @@
+#include <tommath.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
+ */
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+int mp_reduce_setup (mp_int * a, mp_int * b)
+{
+  int     res;
+  
+  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+    return res;
+  }
+  return mp_div (a, b, a, NULL);
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_reduce_setup.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_rshd.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_rshd.c
new file mode 100644 (file)
index 0000000..2a693c5
--- /dev/null
@@ -0,0 +1,72 @@
+#include <tommath.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
+ */
+
+/* shift right a certain amount of digits */
+void mp_rshd (mp_int * a, int b)
+{
+  int     x;
+
+  /* if b <= 0 then ignore it */
+  if (b <= 0) {
+    return;
+  }
+
+  /* if b > used then simply zero it and return */
+  if (a->used <= b) {
+    mp_zero (a);
+    return;
+  }
+
+  {
+    register mp_digit *bottom, *top;
+
+    /* shift the digits down */
+
+    /* bottom */
+    bottom = a->dp;
+
+    /* top [offset into digits] */
+    top = a->dp + b;
+
+    /* this is implemented as a sliding window where 
+     * the window is b-digits long and digits from 
+     * the top of the window are copied to the bottom
+     *
+     * e.g.
+
+     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
+                 /\                   |      ---->
+                  \-------------------/      ---->
+     */
+    for (x = 0; x < (a->used - b); x++) {
+      *bottom++ = *top++;
+    }
+
+    /* zero the top digits */
+    for (; x < a->used; x++) {
+      *bottom++ = 0;
+    }
+  }
+  
+  /* remove excess digits */
+  a->used -= b;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_rshd.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_set.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_set.c
new file mode 100644 (file)
index 0000000..174adcb
--- /dev/null
@@ -0,0 +1,29 @@
+#include <tommath.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
+ */
+
+/* set to a digit */
+void mp_set (mp_int * a, mp_digit b)
+{
+  mp_zero (a);
+  a->dp[0] = b & MP_MASK;
+  a->used  = (a->dp[0] != 0) ? 1 : 0;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_set.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_set_int.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_set_int.c
new file mode 100644 (file)
index 0000000..cf10ea1
--- /dev/null
@@ -0,0 +1,48 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_shrink.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_shrink.c
new file mode 100644 (file)
index 0000000..4b8c5ef
--- /dev/null
@@ -0,0 +1,35 @@
+#include <tommath.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
+ */
+
+/* shrink a bignum */
+int mp_shrink (mp_int * a)
+{
+  mp_digit *tmp;
+  if (a->alloc != a->used && a->used > 0) {
+    if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
+      return MP_MEM;
+    }
+    a->dp    = tmp;
+    a->alloc = a->used;
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_shrink.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_signed_bin_size.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_signed_bin_size.c
new file mode 100644 (file)
index 0000000..6739d19
--- /dev/null
@@ -0,0 +1,27 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqr.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqr.c
new file mode 100644 (file)
index 0000000..868ccbb
--- /dev/null
@@ -0,0 +1,58 @@
+#include <tommath.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
+ */
+
+/* computes b = a*a */
+int
+mp_sqr (mp_int * a, mp_int * b)
+{
+  int     res;
+
+#ifdef BN_MP_TOOM_SQR_C
+  /* use Toom-Cook? */
+  if (a->used >= TOOM_SQR_CUTOFF) {
+    res = mp_toom_sqr(a, b);
+  /* Karatsuba? */
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_SQR_C
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
+    res = mp_karatsuba_sqr (a, b);
+  } else 
+#endif
+  {
+#ifdef BN_FAST_S_MP_SQR_C
+    /* can we use the fast comba multiplier? */
+    if ((a->used * 2 + 1) < MP_WARRAY && 
+         a->used < 
+         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+      res = fast_s_mp_sqr (a, b);
+    } else
+#endif
+#ifdef BN_S_MP_SQR_C
+      res = s_mp_sqr (a, b);
+#else
+      res = MP_VAL;
+#endif
+  }
+  b->sign = MP_ZPOS;
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sqr.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqrmod.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqrmod.c
new file mode 100644 (file)
index 0000000..161cbbb
--- /dev/null
@@ -0,0 +1,41 @@
+#include <tommath.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
+ */
+
+/* c = a * a (mod b) */
+int
+mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_sqr (a, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, b, c);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sqrmod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqrt.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqrt.c
new file mode 100644 (file)
index 0000000..8fd057c
--- /dev/null
@@ -0,0 +1,81 @@
+#include <tommath.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
+ */
+
+/* this function is less generic than mp_n_root, simpler and faster */
+int mp_sqrt(mp_int *arg, mp_int *ret) 
+{
+  int res;
+  mp_int t1,t2;
+
+  /* must be positive */
+  if (arg->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  /* easy out */
+  if (mp_iszero(arg) == MP_YES) {
+    mp_zero(ret);
+    return MP_OKAY;
+  }
+
+  if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init(&t2)) != MP_OKAY) {
+    goto E2;
+  }
+
+  /* First approx. (not very bad for large arg) */
+  mp_rshd (&t1,t1.used/2);
+
+  /* t1 > 0  */ 
+  if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+    goto E1;
+  }
+  if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+    goto E1;
+  }
+  if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+    goto E1;
+  }
+  /* And now t1 > sqrt(arg) */
+  do { 
+    if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+      goto E1;
+    }
+    if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+      goto E1;
+    }
+    if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+      goto E1;
+    }
+    /* t1 >= sqrt(arg) >= t2 at this point */
+  } while (mp_cmp_mag(&t1,&t2) == MP_GT);
+
+  mp_exch(&t1,ret);
+
+E1: mp_clear(&t2);
+E2: mp_clear(&t1);
+  return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sqrt.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sub.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sub.c
new file mode 100644 (file)
index 0000000..f5015cc
--- /dev/null
@@ -0,0 +1,59 @@
+#include <tommath.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
+ */
+
+/* high level subtraction (handles signs) */
+int
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  sa = a->sign;
+  sb = b->sign;
+
+  if (sa != sb) {
+    /* subtract a negative from a positive, OR */
+    /* subtract a positive from a negative. */
+    /* In either case, ADD their magnitudes, */
+    /* and use the sign of the first number. */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* subtract a positive from a positive, OR */
+    /* subtract a negative from a negative. */
+    /* First, take the difference between their */
+    /* magnitudes, then... */
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      /* Copy the sign from the first */
+      c->sign = sa;
+      /* The first has a larger or equal magnitude */
+      res = s_mp_sub (a, b, c);
+    } else {
+      /* The result has the *opposite* sign from */
+      /* the first number. */
+      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+      /* The second has a larger magnitude */
+      res = s_mp_sub (b, a, c);
+    }
+  }
+  return res;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sub.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sub_d.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sub_d.c
new file mode 100644 (file)
index 0000000..06cdca6
--- /dev/null
@@ -0,0 +1,93 @@
+#include <tommath.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
+ */
+
+/* single digit subtraction */
+int
+mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit *tmpa, *tmpc, mu;
+  int       res, ix, oldused;
+
+  /* grow c as required */
+  if (c->alloc < a->used + 1) {
+     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* if a is negative just do an unsigned
+   * addition [with fudged signs]
+   */
+  if (a->sign == MP_NEG) {
+     a->sign = MP_ZPOS;
+     res     = mp_add_d(a, b, c);
+     a->sign = c->sign = MP_NEG;
+
+     /* clamp */
+     mp_clamp(c);
+
+     return res;
+  }
+
+  /* setup regs */
+  oldused = c->used;
+  tmpa    = a->dp;
+  tmpc    = c->dp;
+
+  /* if a <= b simply fix the single digit */
+  if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
+     if (a->used == 1) {
+        *tmpc++ = b - *tmpa;
+     } else {
+        *tmpc++ = b;
+     }
+     ix      = 1;
+
+     /* negative/1digit */
+     c->sign = MP_NEG;
+     c->used = 1;
+  } else {
+     /* positive/size */
+     c->sign = MP_ZPOS;
+     c->used = a->used;
+
+     /* subtract first digit */
+     *tmpc    = *tmpa++ - b;
+     mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+     *tmpc++ &= MP_MASK;
+
+     /* handle rest of the digits */
+     for (ix = 1; ix < a->used; ix++) {
+        *tmpc    = *tmpa++ - mu;
+        mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+        *tmpc++ &= MP_MASK;
+     }
+  }
+
+  /* zero excess digits */
+  while (ix++ < oldused) {
+     *tmpc++ = 0;
+  }
+  mp_clamp(c);
+  return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_sub_d.c,v $ */
+/* $Revision: 1.6 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_submod.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_submod.c
new file mode 100644 (file)
index 0000000..869e23c
--- /dev/null
@@ -0,0 +1,42 @@
+#include <tommath.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
+ */
+
+/* d = a - b (mod c) */
+int
+mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_submod.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_signed_bin.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_signed_bin.c
new file mode 100644 (file)
index 0000000..9df83ca
--- /dev/null
@@ -0,0 +1,33 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c
new file mode 100644 (file)
index 0000000..677f827
--- /dev/null
@@ -0,0 +1,31 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c
new file mode 100644 (file)
index 0000000..c137f10
--- /dev/null
@@ -0,0 +1,48 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c
new file mode 100644 (file)
index 0000000..0dc00c6
--- /dev/null
@@ -0,0 +1,31 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toom_mul.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toom_mul.c
new file mode 100644 (file)
index 0000000..ad5d9e9
--- /dev/null
@@ -0,0 +1,284 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toom_sqr.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toom_sqr.c
new file mode 100644 (file)
index 0000000..48880d0
--- /dev/null
@@ -0,0 +1,226 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toradix.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toradix.c
new file mode 100644 (file)
index 0000000..0adc28d
--- /dev/null
@@ -0,0 +1,75 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toradix_n.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toradix_n.c
new file mode 100644 (file)
index 0000000..796ed55
--- /dev/null
@@ -0,0 +1,88 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c
new file mode 100644 (file)
index 0000000..6dc3bd5
--- /dev/null
@@ -0,0 +1,28 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_mp_xor.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_xor.c
new file mode 100644 (file)
index 0000000..59ff2e1
--- /dev/null
@@ -0,0 +1,51 @@
+#include <tommath.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
+ */
+
+/* XOR two ints together */
+int
+mp_xor (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+     t.dp[ix] ^= x->dp[ix];
+  }
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_xor.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_zero.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_zero.c
new file mode 100644 (file)
index 0000000..b0977d4
--- /dev/null
@@ -0,0 +1,36 @@
+#include <tommath.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
+ */
+
+/* set to zero */
+void mp_zero (mp_int * a)
+{
+  int       n;
+  mp_digit *tmp;
+
+  a->sign = MP_ZPOS;
+  a->used = 0;
+
+  tmp = a->dp;
+  for (n = 0; n < a->alloc; n++) {
+     *tmp++ = 0;
+  }
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_mp_zero.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_mp_zero_multi.c b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_zero_multi.c
new file mode 100644 (file)
index 0000000..339a75f
--- /dev/null
@@ -0,0 +1,35 @@
+#include <tommath.h>
+#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 <stdarg.h>
+
+/* 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/source4/heimdal/lib/hcrypto/libtommath/bn_prime_tab.c b/source4/heimdal/lib/hcrypto/libtommath/bn_prime_tab.c
new file mode 100644 (file)
index 0000000..bd25247
--- /dev/null
@@ -0,0 +1,61 @@
+#include <tommath.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
+ */
+const mp_digit ltm_prime_tab[] = {
+  0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+#ifndef MP_8BIT
+  0x0083,
+  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+#endif
+};
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_prime_tab.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_reverse.c b/source4/heimdal/lib/hcrypto/libtommath/bn_reverse.c
new file mode 100644 (file)
index 0000000..ddfa827
--- /dev/null
@@ -0,0 +1,39 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_add.c b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_add.c
new file mode 100644 (file)
index 0000000..f034ae6
--- /dev/null
@@ -0,0 +1,109 @@
+#include <tommath.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
+ */
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+int
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int *x;
+  int     olduse, res, min, max;
+
+  /* find sizes, we let |a| <= |b| which means we have to sort
+   * them.  "x" will point to the input with the most digits
+   */
+  if (a->used > b->used) {
+    min = b->used;
+    max = a->used;
+    x = a;
+  } else {
+    min = a->used;
+    max = b->used;
+    x = b;
+  }
+
+  /* init result */
+  if (c->alloc < max + 1) {
+    if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get old used digit count and set new one */
+  olduse = c->used;
+  c->used = max + 1;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+
+    /* first input */
+    tmpa = a->dp;
+
+    /* second input */
+    tmpb = b->dp;
+
+    /* destination */
+    tmpc = c->dp;
+
+    /* zero the carry */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+      *tmpc = *tmpa++ + *tmpb++ + u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+      /* take away carry bit from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, that is in A+B 
+     * if A or B has more digits add those in 
+     */
+    if (min != max) {
+      for (; i < max; i++) {
+        /* T[i] = X[i] + U */
+        *tmpc = x->dp[i] + u;
+
+        /* U = carry bit of T[i] */
+        u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+        /* take away carry bit from T[i] */
+        *tmpc++ &= MP_MASK;
+      }
+    }
+
+    /* add carry */
+    *tmpc++ = u;
+
+    /* clear digits above oldused */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_add.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_exptmod.c b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_exptmod.c
new file mode 100644 (file)
index 0000000..097d894
--- /dev/null
@@ -0,0 +1,252 @@
+#include <tommath.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
+ */
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res, mu;
+  mp_digit buf;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+  int (*redux)(mp_int*,mp_int*,mp_int*);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+    if (winsize > 5) {
+       winsize = 5;
+    }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err; 
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* create mu, used for Barrett reduction */
+  if ((err = mp_init (&mu)) != MP_OKAY) {
+    goto LBL_M;
+  }
+  
+  if (redmode == 0) {
+     if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce;
+  } else {
+     if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce_2k_l;
+  }    
+
+  /* create M table
+   *
+   * The M table contains powers of the base, 
+   * e.g. M[x] = G**x mod P
+   *
+   * The first half of the table is not 
+   * computed though accept for M[0] and M[1]
+   */
+  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring 
+   * M[1] (winsize-1) times 
+   */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    /* square it */
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], 
+                       &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+
+    /* reduce modulo P */
+    if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+   */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+    if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_MU;
+  }
+  mp_set (&res, 1);
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset the bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int) DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_exptmod.c,v $ */
+/* $Revision: 1.5 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c
new file mode 100644 (file)
index 0000000..f5bbf39
--- /dev/null
@@ -0,0 +1,90 @@
+#include <tommath.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
+ */
+
+/* multiplies |a| * |b| and only computes upto digs digits of result
+ * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
+ * many digits of output are created.
+ */
+int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+  if (((digs) < MP_WARRAY) &&
+      MIN (a->used, b->used) < 
+          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_digs (a, b, c, digs);
+  }
+
+  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+    return res;
+  }
+  t.used = digs;
+
+  /* compute the digits of the product directly */
+  pa = a->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* set the carry to zero */
+    u = 0;
+
+    /* limit ourselves to making digs digits of output */
+    pb = MIN (b->used, digs - ix);
+
+    /* setup some aliases */
+    /* copy of the digit from a used within the nested loop */
+    tmpx = a->dp[ix];
+    
+    /* an alias for the destination shifted ix places */
+    tmpt = t.dp + ix;
+    
+    /* an alias for the digits of b */
+    tmpy = b->dp;
+
+    /* compute the columns of the output and propagate the carry */
+    for (iy = 0; iy < pb; iy++) {
+      /* compute the column as a mp_word */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* the new column is the lower part of the result */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get the carry word from the result */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    /* set carry if it is placed below digs */
+    if (ix + iy < digs) {
+      *tmpt = u;
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, c);
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_digs.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c
new file mode 100644 (file)
index 0000000..2b718f2
--- /dev/null
@@ -0,0 +1,81 @@
+#include <tommath.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
+ */
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+int
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+  if (((a->used + b->used + 1) < MP_WARRAY)
+      && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_high_digs (a, b, c, digs);
+  }
+#endif
+
+  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+    return res;
+  }
+  t.used = a->used + b->used + 1;
+
+  pa = a->used;
+  pb = b->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* clear the carry */
+    u = 0;
+
+    /* left hand side of A[ix] * B[iy] */
+    tmpx = a->dp[ix];
+
+    /* alias to the address of where the digits will be stored */
+    tmpt = &(t.dp[digs]);
+
+    /* alias for where to read the right hand side from */
+    tmpy = b->dp + (digs - ix);
+
+    for (iy = digs - ix; iy < pb; iy++) {
+      /* calculate the double precision result */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* get the lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* carry the carry */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    *tmpt = u;
+  }
+  mp_clamp (&t);
+  mp_exch (&t, c);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_mul_high_digs.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_sqr.c b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_sqr.c
new file mode 100644 (file)
index 0000000..d2531c2
--- /dev/null
@@ -0,0 +1,84 @@
+#include <tommath.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
+ */
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+int s_mp_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+  int     res, ix, iy, pa;
+  mp_word r;
+  mp_digit u, tmpx, *tmpt;
+
+  pa = a->used;
+  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* default used is maximum possible size */
+  t.used = 2*pa + 1;
+
+  for (ix = 0; ix < pa; ix++) {
+    /* first calculate the digit at 2*ix */
+    /* calculate double precision result */
+    r = ((mp_word) t.dp[2*ix]) +
+        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+    /* store lower part in result */
+    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* get the carry */
+    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+    /* left hand side of A[ix] * A[iy] */
+    tmpx        = a->dp[ix];
+
+    /* alias for where to store the results */
+    tmpt        = t.dp + (2*ix + 1);
+    
+    for (iy = ix + 1; iy < pa; iy++) {
+      /* first calculate the product */
+      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+      /* now calculate the double precision result, note we use
+       * addition instead of *2 since it's easier to optimize
+       */
+      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+      /* store lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get carry */
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+    /* propagate upwards */
+    while (u != ((mp_digit) 0)) {
+      r       = ((mp_word) *tmpt) + ((mp_word) u);
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, b);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_sqr.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_sub.c b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_sub.c
new file mode 100644 (file)
index 0000000..6a60c39
--- /dev/null
@@ -0,0 +1,89 @@
+#include <tommath.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
+ */
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+int
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     olduse, res, min, max;
+
+  /* find sizes */
+  min = b->used;
+  max = a->used;
+
+  /* init result */
+  if (c->alloc < max) {
+    if ((res = mp_grow (c, max)) != MP_OKAY) {
+      return res;
+    }
+  }
+  olduse = c->used;
+  c->used = max;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+    tmpa = a->dp;
+    tmpb = b->dp;
+    tmpc = c->dp;
+
+    /* set carry to zero */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* T[i] = A[i] - B[i] - U */
+      *tmpc = *tmpa++ - *tmpb++ - u;
+
+      /* U = carry bit of T[i]
+       * Note this saves performing an AND operation since
+       * if a carry does occur it will propagate all the way to the
+       * MSB.  As a result a single shift is enough to get the carry
+       */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, e.g. if A has more digits than B  */
+    for (; i < max; i++) {
+      /* T[i] = A[i] - U */
+      *tmpc = *tmpa++ - u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* clear digits above used (since we may not have grown result above) */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/bn_s_mp_sub.c,v $ */
+/* $Revision: 1.4 $ */
+/* $Date: 2006/12/28 01:25:13 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bncore.c b/source4/heimdal/lib/hcrypto/libtommath/bncore.c
new file mode 100644 (file)
index 0000000..8fb1824
--- /dev/null
@@ -0,0 +1,36 @@
+#include <tommath.h>
+#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/source4/heimdal/lib/hcrypto/libtommath/booker.pl b/source4/heimdal/lib/hcrypto/libtommath/booker.pl
new file mode 100644 (file)
index 0000000..49f1889
--- /dev/null
@@ -0,0 +1,265 @@
+#!/bin/perl
+#
+#Used to prepare the book "tommath.src" for LaTeX by pre-processing it into a .tex file
+#
+#Essentially you write the "tommath.src" as normal LaTex except where you want code snippets you put
+#
+#EXAM,file
+#
+#This preprocessor will then open "file" and insert it as a verbatim copy.
+#
+#Tom St Denis
+
+#get graphics type
+if (shift =~ /PDF/) {
+   $graph = "";
+} else {
+   $graph = ".ps";
+}   
+
+open(IN,"<tommath.src") or die "Can't open source file";
+open(OUT,">tommath.tex") or die "Can't open destination file";
+
+print "Scanning for sections\n";
+$chapter = $section = $subsection = 0;
+$x = 0;
+while (<IN>) {
+   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,"<tommath.src") or die "Can't open source file";
+$readline = $wroteline = 0;
+$srcline = 0;
+
+while (<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 (<SRC>) {
+            $text[$line++] = $_;
+            last if ($_ =~ /math\.libtomcrypt\.com/);
+         }
+         <SRC>;   
+      }
+      
+      $inline = 0;
+      while (<SRC>) {
+      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/source4/heimdal/lib/hcrypto/libtommath/callgraph.txt b/source4/heimdal/lib/hcrypto/libtommath/callgraph.txt
new file mode 100644 (file)
index 0000000..2efcf24
--- /dev/null
@@ -0,0 +1,11913 @@
+BN_PRIME_TAB_C
+
+
+BN_MP_SQRT_C
++--->BN_MP_N_ROOT_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_SET_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_EXPT_D_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_SQR_C
+|   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MUL_C
+|   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_MUL_C
+|   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_MUL_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_SUB_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
++--->BN_MP_DIV_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_SET_C
+|   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_ABS_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_MUL_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_ADD_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CMP_D_C
+
+
+BN_MP_EXCH_C
+
+
+BN_MP_IS_SQUARE_C
++--->BN_MP_MOD_D_C
+|   +--->BN_MP_DIV_D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SET_INT_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_SET_INT_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_GET_INT_C
++--->BN_MP_SQRT_C
+|   +--->BN_MP_N_ROOT_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_EXPT_D_C
+|   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_SQR_C
+|   |   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_MUL_C
+|   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_ABS_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_SUB_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_2_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_SQR_C
+|   +--->BN_MP_TOOM_SQR_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_KARATSUBA_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_SQR_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_NEG_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
+
+
+BN_MP_EXPTMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_INVMOD_C
+|   +--->BN_FAST_MP_INVMOD_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_MOD_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_CMP_D_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INVMOD_SLOW_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_CMP_D_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_ABS_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_MULTI_C
++--->BN_MP_REDUCE_IS_2K_L_C
++--->BN_S_MP_EXPTMOD_C
+|   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_REDUCE_SETUP_C
+|   |   +--->BN_MP_2EXPT_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_DIV_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_REDUCE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_C
+|   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_S_MP_MUL_HIGH_DIGS_C
+|   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_D_C
+|   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_REDUCE_2K_SETUP_L_C
+|   |   +--->BN_MP_2EXPT_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_REDUCE_2K_L_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_MUL_C
+|   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_MOD_C
+|   |   +--->BN_MP_DIV_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_SQR_C
+|   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SQR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_MUL_C
+|   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_SET_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_DR_IS_MODULUS_C
++--->BN_MP_REDUCE_IS_2K_C
+|   +--->BN_MP_REDUCE_2K_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_COUNT_BITS_C
++--->BN_MP_EXPTMOD_FAST_C
+|   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_MONTGOMERY_SETUP_C
+|   +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   +--->BN_MP_MONTGOMERY_REDUCE_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   +--->BN_MP_DR_SETUP_C
+|   +--->BN_MP_DR_REDUCE_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   +--->BN_MP_REDUCE_2K_SETUP_C
+|   |   +--->BN_MP_2EXPT_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_REDUCE_2K_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+|   |   +--->BN_MP_2EXPT_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_MULMOD_C
+|   |   +--->BN_MP_MUL_C
+|   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_MOD_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_SET_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MOD_C
+|   |   +--->BN_MP_DIV_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_SQR_C
+|   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SQR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_MUL_C
+|   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_EXCH_C
+
+
+BN_MP_OR_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_ZERO_C
+
+
+BN_MP_GROW_C
+
+
+BN_MP_COUNT_BITS_C
+
+
+BN_MP_PRIME_FERMAT_C
++--->BN_MP_CMP_D_C
++--->BN_MP_INIT_C
++--->BN_MP_EXPTMOD_C
+|   +--->BN_MP_INVMOD_C
+|   |   +--->BN_FAST_MP_INVMOD_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INVMOD_SLOW_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_REDUCE_IS_2K_L_C
+|   +--->BN_S_MP_EXPTMOD_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_REDUCE_SETUP_C
+|   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_REDUCE_C
+|   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_REDUCE_2K_SETUP_L_C
+|   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_REDUCE_2K_L_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MOD_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_SQR_C
+|   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_MUL_C
+|   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_DR_IS_MODULUS_C
+|   +--->BN_MP_REDUCE_IS_2K_C
+|   |   +--->BN_MP_REDUCE_2K_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_EXPTMOD_FAST_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_MONTGOMERY_SETUP_C
+|   |   +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_MONTGOMERY_REDUCE_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_DR_SETUP_C
+|   |   +--->BN_MP_DR_REDUCE_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_REDUCE_2K_SETUP_C
+|   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_REDUCE_2K_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+|   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MULMOD_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_SQR_C
+|   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_MUL_C
+|   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
++--->BN_MP_CMP_C
+|   +--->BN_MP_CMP_MAG_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_SUBMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+
+
+BN_MP_MOD_2D_C
++--->BN_MP_ZERO_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_TORADIX_N_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_DIV_D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_DIV_3_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CMP_C
++--->BN_MP_CMP_MAG_C
+
+
+BNCORE_C
+
+
+BN_MP_TORADIX_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_DIV_D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_DIV_3_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_ADD_D_C
++--->BN_MP_GROW_C
++--->BN_MP_SUB_D_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_DIV_3_C
++--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_FAST_S_MP_MUL_DIGS_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_SQRMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_SQR_C
+|   +--->BN_MP_TOOM_SQR_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_KARATSUBA_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_SQR_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+
+
+BN_MP_INVMOD_C
++--->BN_FAST_MP_INVMOD_C
+|   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_MOD_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_DIV_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_ABS_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_SET_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_DIV_2_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_CMP_D_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_INVMOD_SLOW_C
+|   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_MOD_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_DIV_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_ABS_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_SET_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_DIV_2_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_CMP_D_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
+
+
+BN_MP_AND_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_MUL_D_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_FAST_MP_INVMOD_C
++--->BN_MP_INIT_MULTI_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_MOD_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_DIV_2_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
+|   +--->BN_MP_CMP_MAG_C
++--->BN_MP_CMP_D_C
++--->BN_MP_ADD_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_FWRITE_C
++--->BN_MP_RADIX_SIZE_C
+|   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_DIV_D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_TORADIX_C
+|   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_DIV_D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_S_MP_SQR_C
++--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_N_ROOT_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_EXPT_D_C
+|   +--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_SQR_C
+|   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SQR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_MUL_C
+|   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_TOOM_MUL_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_KARATSUBA_MUL_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_ABS_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_CMP_C
+|   +--->BN_MP_CMP_MAG_C
++--->BN_MP_SUB_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_ADD_D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+
+
+BN_MP_RADIX_SIZE_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_DIV_D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_DIV_3_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_READ_SIGNED_BIN_C
++--->BN_MP_READ_UNSIGNED_BIN_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
+
+
+BN_MP_PRIME_RANDOM_EX_C
++--->BN_MP_READ_UNSIGNED_BIN_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_PRIME_IS_PRIME_C
+|   +--->BN_MP_CMP_D_C
+|   +--->BN_MP_PRIME_IS_DIVISIBLE_C
+|   |   +--->BN_MP_MOD_D_C
+|   |   |   +--->BN_MP_DIV_D_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_INIT_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_INIT_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_INIT_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_SET_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_PRIME_MILLER_RABIN_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_SUB_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CNT_LSB_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXPTMOD_C
+|   |   |   +--->BN_MP_INVMOD_C
+|   |   |   |   +--->BN_FAST_MP_INVMOD_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_INVMOD_SLOW_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_ABS_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_REDUCE_IS_2K_L_C
+|   |   |   +--->BN_S_MP_EXPTMOD_C
+|   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   +--->BN_MP_REDUCE_SETUP_C
+|   |   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_REDUCE_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_REDUCE_2K_SETUP_L_C
+|   |   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_REDUCE_2K_L_C
+|   |   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_DR_IS_MODULUS_C
+|   |   |   +--->BN_MP_REDUCE_IS_2K_C
+|   |   |   |   +--->BN_MP_REDUCE_2K_C
+|   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_EXPTMOD_FAST_C
+|   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   +--->BN_MP_MONTGOMERY_SETUP_C
+|   |   |   |   +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_MONTGOMERY_REDUCE_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_DR_SETUP_C
+|   |   |   |   +--->BN_MP_DR_REDUCE_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_REDUCE_2K_SETUP_C
+|   |   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_REDUCE_2K_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+|   |   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MULMOD_C
+|   |   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_SQRMOD_C
+|   |   |   +--->BN_MP_SQR_C
+|   |   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_ADD_D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_ADD_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
+
+
+BN_MP_KARATSUBA_SQR_C
++--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_SQR_C
+|   +--->BN_MP_TOOM_SQR_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_SQR_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_S_MP_SQR_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
++--->BN_S_MP_ADD_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_LSHD_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_ZERO_C
++--->BN_MP_ADD_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_INIT_COPY_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
+
+
+BN_MP_CLAMP_C
+
+
+BN_MP_TOOM_SQR_C
++--->BN_MP_INIT_MULTI_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_MOD_2D_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_SQR_C
+|   +--->BN_MP_KARATSUBA_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_SQR_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_2_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_LSHD_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_3_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_LSHD_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_MOD_C
++--->BN_MP_INIT_C
++--->BN_MP_DIV_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_SET_C
+|   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_ABS_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_MUL_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_ADD_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
+
+
+BN_MP_INIT_C
+
+
+BN_MP_TOOM_MUL_C
++--->BN_MP_INIT_MULTI_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_MOD_2D_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_KARATSUBA_MUL_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_2_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_LSHD_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_3_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_LSHD_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_PRIME_IS_PRIME_C
++--->BN_MP_CMP_D_C
++--->BN_MP_PRIME_IS_DIVISIBLE_C
+|   +--->BN_MP_MOD_D_C
+|   |   +--->BN_MP_DIV_D_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_INIT_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_INIT_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_PRIME_MILLER_RABIN_C
+|   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_SUB_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CNT_LSB_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_EXPTMOD_C
+|   |   +--->BN_MP_INVMOD_C
+|   |   |   +--->BN_FAST_MP_INVMOD_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_INVMOD_SLOW_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_ABS_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_REDUCE_IS_2K_L_C
+|   |   +--->BN_S_MP_EXPTMOD_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_REDUCE_SETUP_C
+|   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_REDUCE_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_REDUCE_2K_SETUP_L_C
+|   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_REDUCE_2K_L_C
+|   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_SQR_C
+|   |   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_DR_IS_MODULUS_C
+|   |   +--->BN_MP_REDUCE_IS_2K_C
+|   |   |   +--->BN_MP_REDUCE_2K_C
+|   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_EXPTMOD_FAST_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_MONTGOMERY_SETUP_C
+|   |   |   +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_MONTGOMERY_REDUCE_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_DR_SETUP_C
+|   |   |   +--->BN_MP_DR_REDUCE_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_REDUCE_2K_SETUP_C
+|   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_REDUCE_2K_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+|   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MULMOD_C
+|   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_SQR_C
+|   |   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_SQRMOD_C
+|   |   +--->BN_MP_SQR_C
+|   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_COPY_C
++--->BN_MP_GROW_C
+
+
+BN_S_MP_SUB_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_READ_UNSIGNED_BIN_C
++--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_2D_C
+|   +--->BN_MP_COPY_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_EXPTMOD_FAST_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_INIT_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MONTGOMERY_SETUP_C
++--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
++--->BN_MP_MONTGOMERY_REDUCE_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
++--->BN_MP_DR_SETUP_C
++--->BN_MP_DR_REDUCE_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
++--->BN_MP_REDUCE_2K_SETUP_C
+|   +--->BN_MP_2EXPT_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_2K_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_MUL_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+|   +--->BN_MP_2EXPT_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_SET_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MUL_2_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_MULMOD_C
+|   +--->BN_MP_MUL_C
+|   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_MOD_C
+|   |   +--->BN_MP_DIV_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_ABS_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2D_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_MOD_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_SQR_C
+|   +--->BN_MP_TOOM_SQR_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_KARATSUBA_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   +--->BN_FAST_S_MP_SQR_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_TOOM_MUL_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_KARATSUBA_MUL_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
++--->BN_MP_EXCH_C
+
+
+BN_MP_TO_UNSIGNED_BIN_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_DIV_2D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_SET_INT_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_2D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_MOD_D_C
++--->BN_MP_DIV_D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_DIV_3_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_SQR_C
++--->BN_MP_TOOM_SQR_C
+|   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MUL_2_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_2_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_MUL_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_3_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_KARATSUBA_SQR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLEAR_C
++--->BN_FAST_S_MP_SQR_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_S_MP_SQR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_MULMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_TOOM_MUL_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_KARATSUBA_MUL_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+
+
+BN_MP_DIV_2D_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_C
++--->BN_MP_MOD_2D_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
++--->BN_MP_RSHD_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
+
+
+BN_S_MP_ADD_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_FAST_S_MP_SQR_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_S_MP_MUL_DIGS_C
++--->BN_FAST_S_MP_MUL_DIGS_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_XOR_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_RADIX_SMAP_C
+
+
+BN_MP_DR_IS_MODULUS_C
+
+
+BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_2EXPT_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_MUL_2_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
+
+
+BN_MP_SUB_C
++--->BN_S_MP_ADD_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
+
+
+BN_MP_INIT_MULTI_C
++--->BN_MP_INIT_C
++--->BN_MP_CLEAR_C
+
+
+BN_S_MP_MUL_HIGH_DIGS_C
++--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_PRIME_NEXT_PRIME_C
++--->BN_MP_CMP_D_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_SUB_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_ADD_D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_D_C
+|   +--->BN_MP_DIV_D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_C
++--->BN_MP_ADD_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_PRIME_MILLER_RABIN_C
+|   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CNT_LSB_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_EXPTMOD_C
+|   |   +--->BN_MP_INVMOD_C
+|   |   |   +--->BN_FAST_MP_INVMOD_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_INVMOD_SLOW_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_ABS_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_REDUCE_IS_2K_L_C
+|   |   +--->BN_S_MP_EXPTMOD_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_REDUCE_SETUP_C
+|   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_REDUCE_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_REDUCE_2K_SETUP_L_C
+|   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_REDUCE_2K_L_C
+|   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_SQR_C
+|   |   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_DR_IS_MODULUS_C
+|   |   +--->BN_MP_REDUCE_IS_2K_C
+|   |   |   +--->BN_MP_REDUCE_2K_C
+|   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_EXPTMOD_FAST_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_MONTGOMERY_SETUP_C
+|   |   |   +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_MONTGOMERY_REDUCE_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_DR_SETUP_C
+|   |   |   +--->BN_MP_DR_REDUCE_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_REDUCE_2K_SETUP_C
+|   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_REDUCE_2K_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+|   |   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MULMOD_C
+|   |   |   |   +--->BN_MP_MUL_C
+|   |   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_MOD_C
+|   |   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_SQR_C
+|   |   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_SQRMOD_C
+|   |   +--->BN_MP_SQR_C
+|   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_SIGNED_BIN_SIZE_C
++--->BN_MP_UNSIGNED_BIN_SIZE_C
+|   +--->BN_MP_COUNT_BITS_C
+
+
+BN_MP_INVMOD_SLOW_C
++--->BN_MP_INIT_MULTI_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_DIV_2_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
+|   +--->BN_MP_CMP_MAG_C
++--->BN_MP_CMP_D_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_LCM_C
++--->BN_MP_INIT_MULTI_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_GCD_C
+|   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CNT_LSB_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_DIV_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_SET_C
+|   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_ABS_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_MUL_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_TOOM_MUL_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_KARATSUBA_MUL_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_2K_L_C
++--->BN_MP_INIT_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_DIV_2D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_TOOM_MUL_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_KARATSUBA_MUL_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_S_MP_ADD_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_REVERSE_C
+
+
+BN_MP_PRIME_IS_DIVISIBLE_C
++--->BN_MP_MOD_D_C
+|   +--->BN_MP_DIV_D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+
+
+BN_MP_SET_C
++--->BN_MP_ZERO_C
+
+
+BN_MP_GCD_C
++--->BN_MP_ABS_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_CNT_LSB_C
++--->BN_MP_DIV_2D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_EXCH_C
++--->BN_S_MP_SUB_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_2K_SETUP_L_C
++--->BN_MP_INIT_C
++--->BN_MP_2EXPT_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_COUNT_BITS_C
++--->BN_S_MP_SUB_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_READ_RADIX_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_SUB_D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
+
+
+BN_FAST_S_MP_MUL_HIGH_DIGS_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_FAST_MP_MONTGOMERY_REDUCE_C
++--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+
+
+BN_MP_DIV_D_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_DIV_2D_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_DIV_3_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_2K_SETUP_C
++--->BN_MP_INIT_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_2EXPT_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_C
++--->BN_S_MP_SUB_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
+
+
+BN_MP_INIT_SET_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
+
+
+BN_MP_REDUCE_2K_C
++--->BN_MP_INIT_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_DIV_2D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_MUL_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_S_MP_ADD_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_ERROR_C
+
+
+BN_MP_EXPT_D_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_SQR_C
+|   +--->BN_MP_TOOM_SQR_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_KARATSUBA_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_SQR_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_TOOM_MUL_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_KARATSUBA_MUL_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+
+
+BN_S_MP_EXPTMOD_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_INIT_C
++--->BN_MP_CLEAR_C
++--->BN_MP_REDUCE_SETUP_C
+|   +--->BN_MP_2EXPT_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_C
+|   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MUL_C
+|   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_S_MP_MUL_HIGH_DIGS_C
+|   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_D_C
+|   +--->BN_MP_SET_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_2K_SETUP_L_C
+|   +--->BN_MP_2EXPT_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_2K_L_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_MUL_C
+|   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_SQR_C
+|   +--->BN_MP_TOOM_SQR_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_KARATSUBA_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   +--->BN_FAST_S_MP_SQR_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_SQR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_TOOM_MUL_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_KARATSUBA_MUL_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_EXCH_C
+
+
+BN_MP_ABS_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
+
+
+BN_MP_INIT_SET_INT_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_INT_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
+
+
+BN_MP_SUB_D_C
++--->BN_MP_GROW_C
++--->BN_MP_ADD_D_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_TO_SIGNED_BIN_C
++--->BN_MP_TO_UNSIGNED_BIN_C
+|   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_DIV_2_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_REDUCE_IS_2K_C
++--->BN_MP_REDUCE_2K_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_MUL_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_COUNT_BITS_C
+
+
+BN_MP_INIT_SIZE_C
++--->BN_MP_INIT_C
+
+
+BN_MP_DIV_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_MULTI_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_SET_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_ABS_C
++--->BN_MP_MUL_2D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2D_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_INIT_C
++--->BN_MP_INIT_C
++--->BN_MP_INIT_COPY_C
++--->BN_MP_LSHD_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_RSHD_C
++--->BN_MP_RSHD_C
++--->BN_MP_MUL_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CLEAR_C
+
+
+BN_MP_MONTGOMERY_REDUCE_C
++--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_RSHD_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+
+
+BN_MP_MUL_2_C
++--->BN_MP_GROW_C
+
+
+BN_MP_UNSIGNED_BIN_SIZE_C
++--->BN_MP_COUNT_BITS_C
+
+
+BN_MP_ADDMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_ADD_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+
+
+BN_MP_ADD_C
++--->BN_S_MP_ADD_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
+
+
+BN_MP_TO_SIGNED_BIN_N_C
++--->BN_MP_SIGNED_BIN_SIZE_C
+|   +--->BN_MP_UNSIGNED_BIN_SIZE_C
+|   |   +--->BN_MP_COUNT_BITS_C
++--->BN_MP_TO_SIGNED_BIN_C
+|   +--->BN_MP_TO_UNSIGNED_BIN_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_IS_2K_L_C
+
+
+BN_MP_RAND_C
++--->BN_MP_ZERO_C
++--->BN_MP_ADD_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_SUB_D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_LSHD_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_RSHD_C
+
+
+BN_MP_CNT_LSB_C
+
+
+BN_MP_2EXPT_C
++--->BN_MP_ZERO_C
++--->BN_MP_GROW_C
+
+
+BN_MP_RSHD_C
++--->BN_MP_ZERO_C
+
+
+BN_MP_SHRINK_C
+
+
+BN_MP_TO_UNSIGNED_BIN_N_C
++--->BN_MP_UNSIGNED_BIN_SIZE_C
+|   +--->BN_MP_COUNT_BITS_C
++--->BN_MP_TO_UNSIGNED_BIN_C
+|   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_C
++--->BN_MP_REDUCE_SETUP_C
+|   +--->BN_MP_2EXPT_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2D_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_INIT_COPY_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_TOOM_MUL_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_KARATSUBA_MUL_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_S_MP_MUL_HIGH_DIGS_C
+|   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_2D_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_S_MP_MUL_DIGS_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_D_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_LSHD_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
+|   +--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_MUL_2D_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_GROW_C
++--->BN_MP_LSHD_C
+|   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_ZERO_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_GET_INT_C
+
+
+BN_MP_JACOBI_C
++--->BN_MP_CMP_D_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_CNT_LSB_C
++--->BN_MP_DIV_2D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_MOD_C
+|   +--->BN_MP_DIV_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_SET_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CLEAR_MULTI_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_MUL_C
++--->BN_MP_TOOM_MUL_C
+|   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MUL_2_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_2_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_MUL_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_3_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_KARATSUBA_MUL_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CMP_MAG_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   +--->BN_MP_CLEAR_C
++--->BN_FAST_S_MP_MUL_DIGS_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_S_MP_MUL_DIGS_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_EXTEUCLID_C
++--->BN_MP_INIT_MULTI_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_SET_C
+|   +--->BN_MP_ZERO_C
++--->BN_MP_COPY_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_DIV_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_ABS_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_MUL_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_TOOM_MUL_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_KARATSUBA_MUL_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
++--->BN_MP_NEG_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_DR_REDUCE_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+
+
+BN_MP_FREAD_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_SUB_D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_D_C
+
+
+BN_MP_REDUCE_SETUP_C
++--->BN_MP_2EXPT_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_GROW_C
++--->BN_MP_DIV_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_INIT_MULTI_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_SET_C
+|   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_ABS_C
+|   +--->BN_MP_MUL_2D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CMP_C
+|   +--->BN_MP_SUB_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_ADD_C
+|   |   +--->BN_S_MP_ADD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SUB_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_DIV_2D_C
+|   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_EXCH_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_INIT_SIZE_C
+|   |   +--->BN_MP_INIT_C
+|   +--->BN_MP_INIT_C
+|   +--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_LSHD_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_MUL_D_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
+
+
+BN_MP_MONTGOMERY_SETUP_C
+
+
+BN_MP_KARATSUBA_MUL_C
++--->BN_MP_MUL_C
+|   +--->BN_MP_TOOM_MUL_C
+|   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_MOD_2D_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MUL_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_SUB_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_2_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_2D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MUL_D_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_DIV_3_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_INIT_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_LSHD_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_S_MP_MUL_DIGS_C
+|   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_INIT_C
+|   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SIZE_C
+|   +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+|   +--->BN_S_MP_ADD_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CMP_MAG_C
+|   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_LSHD_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_RSHD_C
+|   |   +--->BN_MP_ZERO_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_LSHD_C
++--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+|   +--->BN_MP_ZERO_C
+
+
+BN_MP_PRIME_MILLER_RABIN_C
++--->BN_MP_CMP_D_C
++--->BN_MP_INIT_COPY_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
++--->BN_MP_SUB_D_C
+|   +--->BN_MP_GROW_C
+|   +--->BN_MP_ADD_D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLAMP_C
++--->BN_MP_CNT_LSB_C
++--->BN_MP_DIV_2D_C
+|   +--->BN_MP_COPY_C
+|   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_ZERO_C
+|   +--->BN_MP_MOD_2D_C
+|   |   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_RSHD_C
+|   +--->BN_MP_CLAMP_C
+|   +--->BN_MP_EXCH_C
++--->BN_MP_EXPTMOD_C
+|   +--->BN_MP_INVMOD_C
+|   |   +--->BN_FAST_MP_INVMOD_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_INVMOD_SLOW_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   |   |   +--->BN_MP_ABS_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_ABS_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   +--->BN_MP_CLEAR_MULTI_C
+|   +--->BN_MP_REDUCE_IS_2K_L_C
+|   +--->BN_S_MP_EXPTMOD_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_REDUCE_SETUP_C
+|   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_REDUCE_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_REDUCE_2K_SETUP_L_C
+|   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_REDUCE_2K_L_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MOD_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_SQR_C
+|   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_MUL_C
+|   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_EXCH_C
+|   +--->BN_MP_DR_IS_MODULUS_C
+|   +--->BN_MP_REDUCE_IS_2K_C
+|   |   +--->BN_MP_REDUCE_2K_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   +--->BN_MP_EXPTMOD_FAST_C
+|   |   +--->BN_MP_COUNT_BITS_C
+|   |   +--->BN_MP_MONTGOMERY_SETUP_C
+|   |   +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_MONTGOMERY_REDUCE_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_DR_SETUP_C
+|   |   +--->BN_MP_DR_REDUCE_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   +--->BN_MP_REDUCE_2K_SETUP_C
+|   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_REDUCE_2K_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+|   |   |   +--->BN_MP_2EXPT_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_MULMOD_C
+|   |   |   +--->BN_MP_MUL_C
+|   |   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_MOD_C
+|   |   |   |   +--->BN_MP_DIV_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   |   +--->BN_MP_SET_C
+|   |   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   +--->BN_MP_MOD_C
+|   |   |   +--->BN_MP_DIV_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_COPY_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   +--->BN_MP_SQR_C
+|   |   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_SQR_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_MUL_C
+|   |   |   +--->BN_MP_TOOM_MUL_C
+|   |   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_KARATSUBA_MUL_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_SUB_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_ADD_C
+|   |   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_FAST_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_S_MP_MUL_DIGS_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   +--->BN_MP_EXCH_C
++--->BN_MP_CMP_C
+|   +--->BN_MP_CMP_MAG_C
++--->BN_MP_SQRMOD_C
+|   +--->BN_MP_SQR_C
+|   |   +--->BN_MP_TOOM_SQR_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_MOD_2D_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   |   +--->BN_MP_COPY_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_MUL_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_2_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_DIV_3_C
+|   |   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_MP_EXCH_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_MP_KARATSUBA_SQR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   |   +--->BN_FAST_S_MP_SQR_C
+|   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_S_MP_SQR_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_CLEAR_C
+|   +--->BN_MP_MOD_C
+|   |   +--->BN_MP_DIV_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_MP_COPY_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   +--->BN_MP_ZERO_C
+|   |   |   +--->BN_MP_INIT_MULTI_C
+|   |   |   +--->BN_MP_SET_C
+|   |   |   +--->BN_MP_COUNT_BITS_C
+|   |   |   +--->BN_MP_ABS_C
+|   |   |   +--->BN_MP_MUL_2D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_SUB_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_ADD_C
+|   |   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_EXCH_C
+|   |   |   +--->BN_MP_CLEAR_MULTI_C
+|   |   |   +--->BN_MP_INIT_SIZE_C
+|   |   |   +--->BN_MP_LSHD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_RSHD_C
+|   |   |   +--->BN_MP_MUL_D_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_ADD_C
+|   |   |   +--->BN_S_MP_ADD_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   |   +--->BN_MP_CMP_MAG_C
+|   |   |   +--->BN_S_MP_SUB_C
+|   |   |   |   +--->BN_MP_GROW_C
+|   |   |   |   +--->BN_MP_CLAMP_C
+|   |   +--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_DR_SETUP_C
+
+
+BN_MP_CMP_MAG_C
+
+
diff --git a/source4/heimdal/lib/hcrypto/libtommath/libtommath.dsp b/source4/heimdal/lib/hcrypto/libtommath/libtommath.dsp
new file mode 100644 (file)
index 0000000..6b8908f
--- /dev/null
@@ -0,0 +1,572 @@
+# Microsoft Developer Studio Project File - Name="libtommath" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=libtommath - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "libtommath.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "libtommath.mak" CFG="libtommath - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "libtommath - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "libtommath - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "libtommath"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "libtommath - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Release\tommath.lib"
+
+!ELSEIF  "$(CFG)" == "libtommath - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Debug\tommath.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "libtommath - Win32 Release"
+# Name "libtommath - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\bn_error.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_fast_mp_invmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_fast_mp_montgomery_reduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_fast_s_mp_mul_digs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_fast_s_mp_mul_high_digs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_fast_s_mp_sqr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_2expt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_abs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_add.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_add_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_addmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_and.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_clamp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_clear.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_clear_multi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_cmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_cmp_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_cmp_mag.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_cnt_lsb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_copy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_count_bits.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_div.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_div_2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_div_2d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_div_3.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_div_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_dr_is_modulus.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_dr_reduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_dr_setup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_exch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_expt_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_exptmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_exptmod_fast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_exteuclid.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_fread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_fwrite.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_gcd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_get_int.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_grow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init_copy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init_multi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init_set.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init_set_int.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init_size.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_invmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_invmod_slow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_is_square.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_jacobi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_karatsuba_mul.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_karatsuba_sqr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_lcm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_lshd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mod_2d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mod_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_montgomery_calc_normalization.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_montgomery_reduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_montgomery_setup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mul.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mul_2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mul_2d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mul_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mulmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_n_root.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_neg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_or.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_fermat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_is_divisible.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_is_prime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_miller_rabin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_next_prime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_rabin_miller_trials.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_random_ex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_radix_size.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_radix_smap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_rand.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_read_radix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_read_signed_bin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_read_unsigned_bin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_2k.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_2k_l.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_2k_setup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_2k_setup_l.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_is_2k.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_is_2k_l.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_setup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_rshd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_set.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_set_int.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_shrink.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_signed_bin_size.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_sqr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_sqrmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_sqrt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_sub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_sub_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_submod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_to_signed_bin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_to_signed_bin_n.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_to_unsigned_bin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_to_unsigned_bin_n.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_toom_mul.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_toom_sqr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_toradix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_toradix_n.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_unsigned_bin_size.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_xor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_zero.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_prime_tab.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_reverse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_add.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_exptmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_mul_digs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_mul_high_digs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_sqr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_sub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bncore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\tommath.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\tommath_class.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\tommath_superclass.h
+# End Source File
+# End Target
+# End Project
diff --git a/source4/heimdal/lib/hcrypto/libtommath/mtest/logtab.h b/source4/heimdal/lib/hcrypto/libtommath/mtest/logtab.h
new file mode 100644 (file)
index 0000000..bbefaef
--- /dev/null
@@ -0,0 +1,24 @@
+const float s_logv_2[] = {
+   0.000000000, 0.000000000, 1.000000000, 0.630929754,         /*  0  1  2  3 */
+   0.500000000, 0.430676558, 0.386852807, 0.356207187,         /*  4  5  6  7 */
+   0.333333333, 0.315464877, 0.301029996, 0.289064826,         /*  8  9 10 11 */
+   0.278942946, 0.270238154, 0.262649535, 0.255958025,         /* 12 13 14 15 */
+   0.250000000, 0.244650542, 0.239812467, 0.235408913,         /* 16 17 18 19 */
+   0.231378213, 0.227670249, 0.224243824, 0.221064729,         /* 20 21 22 23 */
+   0.218104292, 0.215338279, 0.212746054, 0.210309918,         /* 24 25 26 27 */
+   0.208014598, 0.205846832, 0.203795047, 0.201849087,         /* 28 29 30 31 */
+   0.200000000, 0.198239863, 0.196561632, 0.194959022,         /* 32 33 34 35 */
+   0.193426404, 0.191958720, 0.190551412, 0.189200360,         /* 36 37 38 39 */
+   0.187901825, 0.186652411, 0.185449023, 0.184288833,         /* 40 41 42 43 */
+   0.183169251, 0.182087900, 0.181042597, 0.180031327,         /* 44 45 46 47 */
+   0.179052232, 0.178103594, 0.177183820, 0.176291434,         /* 48 49 50 51 */
+   0.175425064, 0.174583430, 0.173765343, 0.172969690,         /* 52 53 54 55 */
+   0.172195434, 0.171441601, 0.170707280, 0.169991616,         /* 56 57 58 59 */
+   0.169293808, 0.168613099, 0.167948779, 0.167300179,         /* 60 61 62 63 */
+   0.166666667
+};
+
+
+/* $Source: /cvs/libtom/libtommath/mtest/logtab.h,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/05/05 14:38:47 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-config.h b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-config.h
new file mode 100644 (file)
index 0000000..6049c25
--- /dev/null
@@ -0,0 +1,90 @@
+/* Default configuration for MPI library */
+/* $Id: mpi-config.h,v 1.2 2005/05/05 14:38:47 tom Exp $ */
+
+#ifndef MPI_CONFIG_H_
+#define MPI_CONFIG_H_
+
+/*
+  For boolean options, 
+  0 = no
+  1 = yes
+
+  Other options are documented individually.
+
+ */
+
+#ifndef MP_IOFUNC
+#define MP_IOFUNC     0  /* include mp_print() ?                */
+#endif
+
+#ifndef MP_MODARITH
+#define MP_MODARITH   1  /* include modular arithmetic ?        */
+#endif
+
+#ifndef MP_NUMTH
+#define MP_NUMTH      1  /* include number theoretic functions? */
+#endif
+
+#ifndef MP_LOGTAB
+#define MP_LOGTAB     1  /* use table of logs instead of log()? */
+#endif
+
+#ifndef MP_MEMSET
+#define MP_MEMSET     1  /* use memset() to zero buffers?       */
+#endif
+
+#ifndef MP_MEMCPY
+#define MP_MEMCPY     1  /* use memcpy() to copy buffers?       */
+#endif
+
+#ifndef MP_CRYPTO
+#define MP_CRYPTO     1  /* erase memory on free?               */
+#endif
+
+#ifndef MP_ARGCHK
+/*
+  0 = no parameter checks
+  1 = runtime checks, continue execution and return an error to caller
+  2 = assertions; dump core on parameter errors
+ */
+#define MP_ARGCHK     2  /* how to check input arguments        */
+#endif
+
+#ifndef MP_DEBUG
+#define MP_DEBUG      0  /* print diagnostic output?            */
+#endif
+
+#ifndef MP_DEFPREC
+#define MP_DEFPREC    64 /* default precision, in digits        */
+#endif
+
+#ifndef MP_MACRO
+#define MP_MACRO      1  /* use macros for frequent calls?      */
+#endif
+
+#ifndef MP_SQUARE
+#define MP_SQUARE     1  /* use separate squaring code?         */
+#endif
+
+#ifndef MP_PTAB_SIZE
+/*
+  When building mpprime.c, we build in a table of small prime
+  values to use for primality testing.  The more you include,
+  the more space they take up.  See primes.c for the possible
+  values (currently 16, 32, 64, 128, 256, and 6542)
+ */
+#define MP_PTAB_SIZE  128  /* how many built-in primes?         */
+#endif
+
+#ifndef MP_COMPAT_MACROS
+#define MP_COMPAT_MACROS 1   /* define compatibility macros?    */
+#endif
+
+#endif /* ifndef MPI_CONFIG_H_ */
+
+
+/* crc==3287762869, version==2, Sat Feb 02 06:43:53 2002 */
+
+/* $Source: /cvs/libtom/libtommath/mtest/mpi-config.h,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/05/05 14:38:47 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-types.h b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-types.h
new file mode 100644 (file)
index 0000000..026de58
--- /dev/null
@@ -0,0 +1,20 @@
+/* Type definitions generated by 'types.pl' */
+typedef char               mp_sign;
+typedef unsigned short     mp_digit;  /* 2 byte type */
+typedef unsigned int       mp_word;   /* 4 byte type */
+typedef unsigned int       mp_size;
+typedef int                mp_err;
+
+#define MP_DIGIT_BIT       (CHAR_BIT*sizeof(mp_digit))
+#define MP_DIGIT_MAX       USHRT_MAX
+#define MP_WORD_BIT        (CHAR_BIT*sizeof(mp_word))
+#define MP_WORD_MAX        UINT_MAX
+
+#define MP_DIGIT_SIZE      2
+#define DIGIT_FMT          "%04X"
+#define RADIX              (MP_DIGIT_MAX+1)
+
+
+/* $Source: /cvs/libtom/libtommath/mtest/mpi-types.h,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/05/05 14:38:47 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.c b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.c
new file mode 100644 (file)
index 0000000..7c712dd
--- /dev/null
@@ -0,0 +1,3985 @@
+/*
+    mpi.c
+
+    by Michael J. Fromberger <sting@linguist.dartmouth.edu>
+    Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
+
+    Arbitrary precision integer arithmetic library
+
+    $Id: mpi.c,v 1.2 2005/05/05 14:38:47 tom Exp $
+ */
+
+#include "mpi.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#if MP_DEBUG
+#include <stdio.h>
+
+#define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);}
+#else
+#define DIAG(T,V)
+#endif
+
+/* 
+   If MP_LOGTAB is not defined, use the math library to compute the
+   logarithms on the fly.  Otherwise, use the static table below.
+   Pick which works best for your system.
+ */
+#if MP_LOGTAB
+
+/* {{{ s_logv_2[] - log table for 2 in various bases */
+
+/*
+  A table of the logs of 2 for various bases (the 0 and 1 entries of
+  this table are meaningless and should not be referenced).  
+
+  This table is used to compute output lengths for the mp_toradix()
+  function.  Since a number n in radix r takes up about log_r(n)
+  digits, we estimate the output size by taking the least integer
+  greater than log_r(n), where:
+
+  log_r(n) = log_2(n) * log_r(2)
+
+  This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
+  which are the output bases supported.  
+ */
+
+#include "logtab.h"
+
+/* }}} */
+#define LOG_V_2(R)  s_logv_2[(R)]
+
+#else
+
+#include <math.h>
+#define LOG_V_2(R)  (log(2.0)/log(R))
+
+#endif
+
+/* Default precision for newly created mp_int's      */
+static unsigned int s_mp_defprec = MP_DEFPREC;
+
+/* {{{ Digit arithmetic macros */
+
+/*
+  When adding and multiplying digits, the results can be larger than
+  can be contained in an mp_digit.  Thus, an mp_word is used.  These
+  macros mask off the upper and lower digits of the mp_word (the
+  mp_word may be more than 2 mp_digits wide, but we only concern
+  ourselves with the low-order 2 mp_digits)
+
+  If your mp_word DOES have more than 2 mp_digits, you need to
+  uncomment the first line, and comment out the second.
+ */
+
+/* #define  CARRYOUT(W)  (((W)>>DIGIT_BIT)&MP_DIGIT_MAX) */
+#define  CARRYOUT(W)  ((W)>>DIGIT_BIT)
+#define  ACCUM(W)     ((W)&MP_DIGIT_MAX)
+
+/* }}} */
+
+/* {{{ Comparison constants */
+
+#define  MP_LT       -1
+#define  MP_EQ        0
+#define  MP_GT        1
+
+/* }}} */
+
+/* {{{ Constant strings */
+
+/* Constant strings returned by mp_strerror() */
+static const char *mp_err_string[] = {
+  "unknown result code",     /* say what?            */
+  "boolean true",            /* MP_OKAY, MP_YES      */
+  "boolean false",           /* MP_NO                */
+  "out of memory",           /* MP_MEM               */
+  "argument out of range",   /* MP_RANGE             */
+  "invalid input parameter", /* MP_BADARG            */
+  "result is undefined"      /* MP_UNDEF             */
+};
+
+/* Value to digit maps for radix conversion   */
+
+/* s_dmap_1 - standard digits and letters */
+static const char *s_dmap_1 = 
+  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
+#if 0
+/* s_dmap_2 - base64 ordering for digits  */
+static const char *s_dmap_2 =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#endif
+
+/* }}} */
+
+/* {{{ Static function declarations */
+
+/* 
+   If MP_MACRO is false, these will be defined as actual functions;
+   otherwise, suitable macro definitions will be used.  This works
+   around the fact that ANSI C89 doesn't support an 'inline' keyword
+   (although I hear C9x will ... about bloody time).  At present, the
+   macro definitions are identical to the function bodies, but they'll
+   expand in place, instead of generating a function call.
+
+   I chose these particular functions to be made into macros because
+   some profiling showed they are called a lot on a typical workload,
+   and yet they are primarily housekeeping.
+ */
+#if MP_MACRO == 0
+ void     s_mp_setz(mp_digit *dp, mp_size count); /* zero digits           */
+ void     s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count); /* copy    */
+ void    *s_mp_alloc(size_t nb, size_t ni);       /* general allocator     */
+ void     s_mp_free(void *ptr);                   /* general free function */
+#else
+
+ /* Even if these are defined as macros, we need to respect the settings
+    of the MP_MEMSET and MP_MEMCPY configuration options...
+  */
+ #if MP_MEMSET == 0
+  #define  s_mp_setz(dp, count) \
+       {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;}
+ #else
+  #define  s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit))
+ #endif /* MP_MEMSET */
+
+ #if MP_MEMCPY == 0
+  #define  s_mp_copy(sp, dp, count) \
+       {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];}
+ #else
+  #define  s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit))
+ #endif /* MP_MEMCPY */
+
+ #define  s_mp_alloc(nb, ni)  calloc(nb, ni)
+ #define  s_mp_free(ptr) {if(ptr) free(ptr);}
+#endif /* MP_MACRO */
+
+mp_err   s_mp_grow(mp_int *mp, mp_size min);   /* increase allocated size */
+mp_err   s_mp_pad(mp_int *mp, mp_size min);    /* left pad with zeroes    */
+
+void     s_mp_clamp(mp_int *mp);               /* clip leading zeroes     */
+
+void     s_mp_exch(mp_int *a, mp_int *b);      /* swap a and b in place   */
+
+mp_err   s_mp_lshd(mp_int *mp, mp_size p);     /* left-shift by p digits  */
+void     s_mp_rshd(mp_int *mp, mp_size p);     /* right-shift by p digits */
+void     s_mp_div_2d(mp_int *mp, mp_digit d);  /* divide by 2^d in place  */
+void     s_mp_mod_2d(mp_int *mp, mp_digit d);  /* modulo 2^d in place     */
+mp_err   s_mp_mul_2d(mp_int *mp, mp_digit d);  /* multiply by 2^d in place*/
+void     s_mp_div_2(mp_int *mp);               /* divide by 2 in place    */
+mp_err   s_mp_mul_2(mp_int *mp);               /* multiply by 2 in place  */
+mp_digit s_mp_norm(mp_int *a, mp_int *b);      /* normalize for division  */
+mp_err   s_mp_add_d(mp_int *mp, mp_digit d);   /* unsigned digit addition */
+mp_err   s_mp_sub_d(mp_int *mp, mp_digit d);   /* unsigned digit subtract */
+mp_err   s_mp_mul_d(mp_int *mp, mp_digit d);   /* unsigned digit multiply */
+mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r);
+                                              /* unsigned digit divide   */
+mp_err   s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu);
+                                               /* Barrett reduction       */
+mp_err   s_mp_add(mp_int *a, mp_int *b);       /* magnitude addition      */
+mp_err   s_mp_sub(mp_int *a, mp_int *b);       /* magnitude subtract      */
+mp_err   s_mp_mul(mp_int *a, mp_int *b);       /* magnitude multiply      */
+#if 0
+void     s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len);
+                                               /* multiply buffers in place */
+#endif
+#if MP_SQUARE
+mp_err   s_mp_sqr(mp_int *a);                  /* magnitude square        */
+#else
+#define  s_mp_sqr(a) s_mp_mul(a, a)
+#endif
+mp_err   s_mp_div(mp_int *a, mp_int *b);       /* magnitude divide        */
+mp_err   s_mp_2expt(mp_int *a, mp_digit k);    /* a = 2^k                 */
+int      s_mp_cmp(mp_int *a, mp_int *b);       /* magnitude comparison    */
+int      s_mp_cmp_d(mp_int *a, mp_digit d);    /* magnitude digit compare */
+int      s_mp_ispow2(mp_int *v);               /* is v a power of 2?      */
+int      s_mp_ispow2d(mp_digit d);             /* is d a power of 2?      */
+
+int      s_mp_tovalue(char ch, int r);          /* convert ch to value    */
+char     s_mp_todigit(int val, int r, int low); /* convert val to digit   */
+int      s_mp_outlen(int bits, int r);          /* output length in bytes */
+
+/* }}} */
+
+/* {{{ Default precision manipulation */
+
+unsigned int mp_get_prec(void)
+{
+  return s_mp_defprec;
+
+} /* end mp_get_prec() */
+
+void         mp_set_prec(unsigned int prec)
+{
+  if(prec == 0)
+    s_mp_defprec = MP_DEFPREC;
+  else
+    s_mp_defprec = prec;
+
+} /* end mp_set_prec() */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ mp_init(mp) */
+
+/*
+  mp_init(mp)
+
+  Initialize a new zero-valued mp_int.  Returns MP_OKAY if successful,
+  MP_MEM if memory could not be allocated for the structure.
+ */
+
+mp_err mp_init(mp_int *mp)
+{
+  return mp_init_size(mp, s_mp_defprec);
+
+} /* end mp_init() */
+
+/* }}} */
+
+/* {{{ mp_init_array(mp[], count) */
+
+mp_err mp_init_array(mp_int mp[], int count)
+{
+  mp_err  res;
+  int     pos;
+
+  ARGCHK(mp !=NULL && count > 0, MP_BADARG);
+
+  for(pos = 0; pos < count; ++pos) {
+    if((res = mp_init(&mp[pos])) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  return MP_OKAY;
+
+ CLEANUP:
+  while(--pos >= 0) 
+    mp_clear(&mp[pos]);
+
+  return res;
+
+} /* end mp_init_array() */
+
+/* }}} */
+
+/* {{{ mp_init_size(mp, prec) */
+
+/*
+  mp_init_size(mp, prec)
+
+  Initialize a new zero-valued mp_int with at least the given
+  precision; returns MP_OKAY if successful, or MP_MEM if memory could
+  not be allocated for the structure.
+ */
+
+mp_err mp_init_size(mp_int *mp, mp_size prec)
+{
+  ARGCHK(mp != NULL && prec > 0, MP_BADARG);
+
+  if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit))) == NULL)
+    return MP_MEM;
+
+  SIGN(mp) = MP_ZPOS;
+  USED(mp) = 1;
+  ALLOC(mp) = prec;
+
+  return MP_OKAY;
+
+} /* end mp_init_size() */
+
+/* }}} */
+
+/* {{{ mp_init_copy(mp, from) */
+
+/*
+  mp_init_copy(mp, from)
+
+  Initialize mp as an exact copy of from.  Returns MP_OKAY if
+  successful, MP_MEM if memory could not be allocated for the new
+  structure.
+ */
+
+mp_err mp_init_copy(mp_int *mp, mp_int *from)
+{
+  ARGCHK(mp != NULL && from != NULL, MP_BADARG);
+
+  if(mp == from)
+    return MP_OKAY;
+
+  if((DIGITS(mp) = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL)
+    return MP_MEM;
+
+  s_mp_copy(DIGITS(from), DIGITS(mp), USED(from));
+  USED(mp) = USED(from);
+  ALLOC(mp) = USED(from);
+  SIGN(mp) = SIGN(from);
+
+  return MP_OKAY;
+
+} /* end mp_init_copy() */
+
+/* }}} */
+
+/* {{{ mp_copy(from, to) */
+
+/*
+  mp_copy(from, to)
+
+  Copies the mp_int 'from' to the mp_int 'to'.  It is presumed that
+  'to' has already been initialized (if not, use mp_init_copy()
+  instead). If 'from' and 'to' are identical, nothing happens.
+ */
+
+mp_err mp_copy(mp_int *from, mp_int *to)
+{
+  ARGCHK(from != NULL && to != NULL, MP_BADARG);
+
+  if(from == to)
+    return MP_OKAY;
+
+  { /* copy */
+    mp_digit   *tmp;
+
+    /*
+      If the allocated buffer in 'to' already has enough space to hold
+      all the used digits of 'from', we'll re-use it to avoid hitting
+      the memory allocater more than necessary; otherwise, we'd have
+      to grow anyway, so we just allocate a hunk and make the copy as
+      usual
+     */
+    if(ALLOC(to) >= USED(from)) {
+      s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from));
+      s_mp_copy(DIGITS(from), DIGITS(to), USED(from));
+      
+    } else {
+      if((tmp = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL)
+       return MP_MEM;
+
+      s_mp_copy(DIGITS(from), tmp, USED(from));
+
+      if(DIGITS(to) != NULL) {
+#if MP_CRYPTO
+       s_mp_setz(DIGITS(to), ALLOC(to));
+#endif
+       s_mp_free(DIGITS(to));
+      }
+
+      DIGITS(to) = tmp;
+      ALLOC(to) = USED(from);
+    }
+
+    /* Copy the precision and sign from the original */
+    USED(to) = USED(from);
+    SIGN(to) = SIGN(from);
+  } /* end copy */
+
+  return MP_OKAY;
+
+} /* end mp_copy() */
+
+/* }}} */
+
+/* {{{ mp_exch(mp1, mp2) */
+
+/*
+  mp_exch(mp1, mp2)
+
+  Exchange mp1 and mp2 without allocating any intermediate memory
+  (well, unless you count the stack space needed for this call and the
+  locals it creates...).  This cannot fail.
+ */
+
+void mp_exch(mp_int *mp1, mp_int *mp2)
+{
+#if MP_ARGCHK == 2
+  assert(mp1 != NULL && mp2 != NULL);
+#else
+  if(mp1 == NULL || mp2 == NULL)
+    return;
+#endif
+
+  s_mp_exch(mp1, mp2);
+
+} /* end mp_exch() */
+
+/* }}} */
+
+/* {{{ mp_clear(mp) */
+
+/*
+  mp_clear(mp)
+
+  Release the storage used by an mp_int, and void its fields so that
+  if someone calls mp_clear() again for the same int later, we won't
+  get tollchocked.
+ */
+
+void   mp_clear(mp_int *mp)
+{
+  if(mp == NULL)
+    return;
+
+  if(DIGITS(mp) != NULL) {
+#if MP_CRYPTO
+    s_mp_setz(DIGITS(mp), ALLOC(mp));
+#endif
+    s_mp_free(DIGITS(mp));
+    DIGITS(mp) = NULL;
+  }
+
+  USED(mp) = 0;
+  ALLOC(mp) = 0;
+
+} /* end mp_clear() */
+
+/* }}} */
+
+/* {{{ mp_clear_array(mp[], count) */
+
+void   mp_clear_array(mp_int mp[], int count)
+{
+  ARGCHK(mp != NULL && count > 0, MP_BADARG);
+
+  while(--count >= 0) 
+    mp_clear(&mp[count]);
+
+} /* end mp_clear_array() */
+
+/* }}} */
+
+/* {{{ mp_zero(mp) */
+
+/*
+  mp_zero(mp) 
+
+  Set mp to zero.  Does not change the allocated size of the structure,
+  and therefore cannot fail (except on a bad argument, which we ignore)
+ */
+void   mp_zero(mp_int *mp)
+{
+  if(mp == NULL)
+    return;
+
+  s_mp_setz(DIGITS(mp), ALLOC(mp));
+  USED(mp) = 1;
+  SIGN(mp) = MP_ZPOS;
+
+} /* end mp_zero() */
+
+/* }}} */
+
+/* {{{ mp_set(mp, d) */
+
+void   mp_set(mp_int *mp, mp_digit d)
+{
+  if(mp == NULL)
+    return;
+
+  mp_zero(mp);
+  DIGIT(mp, 0) = d;
+
+} /* end mp_set() */
+
+/* }}} */
+
+/* {{{ mp_set_int(mp, z) */
+
+mp_err mp_set_int(mp_int *mp, long z)
+{
+  int            ix;
+  unsigned long  v = abs(z);
+  mp_err         res;
+
+  ARGCHK(mp != NULL, MP_BADARG);
+
+  mp_zero(mp);
+  if(z == 0)
+    return MP_OKAY;  /* shortcut for zero */
+
+  for(ix = sizeof(long) - 1; ix >= 0; ix--) {
+
+    if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY)
+      return res;
+
+    res = s_mp_add_d(mp, 
+                    (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
+    if(res != MP_OKAY)
+      return res;
+
+  }
+
+  if(z < 0)
+    SIGN(mp) = MP_NEG;
+
+  return MP_OKAY;
+
+} /* end mp_set_int() */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Digit arithmetic */
+
+/* {{{ mp_add_d(a, d, b) */
+
+/*
+  mp_add_d(a, d, b)
+
+  Compute the sum b = a + d, for a single digit d.  Respects the sign of
+  its primary addend (single digits are unsigned anyway).
+ */
+
+mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b)
+{
+  mp_err   res = MP_OKAY;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  if(SIGN(b) == MP_ZPOS) {
+    res = s_mp_add_d(b, d);
+  } else if(s_mp_cmp_d(b, d) >= 0) {
+    res = s_mp_sub_d(b, d);
+  } else {
+    SIGN(b) = MP_ZPOS;
+
+    DIGIT(b, 0) = d - DIGIT(b, 0);
+  }
+
+  return res;
+
+} /* end mp_add_d() */
+
+/* }}} */
+
+/* {{{ mp_sub_d(a, d, b) */
+
+/*
+  mp_sub_d(a, d, b)
+
+  Compute the difference b = a - d, for a single digit d.  Respects the
+  sign of its subtrahend (single digits are unsigned anyway).
+ */
+
+mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b)
+{
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  if(SIGN(b) == MP_NEG) {
+    if((res = s_mp_add_d(b, d)) != MP_OKAY)
+      return res;
+
+  } else if(s_mp_cmp_d(b, d) >= 0) {
+    if((res = s_mp_sub_d(b, d)) != MP_OKAY)
+      return res;
+
+  } else {
+    mp_neg(b, b);
+
+    DIGIT(b, 0) = d - DIGIT(b, 0);
+    SIGN(b) = MP_NEG;
+  }
+
+  if(s_mp_cmp_d(b, 0) == 0)
+    SIGN(b) = MP_ZPOS;
+
+  return MP_OKAY;
+
+} /* end mp_sub_d() */
+
+/* }}} */
+
+/* {{{ mp_mul_d(a, d, b) */
+
+/*
+  mp_mul_d(a, d, b)
+
+  Compute the product b = a * d, for a single digit d.  Respects the sign
+  of its multiplicand (single digits are unsigned anyway)
+ */
+
+mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if(d == 0) {
+    mp_zero(b);
+    return MP_OKAY;
+  }
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  res = s_mp_mul_d(b, d);
+
+  return res;
+
+} /* end mp_mul_d() */
+
+/* }}} */
+
+/* {{{ mp_mul_2(a, c) */
+
+mp_err mp_mul_2(mp_int *a, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, c)) != MP_OKAY)
+    return res;
+
+  return s_mp_mul_2(c);
+
+} /* end mp_mul_2() */
+
+/* }}} */
+
+/* {{{ mp_div_d(a, d, q, r) */
+
+/*
+  mp_div_d(a, d, q, r)
+
+  Compute the quotient q = a / d and remainder r = a mod d, for a
+  single digit d.  Respects the sign of its divisor (single digits are
+  unsigned anyway).
+ */
+
+mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r)
+{
+  mp_err   res;
+  mp_digit rem;
+  int      pow;
+
+  ARGCHK(a != NULL, MP_BADARG);
+
+  if(d == 0)
+    return MP_RANGE;
+
+  /* Shortcut for powers of two ... */
+  if((pow = s_mp_ispow2d(d)) >= 0) {
+    mp_digit  mask;
+
+    mask = (1 << pow) - 1;
+    rem = DIGIT(a, 0) & mask;
+
+    if(q) {
+      mp_copy(a, q);
+      s_mp_div_2d(q, pow);
+    }
+
+    if(r)
+      *r = rem;
+
+    return MP_OKAY;
+  }
+
+  /*
+    If the quotient is actually going to be returned, we'll try to
+    avoid hitting the memory allocator by copying the dividend into it
+    and doing the division there.  This can't be any _worse_ than
+    always copying, and will sometimes be better (since it won't make
+    another copy)
+
+    If it's not going to be returned, we need to allocate a temporary
+    to hold the quotient, which will just be discarded.
+   */
+  if(q) {
+    if((res = mp_copy(a, q)) != MP_OKAY)
+      return res;
+
+    res = s_mp_div_d(q, d, &rem);
+    if(s_mp_cmp_d(q, 0) == MP_EQ)
+      SIGN(q) = MP_ZPOS;
+
+  } else {
+    mp_int  qp;
+
+    if((res = mp_init_copy(&qp, a)) != MP_OKAY)
+      return res;
+
+    res = s_mp_div_d(&qp, d, &rem);
+    if(s_mp_cmp_d(&qp, 0) == 0)
+      SIGN(&qp) = MP_ZPOS;
+
+    mp_clear(&qp);
+  }
+
+  if(r)
+    *r = rem;
+
+  return res;
+
+} /* end mp_div_d() */
+
+/* }}} */
+
+/* {{{ mp_div_2(a, c) */
+
+/*
+  mp_div_2(a, c)
+
+  Compute c = a / 2, disregarding the remainder.
+ */
+
+mp_err mp_div_2(mp_int *a, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, c)) != MP_OKAY)
+    return res;
+
+  s_mp_div_2(c);
+
+  return MP_OKAY;
+
+} /* end mp_div_2() */
+
+/* }}} */
+
+/* {{{ mp_expt_d(a, d, b) */
+
+mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c)
+{
+  mp_int   s, x;
+  mp_err   res;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_init(&s)) != MP_OKAY)
+    return res;
+  if((res = mp_init_copy(&x, a)) != MP_OKAY)
+    goto X;
+
+  DIGIT(&s, 0) = 1;
+
+  while(d != 0) {
+    if(d & 1) {
+      if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+       goto CLEANUP;
+    }
+
+    d >>= 1;
+
+    if((res = s_mp_sqr(&x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  s_mp_exch(&s, c);
+
+CLEANUP:
+  mp_clear(&x);
+X:
+  mp_clear(&s);
+
+  return res;
+
+} /* end mp_expt_d() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Full arithmetic */
+
+/* {{{ mp_abs(a, b) */
+
+/*
+  mp_abs(a, b)
+
+  Compute b = |a|.  'a' and 'b' may be identical.
+ */
+
+mp_err mp_abs(mp_int *a, mp_int *b)
+{
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  SIGN(b) = MP_ZPOS;
+
+  return MP_OKAY;
+
+} /* end mp_abs() */
+
+/* }}} */
+
+/* {{{ mp_neg(a, b) */
+
+/*
+  mp_neg(a, b)
+
+  Compute b = -a.  'a' and 'b' may be identical.
+ */
+
+mp_err mp_neg(mp_int *a, mp_int *b)
+{
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  if(s_mp_cmp_d(b, 0) == MP_EQ) 
+    SIGN(b) = MP_ZPOS;
+  else 
+    SIGN(b) = (SIGN(b) == MP_NEG) ? MP_ZPOS : MP_NEG;
+
+  return MP_OKAY;
+
+} /* end mp_neg() */
+
+/* }}} */
+
+/* {{{ mp_add(a, b, c) */
+
+/*
+  mp_add(a, b, c)
+
+  Compute c = a + b.  All parameters may be identical.
+ */
+
+mp_err mp_add(mp_int *a, mp_int *b, mp_int *c)
+{
+  mp_err  res;
+  int     cmp;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if(SIGN(a) == SIGN(b)) { /* same sign:  add values, keep sign */
+
+    /* Commutativity of addition lets us do this in either order,
+       so we avoid having to use a temporary even if the result 
+       is supposed to replace the output
+     */
+    if(c == b) {
+      if((res = s_mp_add(c, a)) != MP_OKAY)
+       return res;
+    } else {
+      if(c != a && (res = mp_copy(a, c)) != MP_OKAY)
+       return res;
+
+      if((res = s_mp_add(c, b)) != MP_OKAY) 
+       return res;
+    }
+
+  } else if((cmp = s_mp_cmp(a, b)) > 0) {  /* different sign: a > b   */
+
+    /* If the output is going to be clobbered, we will use a temporary
+       variable; otherwise, we'll do it without touching the memory 
+       allocator at all, if possible
+     */
+    if(c == b) {
+      mp_int  tmp;
+
+      if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
+       return res;
+      if((res = s_mp_sub(&tmp, b)) != MP_OKAY) {
+       mp_clear(&tmp);
+       return res;
+      }
+
+      s_mp_exch(&tmp, c);
+      mp_clear(&tmp);
+
+    } else {
+
+      if(c != a && (res = mp_copy(a, c)) != MP_OKAY)
+       return res;
+      if((res = s_mp_sub(c, b)) != MP_OKAY)
+       return res;
+
+    }
+
+  } else if(cmp == 0) {             /* different sign, a == b   */
+
+    mp_zero(c);
+    return MP_OKAY;
+
+  } else {                          /* different sign: a < b    */
+
+    /* See above... */
+    if(c == a) {
+      mp_int  tmp;
+
+      if((res = mp_init_copy(&tmp, b)) != MP_OKAY)
+       return res;
+      if((res = s_mp_sub(&tmp, a)) != MP_OKAY) {
+       mp_clear(&tmp);
+       return res;
+      }
+
+      s_mp_exch(&tmp, c);
+      mp_clear(&tmp);
+
+    } else {
+
+      if(c != b && (res = mp_copy(b, c)) != MP_OKAY)
+       return res;
+      if((res = s_mp_sub(c, a)) != MP_OKAY)
+       return res;
+
+    }
+  }
+
+  if(USED(c) == 1 && DIGIT(c, 0) == 0)
+    SIGN(c) = MP_ZPOS;
+
+  return MP_OKAY;
+
+} /* end mp_add() */
+
+/* }}} */
+
+/* {{{ mp_sub(a, b, c) */
+
+/*
+  mp_sub(a, b, c)
+
+  Compute c = a - b.  All parameters may be identical.
+ */
+
+mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c)
+{
+  mp_err  res;
+  int     cmp;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if(SIGN(a) != SIGN(b)) {
+    if(c == a) {
+      if((res = s_mp_add(c, b)) != MP_OKAY)
+       return res;
+    } else {
+      if(c != b && ((res = mp_copy(b, c)) != MP_OKAY))
+       return res;
+      if((res = s_mp_add(c, a)) != MP_OKAY)
+       return res;
+      SIGN(c) = SIGN(a);
+    }
+
+  } else if((cmp = s_mp_cmp(a, b)) > 0) { /* Same sign, a > b */
+    if(c == b) {
+      mp_int  tmp;
+
+      if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
+       return res;
+      if((res = s_mp_sub(&tmp, b)) != MP_OKAY) {
+       mp_clear(&tmp);
+       return res;
+      }
+      s_mp_exch(&tmp, c);
+      mp_clear(&tmp);
+
+    } else {
+      if(c != a && ((res = mp_copy(a, c)) != MP_OKAY))
+       return res;
+
+      if((res = s_mp_sub(c, b)) != MP_OKAY)
+       return res;
+    }
+
+  } else if(cmp == 0) {  /* Same sign, equal magnitude */
+    mp_zero(c);
+    return MP_OKAY;
+
+  } else {               /* Same sign, b > a */
+    if(c == a) {
+      mp_int  tmp;
+
+      if((res = mp_init_copy(&tmp, b)) != MP_OKAY)
+       return res;
+
+      if((res = s_mp_sub(&tmp, a)) != MP_OKAY) {
+       mp_clear(&tmp);
+       return res;
+      }
+      s_mp_exch(&tmp, c);
+      mp_clear(&tmp);
+
+    } else {
+      if(c != b && ((res = mp_copy(b, c)) != MP_OKAY)) 
+       return res;
+
+      if((res = s_mp_sub(c, a)) != MP_OKAY)
+       return res;
+    }
+
+    SIGN(c) = !SIGN(b);
+  }
+
+  if(USED(c) == 1 && DIGIT(c, 0) == 0)
+    SIGN(c) = MP_ZPOS;
+
+  return MP_OKAY;
+
+} /* end mp_sub() */
+
+/* }}} */
+
+/* {{{ mp_mul(a, b, c) */
+
+/*
+  mp_mul(a, b, c)
+
+  Compute c = a * b.  All parameters may be identical.
+ */
+
+mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c)
+{
+  mp_err   res;
+  mp_sign  sgn;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  sgn = (SIGN(a) == SIGN(b)) ? MP_ZPOS : MP_NEG;
+
+  if(c == b) {
+    if((res = s_mp_mul(c, a)) != MP_OKAY)
+      return res;
+
+  } else {
+    if((res = mp_copy(a, c)) != MP_OKAY)
+      return res;
+
+    if((res = s_mp_mul(c, b)) != MP_OKAY)
+      return res;
+  }
+  
+  if(sgn == MP_ZPOS || s_mp_cmp_d(c, 0) == MP_EQ)
+    SIGN(c) = MP_ZPOS;
+  else
+    SIGN(c) = sgn;
+  
+  return MP_OKAY;
+
+} /* end mp_mul() */
+
+/* }}} */
+
+/* {{{ mp_mul_2d(a, d, c) */
+
+/*
+  mp_mul_2d(a, d, c)
+
+  Compute c = a * 2^d.  a may be the same as c.
+ */
+
+mp_err mp_mul_2d(mp_int *a, mp_digit d, mp_int *c)
+{
+  mp_err   res;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, c)) != MP_OKAY)
+    return res;
+
+  if(d == 0)
+    return MP_OKAY;
+
+  return s_mp_mul_2d(c, d);
+
+} /* end mp_mul() */
+
+/* }}} */
+
+/* {{{ mp_sqr(a, b) */
+
+#if MP_SQUARE
+mp_err mp_sqr(mp_int *a, mp_int *b)
+{
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  if((res = s_mp_sqr(b)) != MP_OKAY)
+    return res;
+
+  SIGN(b) = MP_ZPOS;
+
+  return MP_OKAY;
+
+} /* end mp_sqr() */
+#endif
+
+/* }}} */
+
+/* {{{ mp_div(a, b, q, r) */
+
+/*
+  mp_div(a, b, q, r)
+
+  Compute q = a / b and r = a mod b.  Input parameters may be re-used
+  as output parameters.  If q or r is NULL, that portion of the
+  computation will be discarded (although it will still be computed)
+
+  Pay no attention to the hacker behind the curtain.
+ */
+
+mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r)
+{
+  mp_err   res;
+  mp_int   qtmp, rtmp;
+  int      cmp;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if(mp_cmp_z(b) == MP_EQ)
+    return MP_RANGE;
+
+  /* If a <= b, we can compute the solution without division, and
+     avoid any memory allocation
+   */
+  if((cmp = s_mp_cmp(a, b)) < 0) {
+    if(r) {
+      if((res = mp_copy(a, r)) != MP_OKAY)
+       return res;
+    }
+
+    if(q) 
+      mp_zero(q);
+
+    return MP_OKAY;
+
+  } else if(cmp == 0) {
+
+    /* Set quotient to 1, with appropriate sign */
+    if(q) {
+      int qneg = (SIGN(a) != SIGN(b));
+
+      mp_set(q, 1);
+      if(qneg)
+       SIGN(q) = MP_NEG;
+    }
+
+    if(r)
+      mp_zero(r);
+
+    return MP_OKAY;
+  }
+
+  /* If we get here, it means we actually have to do some division */
+
+  /* Set up some temporaries... */
+  if((res = mp_init_copy(&qtmp, a)) != MP_OKAY)
+    return res;
+  if((res = mp_init_copy(&rtmp, b)) != MP_OKAY)
+    goto CLEANUP;
+
+  if((res = s_mp_div(&qtmp, &rtmp)) != MP_OKAY)
+    goto CLEANUP;
+
+  /* Compute the signs for the output  */
+  SIGN(&rtmp) = SIGN(a); /* Sr = Sa              */
+  if(SIGN(a) == SIGN(b))
+    SIGN(&qtmp) = MP_ZPOS;  /* Sq = MP_ZPOS if Sa = Sb */
+  else
+    SIGN(&qtmp) = MP_NEG;   /* Sq = MP_NEG if Sa != Sb */
+
+  if(s_mp_cmp_d(&qtmp, 0) == MP_EQ)
+    SIGN(&qtmp) = MP_ZPOS;
+  if(s_mp_cmp_d(&rtmp, 0) == MP_EQ)
+    SIGN(&rtmp) = MP_ZPOS;
+
+  /* Copy output, if it is needed      */
+  if(q) 
+    s_mp_exch(&qtmp, q);
+
+  if(r) 
+    s_mp_exch(&rtmp, r);
+
+CLEANUP:
+  mp_clear(&rtmp);
+  mp_clear(&qtmp);
+
+  return res;
+
+} /* end mp_div() */
+
+/* }}} */
+
+/* {{{ mp_div_2d(a, d, q, r) */
+
+mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL, MP_BADARG);
+
+  if(q) {
+    if((res = mp_copy(a, q)) != MP_OKAY)
+      return res;
+
+    s_mp_div_2d(q, d);
+  }
+
+  if(r) {
+    if((res = mp_copy(a, r)) != MP_OKAY)
+      return res;
+
+    s_mp_mod_2d(r, d);
+  }
+
+  return MP_OKAY;
+
+} /* end mp_div_2d() */
+
+/* }}} */
+
+/* {{{ mp_expt(a, b, c) */
+
+/*
+  mp_expt(a, b, c)
+
+  Compute c = a ** b, that is, raise a to the b power.  Uses a
+  standard iterative square-and-multiply technique.
+ */
+
+mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c)
+{
+  mp_int   s, x;
+  mp_err   res;
+  mp_digit d;
+  int      dig, bit;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if(mp_cmp_z(b) < 0)
+    return MP_RANGE;
+
+  if((res = mp_init(&s)) != MP_OKAY)
+    return res;
+
+  mp_set(&s, 1);
+
+  if((res = mp_init_copy(&x, a)) != MP_OKAY)
+    goto X;
+
+  /* Loop over low-order digits in ascending order */
+  for(dig = 0; dig < (USED(b) - 1); dig++) {
+    d = DIGIT(b, dig);
+
+    /* Loop over bits of each non-maximal digit */
+    for(bit = 0; bit < DIGIT_BIT; bit++) {
+      if(d & 1) {
+       if((res = s_mp_mul(&s, &x)) != MP_OKAY) 
+         goto CLEANUP;
+      }
+
+      d >>= 1;
+      
+      if((res = s_mp_sqr(&x)) != MP_OKAY)
+       goto CLEANUP;
+    }
+  }
+
+  /* Consider now the last digit... */
+  d = DIGIT(b, dig);
+
+  while(d) {
+    if(d & 1) {
+      if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+       goto CLEANUP;
+    }
+
+    d >>= 1;
+
+    if((res = s_mp_sqr(&x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+  
+  if(mp_iseven(b))
+    SIGN(&s) = SIGN(a);
+
+  res = mp_copy(&s, c);
+
+CLEANUP:
+  mp_clear(&x);
+X:
+  mp_clear(&s);
+
+  return res;
+
+} /* end mp_expt() */
+
+/* }}} */
+
+/* {{{ mp_2expt(a, k) */
+
+/* Compute a = 2^k */
+
+mp_err mp_2expt(mp_int *a, mp_digit k)
+{
+  ARGCHK(a != NULL, MP_BADARG);
+
+  return s_mp_2expt(a, k);
+
+} /* end mp_2expt() */
+
+/* }}} */
+
+/* {{{ mp_mod(a, m, c) */
+
+/*
+  mp_mod(a, m, c)
+
+  Compute c = a (mod m).  Result will always be 0 <= c < m.
+ */
+
+mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c)
+{
+  mp_err  res;
+  int     mag;
+
+  ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
+
+  if(SIGN(m) == MP_NEG)
+    return MP_RANGE;
+
+  /*
+     If |a| > m, we need to divide to get the remainder and take the
+     absolute value.  
+
+     If |a| < m, we don't need to do any division, just copy and adjust
+     the sign (if a is negative).
+
+     If |a| == m, we can simply set the result to zero.
+
+     This order is intended to minimize the average path length of the
+     comparison chain on common workloads -- the most frequent cases are
+     that |a| != m, so we do those first.
+   */
+  if((mag = s_mp_cmp(a, m)) > 0) {
+    if((res = mp_div(a, m, NULL, c)) != MP_OKAY)
+      return res;
+    
+    if(SIGN(c) == MP_NEG) {
+      if((res = mp_add(c, m, c)) != MP_OKAY)
+       return res;
+    }
+
+  } else if(mag < 0) {
+    if((res = mp_copy(a, c)) != MP_OKAY)
+      return res;
+
+    if(mp_cmp_z(a) < 0) {
+      if((res = mp_add(c, m, c)) != MP_OKAY)
+       return res;
+
+    }
+    
+  } else {
+    mp_zero(c);
+
+  }
+
+  return MP_OKAY;
+
+} /* end mp_mod() */
+
+/* }}} */
+
+/* {{{ mp_mod_d(a, d, c) */
+
+/*
+  mp_mod_d(a, d, c)
+
+  Compute c = a (mod d).  Result will always be 0 <= c < d
+ */
+mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c)
+{
+  mp_err   res;
+  mp_digit rem;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if(s_mp_cmp_d(a, d) > 0) {
+    if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY)
+      return res;
+
+  } else {
+    if(SIGN(a) == MP_NEG)
+      rem = d - DIGIT(a, 0);
+    else
+      rem = DIGIT(a, 0);
+  }
+
+  if(c)
+    *c = rem;
+
+  return MP_OKAY;
+
+} /* end mp_mod_d() */
+
+/* }}} */
+
+/* {{{ mp_sqrt(a, b) */
+
+/*
+  mp_sqrt(a, b)
+
+  Compute the integer square root of a, and store the result in b.
+  Uses an integer-arithmetic version of Newton's iterative linear
+  approximation technique to determine this value; the result has the
+  following two properties:
+
+     b^2 <= a
+     (b+1)^2 >= a
+
+  It is a range error to pass a negative value.
+ */
+mp_err mp_sqrt(mp_int *a, mp_int *b)
+{
+  mp_int   x, t;
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  /* Cannot take square root of a negative value */
+  if(SIGN(a) == MP_NEG)
+    return MP_RANGE;
+
+  /* Special cases for zero and one, trivial     */
+  if(mp_cmp_d(a, 0) == MP_EQ || mp_cmp_d(a, 1) == MP_EQ) 
+    return mp_copy(a, b);
+    
+  /* Initialize the temporaries we'll use below  */
+  if((res = mp_init_size(&t, USED(a))) != MP_OKAY)
+    return res;
+
+  /* Compute an initial guess for the iteration as a itself */
+  if((res = mp_init_copy(&x, a)) != MP_OKAY)
+    goto X;
+
+s_mp_rshd(&x, (USED(&x)/2)+1);
+mp_add_d(&x, 1, &x);
+
+  for(;;) {
+    /* t = (x * x) - a */
+    mp_copy(&x, &t);      /* can't fail, t is big enough for original x */
+    if((res = mp_sqr(&t, &t)) != MP_OKAY ||
+       (res = mp_sub(&t, a, &t)) != MP_OKAY)
+      goto CLEANUP;
+
+    /* t = t / 2x       */
+    s_mp_mul_2(&x);
+    if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY)
+      goto CLEANUP;
+    s_mp_div_2(&x);
+
+    /* Terminate the loop, if the quotient is zero */
+    if(mp_cmp_z(&t) == MP_EQ)
+      break;
+
+    /* x = x - t       */
+    if((res = mp_sub(&x, &t, &x)) != MP_OKAY)
+      goto CLEANUP;
+
+  }
+
+  /* Copy result to output parameter */
+  mp_sub_d(&x, 1, &x);
+  s_mp_exch(&x, b);
+
+ CLEANUP:
+  mp_clear(&x);
+ X:
+  mp_clear(&t); 
+
+  return res;
+
+} /* end mp_sqrt() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Modular arithmetic */
+
+#if MP_MODARITH
+/* {{{ mp_addmod(a, b, m, c) */
+
+/*
+  mp_addmod(a, b, m, c)
+
+  Compute c = (a + b) mod m
+ */
+
+mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_add(a, b, c)) != MP_OKAY)
+    return res;
+  if((res = mp_mod(c, m, c)) != MP_OKAY)
+    return res;
+
+  return MP_OKAY;
+
+}
+
+/* }}} */
+
+/* {{{ mp_submod(a, b, m, c) */
+
+/*
+  mp_submod(a, b, m, c)
+
+  Compute c = (a - b) mod m
+ */
+
+mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_sub(a, b, c)) != MP_OKAY)
+    return res;
+  if((res = mp_mod(c, m, c)) != MP_OKAY)
+    return res;
+
+  return MP_OKAY;
+
+}
+
+/* }}} */
+
+/* {{{ mp_mulmod(a, b, m, c) */
+
+/*
+  mp_mulmod(a, b, m, c)
+
+  Compute c = (a * b) mod m
+ */
+
+mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_mul(a, b, c)) != MP_OKAY)
+    return res;
+  if((res = mp_mod(c, m, c)) != MP_OKAY)
+    return res;
+
+  return MP_OKAY;
+
+}
+
+/* }}} */
+
+/* {{{ mp_sqrmod(a, m, c) */
+
+#if MP_SQUARE
+mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_sqr(a, c)) != MP_OKAY)
+    return res;
+  if((res = mp_mod(c, m, c)) != MP_OKAY)
+    return res;
+
+  return MP_OKAY;
+
+} /* end mp_sqrmod() */
+#endif
+
+/* }}} */
+
+/* {{{ mp_exptmod(a, b, m, c) */
+
+/*
+  mp_exptmod(a, b, m, c)
+
+  Compute c = (a ** b) mod m.  Uses a standard square-and-multiply
+  method with modular reductions at each step. (This is basically the
+  same code as mp_expt(), except for the addition of the reductions)
+  
+  The modular reductions are done using Barrett's algorithm (see
+  s_mp_reduce() below for details)
+ */
+
+mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c)
+{
+  mp_int   s, x, mu;
+  mp_err   res;
+  mp_digit d, *db = DIGITS(b);
+  mp_size  ub = USED(b);
+  int      dig, bit;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
+    return MP_RANGE;
+
+  if((res = mp_init(&s)) != MP_OKAY)
+    return res;
+  if((res = mp_init_copy(&x, a)) != MP_OKAY)
+    goto X;
+  if((res = mp_mod(&x, m, &x)) != MP_OKAY ||
+     (res = mp_init(&mu)) != MP_OKAY)
+    goto MU;
+
+  mp_set(&s, 1);
+
+  /* mu = b^2k / m */
+  s_mp_add_d(&mu, 1); 
+  s_mp_lshd(&mu, 2 * USED(m));
+  if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY)
+    goto CLEANUP;
+
+  /* Loop over digits of b in ascending order, except highest order */
+  for(dig = 0; dig < (ub - 1); dig++) {
+    d = *db++;
+
+    /* Loop over the bits of the lower-order digits */
+    for(bit = 0; bit < DIGIT_BIT; bit++) {
+      if(d & 1) {
+       if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+         goto CLEANUP;
+       if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
+         goto CLEANUP;
+      }
+
+      d >>= 1;
+
+      if((res = s_mp_sqr(&x)) != MP_OKAY)
+       goto CLEANUP;
+      if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
+       goto CLEANUP;
+    }
+  }
+
+  /* Now do the last digit... */
+  d = *db;
+
+  while(d) {
+    if(d & 1) {
+      if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+       goto CLEANUP;
+      if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
+       goto CLEANUP;
+    }
+
+    d >>= 1;
+
+    if((res = s_mp_sqr(&x)) != MP_OKAY)
+      goto CLEANUP;
+    if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  s_mp_exch(&s, c);
+
+ CLEANUP:
+  mp_clear(&mu);
+ MU:
+  mp_clear(&x);
+ X:
+  mp_clear(&s);
+
+  return res;
+
+} /* end mp_exptmod() */
+
+/* }}} */
+
+/* {{{ mp_exptmod_d(a, d, m, c) */
+
+mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c)
+{
+  mp_int   s, x;
+  mp_err   res;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_init(&s)) != MP_OKAY)
+    return res;
+  if((res = mp_init_copy(&x, a)) != MP_OKAY)
+    goto X;
+
+  mp_set(&s, 1);
+
+  while(d != 0) {
+    if(d & 1) {
+      if((res = s_mp_mul(&s, &x)) != MP_OKAY ||
+        (res = mp_mod(&s, m, &s)) != MP_OKAY)
+       goto CLEANUP;
+    }
+
+    d /= 2;
+
+    if((res = s_mp_sqr(&x)) != MP_OKAY ||
+       (res = mp_mod(&x, m, &x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  s_mp_exch(&s, c);
+
+CLEANUP:
+  mp_clear(&x);
+X:
+  mp_clear(&s);
+
+  return res;
+
+} /* end mp_exptmod_d() */
+
+/* }}} */
+#endif /* if MP_MODARITH */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Comparison functions */
+
+/* {{{ mp_cmp_z(a) */
+
+/*
+  mp_cmp_z(a)
+
+  Compare a <=> 0.  Returns <0 if a<0, 0 if a=0, >0 if a>0.
+ */
+
+int    mp_cmp_z(mp_int *a)
+{
+  if(SIGN(a) == MP_NEG)
+    return MP_LT;
+  else if(USED(a) == 1 && DIGIT(a, 0) == 0)
+    return MP_EQ;
+  else
+    return MP_GT;
+
+} /* end mp_cmp_z() */
+
+/* }}} */
+
+/* {{{ mp_cmp_d(a, d) */
+
+/*
+  mp_cmp_d(a, d)
+
+  Compare a <=> d.  Returns <0 if a<d, 0 if a=d, >0 if a>d
+ */
+
+int    mp_cmp_d(mp_int *a, mp_digit d)
+{
+  ARGCHK(a != NULL, MP_EQ);
+
+  if(SIGN(a) == MP_NEG)
+    return MP_LT;
+
+  return s_mp_cmp_d(a, d);
+
+} /* end mp_cmp_d() */
+
+/* }}} */
+
+/* {{{ mp_cmp(a, b) */
+
+int    mp_cmp(mp_int *a, mp_int *b)
+{
+  ARGCHK(a != NULL && b != NULL, MP_EQ);
+
+  if(SIGN(a) == SIGN(b)) {
+    int  mag;
+
+    if((mag = s_mp_cmp(a, b)) == MP_EQ)
+      return MP_EQ;
+
+    if(SIGN(a) == MP_ZPOS)
+      return mag;
+    else
+      return -mag;
+
+  } else if(SIGN(a) == MP_ZPOS) {
+    return MP_GT;
+  } else {
+    return MP_LT;
+  }
+
+} /* end mp_cmp() */
+
+/* }}} */
+
+/* {{{ mp_cmp_mag(a, b) */
+
+/*
+  mp_cmp_mag(a, b)
+
+  Compares |a| <=> |b|, and returns an appropriate comparison result
+ */
+
+int    mp_cmp_mag(mp_int *a, mp_int *b)
+{
+  ARGCHK(a != NULL && b != NULL, MP_EQ);
+
+  return s_mp_cmp(a, b);
+
+} /* end mp_cmp_mag() */
+
+/* }}} */
+
+/* {{{ mp_cmp_int(a, z) */
+
+/*
+  This just converts z to an mp_int, and uses the existing comparison
+  routines.  This is sort of inefficient, but it's not clear to me how
+  frequently this wil get used anyway.  For small positive constants,
+  you can always use mp_cmp_d(), and for zero, there is mp_cmp_z().
+ */
+int    mp_cmp_int(mp_int *a, long z)
+{
+  mp_int  tmp;
+  int     out;
+
+  ARGCHK(a != NULL, MP_EQ);
+  
+  mp_init(&tmp); mp_set_int(&tmp, z);
+  out = mp_cmp(a, &tmp);
+  mp_clear(&tmp);
+
+  return out;
+
+} /* end mp_cmp_int() */
+
+/* }}} */
+
+/* {{{ mp_isodd(a) */
+
+/*
+  mp_isodd(a)
+
+  Returns a true (non-zero) value if a is odd, false (zero) otherwise.
+ */
+int    mp_isodd(mp_int *a)
+{
+  ARGCHK(a != NULL, 0);
+
+  return (DIGIT(a, 0) & 1);
+
+} /* end mp_isodd() */
+
+/* }}} */
+
+/* {{{ mp_iseven(a) */
+
+int    mp_iseven(mp_int *a)
+{
+  return !mp_isodd(a);
+
+} /* end mp_iseven() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Number theoretic functions */
+
+#if MP_NUMTH
+/* {{{ mp_gcd(a, b, c) */
+
+/*
+  Like the old mp_gcd() function, except computes the GCD using the
+  binary algorithm due to Josef Stein in 1961 (via Knuth).
+ */
+mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c)
+{
+  mp_err   res;
+  mp_int   u, v, t;
+  mp_size  k = 0;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ)
+      return MP_RANGE;
+  if(mp_cmp_z(a) == MP_EQ) {
+    return mp_copy(b, c);
+  } else if(mp_cmp_z(b) == MP_EQ) {
+    return mp_copy(a, c);
+  }
+
+  if((res = mp_init(&t)) != MP_OKAY)
+    return res;
+  if((res = mp_init_copy(&u, a)) != MP_OKAY)
+    goto U;
+  if((res = mp_init_copy(&v, b)) != MP_OKAY)
+    goto V;
+
+  SIGN(&u) = MP_ZPOS;
+  SIGN(&v) = MP_ZPOS;
+
+  /* Divide out common factors of 2 until at least 1 of a, b is even */
+  while(mp_iseven(&u) && mp_iseven(&v)) {
+    s_mp_div_2(&u);
+    s_mp_div_2(&v);
+    ++k;
+  }
+
+  /* Initialize t */
+  if(mp_isodd(&u)) {
+    if((res = mp_copy(&v, &t)) != MP_OKAY)
+      goto CLEANUP;
+    
+    /* t = -v */
+    if(SIGN(&v) == MP_ZPOS)
+      SIGN(&t) = MP_NEG;
+    else
+      SIGN(&t) = MP_ZPOS;
+    
+  } else {
+    if((res = mp_copy(&u, &t)) != MP_OKAY)
+      goto CLEANUP;
+
+  }
+
+  for(;;) {
+    while(mp_iseven(&t)) {
+      s_mp_div_2(&t);
+    }
+
+    if(mp_cmp_z(&t) == MP_GT) {
+      if((res = mp_copy(&t, &u)) != MP_OKAY)
+       goto CLEANUP;
+
+    } else {
+      if((res = mp_copy(&t, &v)) != MP_OKAY)
+       goto CLEANUP;
+
+      /* v = -t */
+      if(SIGN(&t) == MP_ZPOS)
+       SIGN(&v) = MP_NEG;
+      else
+       SIGN(&v) = MP_ZPOS;
+    }
+
+    if((res = mp_sub(&u, &v, &t)) != MP_OKAY)
+      goto CLEANUP;
+
+    if(s_mp_cmp_d(&t, 0) == MP_EQ)
+      break;
+  }
+
+  s_mp_2expt(&v, k);       /* v = 2^k   */
+  res = mp_mul(&u, &v, c); /* c = u * v */
+
+ CLEANUP:
+  mp_clear(&v);
+ V:
+  mp_clear(&u);
+ U:
+  mp_clear(&t);
+
+  return res;
+
+} /* end mp_bgcd() */
+
+/* }}} */
+
+/* {{{ mp_lcm(a, b, c) */
+
+/* We compute the least common multiple using the rule:
+
+   ab = [a, b](a, b)
+
+   ... by computing the product, and dividing out the gcd.
+ */
+
+mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c)
+{
+  mp_int  gcd, prod;
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  /* Set up temporaries */
+  if((res = mp_init(&gcd)) != MP_OKAY)
+    return res;
+  if((res = mp_init(&prod)) != MP_OKAY)
+    goto GCD;
+
+  if((res = mp_mul(a, b, &prod)) != MP_OKAY)
+    goto CLEANUP;
+  if((res = mp_gcd(a, b, &gcd)) != MP_OKAY)
+    goto CLEANUP;
+
+  res = mp_div(&prod, &gcd, c, NULL);
+
+ CLEANUP:
+  mp_clear(&prod);
+ GCD:
+  mp_clear(&gcd);
+
+  return res;
+
+} /* end mp_lcm() */
+
+/* }}} */
+
+/* {{{ mp_xgcd(a, b, g, x, y) */
+
+/*
+  mp_xgcd(a, b, g, x, y)
+
+  Compute g = (a, b) and values x and y satisfying Bezout's identity
+  (that is, ax + by = g).  This uses the extended binary GCD algorithm
+  based on the Stein algorithm used for mp_gcd()
+ */
+
+mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y)
+{
+  mp_int   gx, xc, yc, u, v, A, B, C, D;
+  mp_int  *clean[9];
+  mp_err   res;
+  int      last = -1;
+
+  if(mp_cmp_z(b) == 0)
+    return MP_RANGE;
+
+  /* Initialize all these variables we need */
+  if((res = mp_init(&u)) != MP_OKAY) goto CLEANUP;
+  clean[++last] = &u;
+  if((res = mp_init(&v)) != MP_OKAY) goto CLEANUP;
+  clean[++last] = &v;
+  if((res = mp_init(&gx)) != MP_OKAY) goto CLEANUP;
+  clean[++last] = &gx;
+  if((res = mp_init(&A)) != MP_OKAY) goto CLEANUP;
+  clean[++last] = &A;
+  if((res = mp_init(&B)) != MP_OKAY) goto CLEANUP;
+  clean[++last] = &B;
+  if((res = mp_init(&C)) != MP_OKAY) goto CLEANUP;
+  clean[++last] = &C;
+  if((res = mp_init(&D)) != MP_OKAY) goto CLEANUP;
+  clean[++last] = &D;
+  if((res = mp_init_copy(&xc, a)) != MP_OKAY) goto CLEANUP;
+  clean[++last] = &xc;
+  mp_abs(&xc, &xc);
+  if((res = mp_init_copy(&yc, b)) != MP_OKAY) goto CLEANUP;
+  clean[++last] = &yc;
+  mp_abs(&yc, &yc);
+
+  mp_set(&gx, 1);
+
+  /* Divide by two until at least one of them is even */
+  while(mp_iseven(&xc) && mp_iseven(&yc)) {
+    s_mp_div_2(&xc);
+    s_mp_div_2(&yc);
+    if((res = s_mp_mul_2(&gx)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  mp_copy(&xc, &u);
+  mp_copy(&yc, &v);
+  mp_set(&A, 1); mp_set(&D, 1);
+
+  /* Loop through binary GCD algorithm */
+  for(;;) {
+    while(mp_iseven(&u)) {
+      s_mp_div_2(&u);
+
+      if(mp_iseven(&A) && mp_iseven(&B)) {
+       s_mp_div_2(&A); s_mp_div_2(&B);
+      } else {
+       if((res = mp_add(&A, &yc, &A)) != MP_OKAY) goto CLEANUP;
+       s_mp_div_2(&A);
+       if((res = mp_sub(&B, &xc, &B)) != MP_OKAY) goto CLEANUP;
+       s_mp_div_2(&B);
+      }
+    }
+
+    while(mp_iseven(&v)) {
+      s_mp_div_2(&v);
+
+      if(mp_iseven(&C) && mp_iseven(&D)) {
+       s_mp_div_2(&C); s_mp_div_2(&D);
+      } else {
+       if((res = mp_add(&C, &yc, &C)) != MP_OKAY) goto CLEANUP;
+       s_mp_div_2(&C);
+       if((res = mp_sub(&D, &xc, &D)) != MP_OKAY) goto CLEANUP;
+       s_mp_div_2(&D);
+      }
+    }
+
+    if(mp_cmp(&u, &v) >= 0) {
+      if((res = mp_sub(&u, &v, &u)) != MP_OKAY) goto CLEANUP;
+      if((res = mp_sub(&A, &C, &A)) != MP_OKAY) goto CLEANUP;
+      if((res = mp_sub(&B, &D, &B)) != MP_OKAY) goto CLEANUP;
+
+    } else {
+      if((res = mp_sub(&v, &u, &v)) != MP_OKAY) goto CLEANUP;
+      if((res = mp_sub(&C, &A, &C)) != MP_OKAY) goto CLEANUP;
+      if((res = mp_sub(&D, &B, &D)) != MP_OKAY) goto CLEANUP;
+
+    }
+
+    /* If we're done, copy results to output */
+    if(mp_cmp_z(&u) == 0) {
+      if(x)
+       if((res = mp_copy(&C, x)) != MP_OKAY) goto CLEANUP;
+
+      if(y)
+       if((res = mp_copy(&D, y)) != MP_OKAY) goto CLEANUP;
+      
+      if(g)
+       if((res = mp_mul(&gx, &v, g)) != MP_OKAY) goto CLEANUP;
+
+      break;
+    }
+  }
+
+ CLEANUP:
+  while(last >= 0)
+    mp_clear(clean[last--]);
+
+  return res;
+
+} /* end mp_xgcd() */
+
+/* }}} */
+
+/* {{{ mp_invmod(a, m, c) */
+
+/*
+  mp_invmod(a, m, c)
+
+  Compute c = a^-1 (mod m), if there is an inverse for a (mod m).
+  This is equivalent to the question of whether (a, m) = 1.  If not,
+  MP_UNDEF is returned, and there is no inverse.
+ */
+
+mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c)
+{
+  mp_int  g, x;
+  mp_err  res;
+
+  ARGCHK(a && m && c, MP_BADARG);
+
+  if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
+    return MP_RANGE;
+
+  if((res = mp_init(&g)) != MP_OKAY)
+    return res;
+  if((res = mp_init(&x)) != MP_OKAY)
+    goto X;
+
+  if((res = mp_xgcd(a, m, &g, &x, NULL)) != MP_OKAY)
+    goto CLEANUP;
+
+  if(mp_cmp_d(&g, 1) != MP_EQ) {
+    res = MP_UNDEF;
+    goto CLEANUP;
+  }
+
+  res = mp_mod(&x, m, c);
+  SIGN(c) = SIGN(a);
+
+CLEANUP:
+  mp_clear(&x);
+X:
+  mp_clear(&g);
+
+  return res;
+
+} /* end mp_invmod() */
+
+/* }}} */
+#endif /* if MP_NUMTH */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ mp_print(mp, ofp) */
+
+#if MP_IOFUNC
+/*
+  mp_print(mp, ofp)
+
+  Print a textual representation of the given mp_int on the output
+  stream 'ofp'.  Output is generated using the internal radix.
+ */
+
+void   mp_print(mp_int *mp, FILE *ofp)
+{
+  int   ix;
+
+  if(mp == NULL || ofp == NULL)
+    return;
+
+  fputc((SIGN(mp) == MP_NEG) ? '-' : '+', ofp);
+
+  for(ix = USED(mp) - 1; ix >= 0; ix--) {
+    fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix));
+  }
+
+} /* end mp_print() */
+
+#endif /* if MP_IOFUNC */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ More I/O Functions */
+
+/* {{{ mp_read_signed_bin(mp, str, len) */
+
+/* 
+   mp_read_signed_bin(mp, str, len)
+
+   Read in a raw value (base 256) into the given mp_int
+ */
+
+mp_err  mp_read_signed_bin(mp_int *mp, unsigned char *str, int len)
+{
+  mp_err         res;
+
+  ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
+
+  if((res = mp_read_unsigned_bin(mp, str + 1, len - 1)) == MP_OKAY) {
+    /* Get sign from first byte */
+    if(str[0])
+      SIGN(mp) = MP_NEG;
+    else
+      SIGN(mp) = MP_ZPOS;
+  }
+
+  return res;
+
+} /* end mp_read_signed_bin() */
+
+/* }}} */
+
+/* {{{ mp_signed_bin_size(mp) */
+
+int    mp_signed_bin_size(mp_int *mp)
+{
+  ARGCHK(mp != NULL, 0);
+
+  return mp_unsigned_bin_size(mp) + 1;
+
+} /* end mp_signed_bin_size() */
+
+/* }}} */
+
+/* {{{ mp_to_signed_bin(mp, str) */
+
+mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str)
+{
+  ARGCHK(mp != NULL && str != NULL, MP_BADARG);
+
+  /* Caller responsible for allocating enough memory (use mp_raw_size(mp)) */
+  str[0] = (char)SIGN(mp);
+
+  return mp_to_unsigned_bin(mp, str + 1);
+
+} /* end mp_to_signed_bin() */
+
+/* }}} */
+
+/* {{{ mp_read_unsigned_bin(mp, str, len) */
+
+/*
+  mp_read_unsigned_bin(mp, str, len)
+
+  Read in an unsigned value (base 256) into the given mp_int
+ */
+
+mp_err  mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len)
+{
+  int     ix;
+  mp_err  res;
+
+  ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
+
+  mp_zero(mp);
+
+  for(ix = 0; ix < len; ix++) {
+    if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY)
+      return res;
+
+    if((res = mp_add_d(mp, str[ix], mp)) != MP_OKAY)
+      return res;
+  }
+  
+  return MP_OKAY;
+  
+} /* end mp_read_unsigned_bin() */
+
+/* }}} */
+
+/* {{{ mp_unsigned_bin_size(mp) */
+
+int     mp_unsigned_bin_size(mp_int *mp) 
+{
+  mp_digit   topdig;
+  int        count;
+
+  ARGCHK(mp != NULL, 0);
+
+  /* Special case for the value zero */
+  if(USED(mp) == 1 && DIGIT(mp, 0) == 0)
+    return 1;
+
+  count = (USED(mp) - 1) * sizeof(mp_digit);
+  topdig = DIGIT(mp, USED(mp) - 1);
+
+  while(topdig != 0) {
+    ++count;
+    topdig >>= CHAR_BIT;
+  }
+
+  return count;
+
+} /* end mp_unsigned_bin_size() */
+
+/* }}} */
+
+/* {{{ mp_to_unsigned_bin(mp, str) */
+
+mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str)
+{
+  mp_digit      *dp, *end, d;
+  unsigned char *spos;
+
+  ARGCHK(mp != NULL && str != NULL, MP_BADARG);
+
+  dp = DIGITS(mp);
+  end = dp + USED(mp) - 1;
+  spos = str;
+
+  /* Special case for zero, quick test */
+  if(dp == end && *dp == 0) {
+    *str = '\0';
+    return MP_OKAY;
+  }
+
+  /* Generate digits in reverse order */
+  while(dp < end) {
+    int      ix;
+
+    d = *dp;
+    for(ix = 0; ix < sizeof(mp_digit); ++ix) {
+      *spos = d & UCHAR_MAX;
+      d >>= CHAR_BIT;
+      ++spos;
+    }
+
+    ++dp;
+  }
+
+  /* Now handle last digit specially, high order zeroes are not written */
+  d = *end;
+  while(d != 0) {
+    *spos = d & UCHAR_MAX;
+    d >>= CHAR_BIT;
+    ++spos;
+  }
+
+  /* Reverse everything to get digits in the correct order */
+  while(--spos > str) {
+    unsigned char t = *str;
+    *str = *spos;
+    *spos = t;
+
+    ++str;
+  }
+
+  return MP_OKAY;
+
+} /* end mp_to_unsigned_bin() */
+
+/* }}} */
+
+/* {{{ mp_count_bits(mp) */
+
+int    mp_count_bits(mp_int *mp)
+{
+  int      len;
+  mp_digit d;
+
+  ARGCHK(mp != NULL, MP_BADARG);
+
+  len = DIGIT_BIT * (USED(mp) - 1);
+  d = DIGIT(mp, USED(mp) - 1);
+
+  while(d != 0) {
+    ++len;
+    d >>= 1;
+  }
+
+  return len;
+  
+} /* end mp_count_bits() */
+
+/* }}} */
+
+/* {{{ mp_read_radix(mp, str, radix) */
+
+/*
+  mp_read_radix(mp, str, radix)
+
+  Read an integer from the given string, and set mp to the resulting
+  value.  The input is presumed to be in base 10.  Leading non-digit
+  characters are ignored, and the function reads until a non-digit
+  character or the end of the string.
+ */
+
+mp_err  mp_read_radix(mp_int *mp, unsigned char *str, int radix)
+{
+  int     ix = 0, val = 0;
+  mp_err  res;
+  mp_sign sig = MP_ZPOS;
+
+  ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX, 
+        MP_BADARG);
+
+  mp_zero(mp);
+
+  /* Skip leading non-digit characters until a digit or '-' or '+' */
+  while(str[ix] && 
+       (s_mp_tovalue(str[ix], radix) < 0) && 
+       str[ix] != '-' &&
+       str[ix] != '+') {
+    ++ix;
+  }
+
+  if(str[ix] == '-') {
+    sig = MP_NEG;
+    ++ix;
+  } else if(str[ix] == '+') {
+    sig = MP_ZPOS; /* this is the default anyway... */
+    ++ix;
+  }
+
+  while((val = s_mp_tovalue(str[ix], radix)) >= 0) {
+    if((res = s_mp_mul_d(mp, radix)) != MP_OKAY)
+      return res;
+    if((res = s_mp_add_d(mp, val)) != MP_OKAY)
+      return res;
+    ++ix;
+  }
+
+  if(s_mp_cmp_d(mp, 0) == MP_EQ)
+    SIGN(mp) = MP_ZPOS;
+  else
+    SIGN(mp) = sig;
+
+  return MP_OKAY;
+
+} /* end mp_read_radix() */
+
+/* }}} */
+
+/* {{{ mp_radix_size(mp, radix) */
+
+int    mp_radix_size(mp_int *mp, int radix)
+{
+  int  len;
+  ARGCHK(mp != NULL, 0);
+
+  len = s_mp_outlen(mp_count_bits(mp), radix) + 1; /* for NUL terminator */
+
+  if(mp_cmp_z(mp) < 0)
+    ++len; /* for sign */
+
+  return len;
+
+} /* end mp_radix_size() */
+
+/* }}} */
+
+/* {{{ mp_value_radix_size(num, qty, radix) */
+
+/* num = number of digits
+   qty = number of bits per digit
+   radix = target base
+   
+   Return the number of digits in the specified radix that would be
+   needed to express 'num' digits of 'qty' bits each.
+ */
+int    mp_value_radix_size(int num, int qty, int radix)
+{
+  ARGCHK(num >= 0 && qty > 0 && radix >= 2 && radix <= MAX_RADIX, 0);
+
+  return s_mp_outlen(num * qty, radix);
+
+} /* end mp_value_radix_size() */
+
+/* }}} */
+
+/* {{{ mp_toradix(mp, str, radix) */
+
+mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix)
+{
+  int  ix, pos = 0;
+
+  ARGCHK(mp != NULL && str != NULL, MP_BADARG);
+  ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE);
+
+  if(mp_cmp_z(mp) == MP_EQ) {
+    str[0] = '0';
+    str[1] = '\0';
+  } else {
+    mp_err   res;
+    mp_int   tmp;
+    mp_sign  sgn;
+    mp_digit rem, rdx = (mp_digit)radix;
+    char     ch;
+
+    if((res = mp_init_copy(&tmp, mp)) != MP_OKAY)
+      return res;
+
+    /* Save sign for later, and take absolute value */
+    sgn = SIGN(&tmp); SIGN(&tmp) = MP_ZPOS;
+
+    /* Generate output digits in reverse order      */
+    while(mp_cmp_z(&tmp) != 0) {
+      if((res = s_mp_div_d(&tmp, rdx, &rem)) != MP_OKAY) {
+       mp_clear(&tmp);
+       return res;
+      }
+
+      /* Generate digits, use capital letters */
+      ch = s_mp_todigit(rem, radix, 0);
+
+      str[pos++] = ch;
+    }
+
+    /* Add - sign if original value was negative */
+    if(sgn == MP_NEG)
+      str[pos++] = '-';
+
+    /* Add trailing NUL to end the string        */
+    str[pos--] = '\0';
+
+    /* Reverse the digits and sign indicator     */
+    ix = 0;
+    while(ix < pos) {
+      char tmp = str[ix];
+
+      str[ix] = str[pos];
+      str[pos] = tmp;
+      ++ix;
+      --pos;
+    }
+    
+    mp_clear(&tmp);
+  }
+
+  return MP_OKAY;
+
+} /* end mp_toradix() */
+
+/* }}} */
+
+/* {{{ mp_char2value(ch, r) */
+
+int    mp_char2value(char ch, int r)
+{
+  return s_mp_tovalue(ch, r);
+
+} /* end mp_tovalue() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ mp_strerror(ec) */
+
+/*
+  mp_strerror(ec)
+
+  Return a string describing the meaning of error code 'ec'.  The
+  string returned is allocated in static memory, so the caller should
+  not attempt to modify or free the memory associated with this
+  string.
+ */
+const char  *mp_strerror(mp_err ec)
+{
+  int   aec = (ec < 0) ? -ec : ec;
+
+  /* Code values are negative, so the senses of these comparisons
+     are accurate */
+  if(ec < MP_LAST_CODE || ec > MP_OKAY) {
+    return mp_err_string[0];  /* unknown error code */
+  } else {
+    return mp_err_string[aec + 1];
+  }
+
+} /* end mp_strerror() */
+
+/* }}} */
+
+/*========================================================================*/
+/*------------------------------------------------------------------------*/
+/* Static function definitions (internal use only)                        */
+
+/* {{{ Memory management */
+
+/* {{{ s_mp_grow(mp, min) */
+
+/* Make sure there are at least 'min' digits allocated to mp              */
+mp_err   s_mp_grow(mp_int *mp, mp_size min)
+{
+  if(min > ALLOC(mp)) {
+    mp_digit   *tmp;
+
+    /* Set min to next nearest default precision block size */
+    min = ((min + (s_mp_defprec - 1)) / s_mp_defprec) * s_mp_defprec;
+
+    if((tmp = s_mp_alloc(min, sizeof(mp_digit))) == NULL)
+      return MP_MEM;
+
+    s_mp_copy(DIGITS(mp), tmp, USED(mp));
+
+#if MP_CRYPTO
+    s_mp_setz(DIGITS(mp), ALLOC(mp));
+#endif
+    s_mp_free(DIGITS(mp));
+    DIGITS(mp) = tmp;
+    ALLOC(mp) = min;
+  }
+
+  return MP_OKAY;
+
+} /* end s_mp_grow() */
+
+/* }}} */
+
+/* {{{ s_mp_pad(mp, min) */
+
+/* Make sure the used size of mp is at least 'min', growing if needed     */
+mp_err   s_mp_pad(mp_int *mp, mp_size min)
+{
+  if(min > USED(mp)) {
+    mp_err  res;
+
+    /* Make sure there is room to increase precision  */
+    if(min > ALLOC(mp) && (res = s_mp_grow(mp, min)) != MP_OKAY)
+      return res;
+
+    /* Increase precision; should already be 0-filled */
+    USED(mp) = min;
+  }
+
+  return MP_OKAY;
+
+} /* end s_mp_pad() */
+
+/* }}} */
+
+/* {{{ s_mp_setz(dp, count) */
+
+#if MP_MACRO == 0
+/* Set 'count' digits pointed to by dp to be zeroes                       */
+void s_mp_setz(mp_digit *dp, mp_size count)
+{
+#if MP_MEMSET == 0
+  int  ix;
+
+  for(ix = 0; ix < count; ix++)
+    dp[ix] = 0;
+#else
+  memset(dp, 0, count * sizeof(mp_digit));
+#endif
+
+} /* end s_mp_setz() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_copy(sp, dp, count) */
+
+#if MP_MACRO == 0
+/* Copy 'count' digits from sp to dp                                      */
+void s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count)
+{
+#if MP_MEMCPY == 0
+  int  ix;
+
+  for(ix = 0; ix < count; ix++)
+    dp[ix] = sp[ix];
+#else
+  memcpy(dp, sp, count * sizeof(mp_digit));
+#endif
+
+} /* end s_mp_copy() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_alloc(nb, ni) */
+
+#if MP_MACRO == 0
+/* Allocate ni records of nb bytes each, and return a pointer to that     */
+void    *s_mp_alloc(size_t nb, size_t ni)
+{
+  return calloc(nb, ni);
+
+} /* end s_mp_alloc() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_free(ptr) */
+
+#if MP_MACRO == 0
+/* Free the memory pointed to by ptr                                      */
+void     s_mp_free(void *ptr)
+{
+  if(ptr)
+    free(ptr);
+
+} /* end s_mp_free() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_clamp(mp) */
+
+/* Remove leading zeroes from the given value                             */
+void     s_mp_clamp(mp_int *mp)
+{
+  mp_size   du = USED(mp);
+  mp_digit *zp = DIGITS(mp) + du - 1;
+
+  while(du > 1 && !*zp--)
+    --du;
+
+  USED(mp) = du;
+
+} /* end s_mp_clamp() */
+
+
+/* }}} */
+
+/* {{{ s_mp_exch(a, b) */
+
+/* Exchange the data for a and b; (b, a) = (a, b)                         */
+void     s_mp_exch(mp_int *a, mp_int *b)
+{
+  mp_int   tmp;
+
+  tmp = *a;
+  *a = *b;
+  *b = tmp;
+
+} /* end s_mp_exch() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Arithmetic helpers */
+
+/* {{{ s_mp_lshd(mp, p) */
+
+/* 
+   Shift mp leftward by p digits, growing if needed, and zero-filling
+   the in-shifted digits at the right end.  This is a convenient
+   alternative to multiplication by powers of the radix
+ */   
+
+mp_err   s_mp_lshd(mp_int *mp, mp_size p)
+{
+  mp_err   res;
+  mp_size  pos;
+  mp_digit *dp;
+  int     ix;
+
+  if(p == 0)
+    return MP_OKAY;
+
+  if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY)
+    return res;
+
+  pos = USED(mp) - 1;
+  dp = DIGITS(mp);
+
+  /* Shift all the significant figures over as needed */
+  for(ix = pos - p; ix >= 0; ix--) 
+    dp[ix + p] = dp[ix];
+
+  /* Fill the bottom digits with zeroes */
+  for(ix = 0; ix < p; ix++)
+    dp[ix] = 0;
+
+  return MP_OKAY;
+
+} /* end s_mp_lshd() */
+
+/* }}} */
+
+/* {{{ s_mp_rshd(mp, p) */
+
+/* 
+   Shift mp rightward by p digits.  Maintains the invariant that
+   digits above the precision are all zero.  Digits shifted off the
+   end are lost.  Cannot fail.
+ */
+
+void     s_mp_rshd(mp_int *mp, mp_size p)
+{
+  mp_size  ix;
+  mp_digit *dp;
+
+  if(p == 0)
+    return;
+
+  /* Shortcut when all digits are to be shifted off */
+  if(p >= USED(mp)) {
+    s_mp_setz(DIGITS(mp), ALLOC(mp));
+    USED(mp) = 1;
+    SIGN(mp) = MP_ZPOS;
+    return;
+  }
+
+  /* Shift all the significant figures over as needed */
+  dp = DIGITS(mp);
+  for(ix = p; ix < USED(mp); ix++)
+    dp[ix - p] = dp[ix];
+
+  /* Fill the top digits with zeroes */
+  ix -= p;
+  while(ix < USED(mp))
+    dp[ix++] = 0;
+
+  /* Strip off any leading zeroes    */
+  s_mp_clamp(mp);
+
+} /* end s_mp_rshd() */
+
+/* }}} */
+
+/* {{{ s_mp_div_2(mp) */
+
+/* Divide by two -- take advantage of radix properties to do it fast      */
+void     s_mp_div_2(mp_int *mp)
+{
+  s_mp_div_2d(mp, 1);
+
+} /* end s_mp_div_2() */
+
+/* }}} */
+
+/* {{{ s_mp_mul_2(mp) */
+
+mp_err s_mp_mul_2(mp_int *mp)
+{
+  int      ix;
+  mp_digit kin = 0, kout, *dp = DIGITS(mp);
+  mp_err   res;
+
+  /* Shift digits leftward by 1 bit */
+  for(ix = 0; ix < USED(mp); ix++) {
+    kout = (dp[ix] >> (DIGIT_BIT - 1)) & 1;
+    dp[ix] = (dp[ix] << 1) | kin;
+
+    kin = kout;
+  }
+
+  /* Deal with rollover from last digit */
+  if(kin) {
+    if(ix >= ALLOC(mp)) {
+      if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY)
+       return res;
+      dp = DIGITS(mp);
+    }
+
+    dp[ix] = kin;
+    USED(mp) += 1;
+  }
+
+  return MP_OKAY;
+
+} /* end s_mp_mul_2() */
+
+/* }}} */
+
+/* {{{ s_mp_mod_2d(mp, d) */
+
+/*
+  Remainder the integer by 2^d, where d is a number of bits.  This
+  amounts to a bitwise AND of the value, and does not require the full
+  division code
+ */
+void     s_mp_mod_2d(mp_int *mp, mp_digit d)
+{
+  unsigned int  ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT);
+  unsigned int  ix;
+  mp_digit      dmask, *dp = DIGITS(mp);
+
+  if(ndig >= USED(mp))
+    return;
+
+  /* Flush all the bits above 2^d in its digit */
+  dmask = (1 << nbit) - 1;
+  dp[ndig] &= dmask;
+
+  /* Flush all digits above the one with 2^d in it */
+  for(ix = ndig + 1; ix < USED(mp); ix++)
+    dp[ix] = 0;
+
+  s_mp_clamp(mp);
+
+} /* end s_mp_mod_2d() */
+
+/* }}} */
+
+/* {{{ s_mp_mul_2d(mp, d) */
+
+/*
+  Multiply by the integer 2^d, where d is a number of bits.  This
+  amounts to a bitwise shift of the value, and does not require the
+  full multiplication code.
+ */
+mp_err    s_mp_mul_2d(mp_int *mp, mp_digit d)
+{
+  mp_err   res;
+  mp_digit save, next, mask, *dp;
+  mp_size  used;
+  int      ix;
+
+  if((res = s_mp_lshd(mp, d / DIGIT_BIT)) != MP_OKAY)
+    return res;
+
+  dp = DIGITS(mp); used = USED(mp);
+  d %= DIGIT_BIT;
+
+  mask = (1 << d) - 1;
+
+  /* If the shift requires another digit, make sure we've got one to
+     work with */
+  if((dp[used - 1] >> (DIGIT_BIT - d)) & mask) {
+    if((res = s_mp_grow(mp, used + 1)) != MP_OKAY)
+      return res;
+    dp = DIGITS(mp);
+  }
+
+  /* Do the shifting... */
+  save = 0;
+  for(ix = 0; ix < used; ix++) {
+    next = (dp[ix] >> (DIGIT_BIT - d)) & mask;
+    dp[ix] = (dp[ix] << d) | save;
+    save = next;
+  }
+
+  /* If, at this point, we have a nonzero carryout into the next
+     digit, we'll increase the size by one digit, and store it...
+   */
+  if(save) {
+    dp[used] = save;
+    USED(mp) += 1;
+  }
+
+  s_mp_clamp(mp);
+  return MP_OKAY;
+
+} /* end s_mp_mul_2d() */
+
+/* }}} */
+
+/* {{{ s_mp_div_2d(mp, d) */
+
+/*
+  Divide the integer by 2^d, where d is a number of bits.  This
+  amounts to a bitwise shift of the value, and does not require the
+  full division code (used in Barrett reduction, see below)
+ */
+void     s_mp_div_2d(mp_int *mp, mp_digit d)
+{
+  int       ix;
+  mp_digit  save, next, mask, *dp = DIGITS(mp);
+
+  s_mp_rshd(mp, d / DIGIT_BIT);
+  d %= DIGIT_BIT;
+
+  mask = (1 << d) - 1;
+
+  save = 0;
+  for(ix = USED(mp) - 1; ix >= 0; ix--) {
+    next = dp[ix] & mask;
+    dp[ix] = (dp[ix] >> d) | (save << (DIGIT_BIT - d));
+    save = next;
+  }
+
+  s_mp_clamp(mp);
+
+} /* end s_mp_div_2d() */
+
+/* }}} */
+
+/* {{{ s_mp_norm(a, b) */
+
+/*
+  s_mp_norm(a, b)
+
+  Normalize a and b for division, where b is the divisor.  In order
+  that we might make good guesses for quotient digits, we want the
+  leading digit of b to be at least half the radix, which we
+  accomplish by multiplying a and b by a constant.  This constant is
+  returned (so that it can be divided back out of the remainder at the
+  end of the division process).
+
+  We multiply by the smallest power of 2 that gives us a leading digit
+  at least half the radix.  By choosing a power of 2, we simplify the 
+  multiplication and division steps to simple shifts.
+ */
+mp_digit s_mp_norm(mp_int *a, mp_int *b)
+{
+  mp_digit  t, d = 0;
+
+  t = DIGIT(b, USED(b) - 1);
+  while(t < (RADIX / 2)) {
+    t <<= 1;
+    ++d;
+  }
+    
+  if(d != 0) {
+    s_mp_mul_2d(a, d);
+    s_mp_mul_2d(b, d);
+  }
+
+  return d;
+
+} /* end s_mp_norm() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive digit arithmetic */
+
+/* {{{ s_mp_add_d(mp, d) */
+
+/* Add d to |mp| in place                                                 */
+mp_err   s_mp_add_d(mp_int *mp, mp_digit d)    /* unsigned digit addition */
+{
+  mp_word   w, k = 0;
+  mp_size   ix = 1, used = USED(mp);
+  mp_digit *dp = DIGITS(mp);
+
+  w = dp[0] + d;
+  dp[0] = ACCUM(w);
+  k = CARRYOUT(w);
+
+  while(ix < used && k) {
+    w = dp[ix] + k;
+    dp[ix] = ACCUM(w);
+    k = CARRYOUT(w);
+    ++ix;
+  }
+
+  if(k != 0) {
+    mp_err  res;
+
+    if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY)
+      return res;
+
+    DIGIT(mp, ix) = k;
+  }
+
+  return MP_OKAY;
+
+} /* end s_mp_add_d() */
+
+/* }}} */
+
+/* {{{ s_mp_sub_d(mp, d) */
+
+/* Subtract d from |mp| in place, assumes |mp| > d                        */
+mp_err   s_mp_sub_d(mp_int *mp, mp_digit d)    /* unsigned digit subtract */
+{
+  mp_word   w, b = 0;
+  mp_size   ix = 1, used = USED(mp);
+  mp_digit *dp = DIGITS(mp);
+
+  /* Compute initial subtraction    */
+  w = (RADIX + dp[0]) - d;
+  b = CARRYOUT(w) ? 0 : 1;
+  dp[0] = ACCUM(w);
+
+  /* Propagate borrows leftward     */
+  while(b && ix < used) {
+    w = (RADIX + dp[ix]) - b;
+    b = CARRYOUT(w) ? 0 : 1;
+    dp[ix] = ACCUM(w);
+    ++ix;
+  }
+
+  /* Remove leading zeroes          */
+  s_mp_clamp(mp);
+
+  /* If we have a borrow out, it's a violation of the input invariant */
+  if(b)
+    return MP_RANGE;
+  else
+    return MP_OKAY;
+
+} /* end s_mp_sub_d() */
+
+/* }}} */
+
+/* {{{ s_mp_mul_d(a, d) */
+
+/* Compute a = a * d, single digit multiplication                         */
+mp_err   s_mp_mul_d(mp_int *a, mp_digit d)
+{
+  mp_word w, k = 0;
+  mp_size ix, max;
+  mp_err  res;
+  mp_digit *dp = DIGITS(a);
+
+  /*
+    Single-digit multiplication will increase the precision of the
+    output by at most one digit.  However, we can detect when this
+    will happen -- if the high-order digit of a, times d, gives a
+    two-digit result, then the precision of the result will increase;
+    otherwise it won't.  We use this fact to avoid calling s_mp_pad()
+    unless absolutely necessary.
+   */
+  max = USED(a);
+  w = dp[max - 1] * d;
+  if(CARRYOUT(w) != 0) {
+    if((res = s_mp_pad(a, max + 1)) != MP_OKAY)
+      return res;
+    dp = DIGITS(a);
+  }
+
+  for(ix = 0; ix < max; ix++) {
+    w = (dp[ix] * d) + k;
+    dp[ix] = ACCUM(w);
+    k = CARRYOUT(w);
+  }
+
+  /* If there is a precision increase, take care of it here; the above
+     test guarantees we have enough storage to do this safely.
+   */
+  if(k) {
+    dp[max] = k; 
+    USED(a) = max + 1;
+  }
+
+  s_mp_clamp(a);
+
+  return MP_OKAY;
+  
+} /* end s_mp_mul_d() */
+
+/* }}} */
+
+/* {{{ s_mp_div_d(mp, d, r) */
+
+/*
+  s_mp_div_d(mp, d, r)
+
+  Compute the quotient mp = mp / d and remainder r = mp mod d, for a
+  single digit d.  If r is null, the remainder will be discarded.
+ */
+
+mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r)
+{
+  mp_word   w = 0, t;
+  mp_int    quot;
+  mp_err    res;
+  mp_digit *dp = DIGITS(mp), *qp;
+  int       ix;
+
+  if(d == 0)
+    return MP_RANGE;
+
+  /* Make room for the quotient */
+  if((res = mp_init_size(&quot, USED(mp))) != MP_OKAY)
+    return res;
+
+  USED(&quot) = USED(mp); /* so clamping will work below */
+  qp = DIGITS(&quot);
+
+  /* Divide without subtraction */
+  for(ix = USED(mp) - 1; ix >= 0; ix--) {
+    w = (w << DIGIT_BIT) | dp[ix];
+
+    if(w >= d) {
+      t = w / d;
+      w = w % d;
+    } else {
+      t = 0;
+    }
+
+    qp[ix] = t;
+  }
+
+  /* Deliver the remainder, if desired */
+  if(r)
+    *r = w;
+
+  s_mp_clamp(&quot);
+  mp_exch(&quot, mp);
+  mp_clear(&quot);
+
+  return MP_OKAY;
+
+} /* end s_mp_div_d() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive full arithmetic */
+
+/* {{{ s_mp_add(a, b) */
+
+/* Compute a = |a| + |b|                                                  */
+mp_err   s_mp_add(mp_int *a, mp_int *b)        /* magnitude addition      */
+{
+  mp_word   w = 0;
+  mp_digit *pa, *pb;
+  mp_size   ix, used = USED(b);
+  mp_err    res;
+
+  /* Make sure a has enough precision for the output value */
+  if((used > USED(a)) && (res = s_mp_pad(a, used)) != MP_OKAY)
+    return res;
+
+  /*
+    Add up all digits up to the precision of b.  If b had initially
+    the same precision as a, or greater, we took care of it by the
+    padding step above, so there is no problem.  If b had initially
+    less precision, we'll have to make sure the carry out is duly
+    propagated upward among the higher-order digits of the sum.
+   */
+  pa = DIGITS(a);
+  pb = DIGITS(b);
+  for(ix = 0; ix < used; ++ix) {
+    w += *pa + *pb++;
+    *pa++ = ACCUM(w);
+    w = CARRYOUT(w);
+  }
+
+  /* If we run out of 'b' digits before we're actually done, make
+     sure the carries get propagated upward...  
+   */
+  used = USED(a);
+  while(w && ix < used) {
+    w += *pa;
+    *pa++ = ACCUM(w);
+    w = CARRYOUT(w);
+    ++ix;
+  }
+
+  /* If there's an overall carry out, increase precision and include
+     it.  We could have done this initially, but why touch the memory
+     allocator unless we're sure we have to?
+   */
+  if(w) {
+    if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
+      return res;
+
+    DIGIT(a, ix) = w;  /* pa may not be valid after s_mp_pad() call */
+  }
+
+  return MP_OKAY;
+
+} /* end s_mp_add() */
+
+/* }}} */
+
+/* {{{ s_mp_sub(a, b) */
+
+/* Compute a = |a| - |b|, assumes |a| >= |b|                              */
+mp_err   s_mp_sub(mp_int *a, mp_int *b)        /* magnitude subtract      */
+{
+  mp_word   w = 0;
+  mp_digit *pa, *pb;
+  mp_size   ix, used = USED(b);
+
+  /*
+    Subtract and propagate borrow.  Up to the precision of b, this
+    accounts for the digits of b; after that, we just make sure the
+    carries get to the right place.  This saves having to pad b out to
+    the precision of a just to make the loops work right...
+   */
+  pa = DIGITS(a);
+  pb = DIGITS(b);
+
+  for(ix = 0; ix < used; ++ix) {
+    w = (RADIX + *pa) - w - *pb++;
+    *pa++ = ACCUM(w);
+    w = CARRYOUT(w) ? 0 : 1;
+  }
+
+  used = USED(a);
+  while(ix < used) {
+    w = RADIX + *pa - w;
+    *pa++ = ACCUM(w);
+    w = CARRYOUT(w) ? 0 : 1;
+    ++ix;
+  }
+
+  /* Clobber any leading zeroes we created    */
+  s_mp_clamp(a);
+
+  /* 
+     If there was a borrow out, then |b| > |a| in violation
+     of our input invariant.  We've already done the work,
+     but we'll at least complain about it...
+   */
+  if(w)
+    return MP_RANGE;
+  else
+    return MP_OKAY;
+
+} /* end s_mp_sub() */
+
+/* }}} */
+
+mp_err   s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu)
+{
+  mp_int   q;
+  mp_err   res;
+  mp_size  um = USED(m);
+
+  if((res = mp_init_copy(&q, x)) != MP_OKAY)
+    return res;
+
+  s_mp_rshd(&q, um - 1);       /* q1 = x / b^(k-1)  */
+  s_mp_mul(&q, mu);            /* q2 = q1 * mu      */
+  s_mp_rshd(&q, um + 1);       /* q3 = q2 / b^(k+1) */
+
+  /* x = x mod b^(k+1), quick (no division) */
+  s_mp_mod_2d(x, (mp_digit)(DIGIT_BIT * (um + 1)));
+
+  /* q = q * m mod b^(k+1), quick (no division), uses the short multiplier */
+#ifndef SHRT_MUL
+  s_mp_mul(&q, m);
+  s_mp_mod_2d(&q, (mp_digit)(DIGIT_BIT * (um + 1)));
+#else
+  s_mp_mul_dig(&q, m, um + 1);
+#endif  
+
+  /* x = x - q */
+  if((res = mp_sub(x, &q, x)) != MP_OKAY)
+    goto CLEANUP;
+
+  /* If x < 0, add b^(k+1) to it */
+  if(mp_cmp_z(x) < 0) {
+    mp_set(&q, 1);
+    if((res = s_mp_lshd(&q, um + 1)) != MP_OKAY)
+      goto CLEANUP;
+    if((res = mp_add(x, &q, x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  /* Back off if it's too big */
+  while(mp_cmp(x, m) >= 0) {
+    if((res = s_mp_sub(x, m)) != MP_OKAY)
+      break;
+  }
+
+ CLEANUP:
+  mp_clear(&q);
+
+  return res;
+
+} /* end s_mp_reduce() */
+
+
+
+/* {{{ s_mp_mul(a, b) */
+
+/* Compute a = |a| * |b|                                                  */
+mp_err   s_mp_mul(mp_int *a, mp_int *b)
+{
+  mp_word   w, k = 0;
+  mp_int    tmp;
+  mp_err    res;
+  mp_size   ix, jx, ua = USED(a), ub = USED(b);
+  mp_digit *pa, *pb, *pt, *pbt;
+
+  if((res = mp_init_size(&tmp, ua + ub)) != MP_OKAY)
+    return res;
+
+  /* This has the effect of left-padding with zeroes... */
+  USED(&tmp) = ua + ub;
+
+  /* We're going to need the base value each iteration */
+  pbt = DIGITS(&tmp);
+
+  /* Outer loop:  Digits of b */
+
+  pb = DIGITS(b);
+  for(ix = 0; ix < ub; ++ix, ++pb) {
+    if(*pb == 0) 
+      continue;
+
+    /* Inner product:  Digits of a */
+    pa = DIGITS(a);
+    for(jx = 0; jx < ua; ++jx, ++pa) {
+      pt = pbt + ix + jx;
+      w = *pb * *pa + k + *pt;
+      *pt = ACCUM(w);
+      k = CARRYOUT(w);
+    }
+
+    pbt[ix + jx] = k;
+    k = 0;
+  }
+
+  s_mp_clamp(&tmp);
+  s_mp_exch(&tmp, a);
+
+  mp_clear(&tmp);
+
+  return MP_OKAY;
+
+} /* end s_mp_mul() */
+
+/* }}} */
+
+/* {{{ s_mp_kmul(a, b, out, len) */
+
+#if 0
+void   s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len)
+{
+  mp_word   w, k = 0;
+  mp_size   ix, jx;
+  mp_digit *pa, *pt;
+
+  for(ix = 0; ix < len; ++ix, ++b) {
+    if(*b == 0)
+      continue;
+    
+    pa = a;
+    for(jx = 0; jx < len; ++jx, ++pa) {
+      pt = out + ix + jx;
+      w = *b * *pa + k + *pt;
+      *pt = ACCUM(w);
+      k = CARRYOUT(w);
+    }
+
+    out[ix + jx] = k;
+    k = 0;
+  }
+
+} /* end s_mp_kmul() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_sqr(a) */
+
+/*
+  Computes the square of a, in place.  This can be done more
+  efficiently than a general multiplication, because many of the
+  computation steps are redundant when squaring.  The inner product
+  step is a bit more complicated, but we save a fair number of
+  iterations of the multiplication loop.
+ */
+#if MP_SQUARE
+mp_err   s_mp_sqr(mp_int *a)
+{
+  mp_word  w, k = 0;
+  mp_int   tmp;
+  mp_err   res;
+  mp_size  ix, jx, kx, used = USED(a);
+  mp_digit *pa1, *pa2, *pt, *pbt;
+
+  if((res = mp_init_size(&tmp, 2 * used)) != MP_OKAY)
+    return res;
+
+  /* Left-pad with zeroes */
+  USED(&tmp) = 2 * used;
+
+  /* We need the base value each time through the loop */
+  pbt = DIGITS(&tmp);
+
+  pa1 = DIGITS(a);
+  for(ix = 0; ix < used; ++ix, ++pa1) {
+    if(*pa1 == 0)
+      continue;
+
+    w = DIGIT(&tmp, ix + ix) + (*pa1 * *pa1);
+
+    pbt[ix + ix] = ACCUM(w);
+    k = CARRYOUT(w);
+
+    /*
+      The inner product is computed as:
+
+         (C, S) = t[i,j] + 2 a[i] a[j] + C
+
+      This can overflow what can be represented in an mp_word, and
+      since C arithmetic does not provide any way to check for
+      overflow, we have to check explicitly for overflow conditions
+      before they happen.
+     */
+    for(jx = ix + 1, pa2 = DIGITS(a) + jx; jx < used; ++jx, ++pa2) {
+      mp_word  u = 0, v;
+      
+      /* Store this in a temporary to avoid indirections later */
+      pt = pbt + ix + jx;
+
+      /* Compute the multiplicative step */
+      w = *pa1 * *pa2;
+
+      /* If w is more than half MP_WORD_MAX, the doubling will
+        overflow, and we need to record a carry out into the next
+        word */
+      u = (w >> (MP_WORD_BIT - 1)) & 1;
+
+      /* Double what we've got, overflow will be ignored as defined
+        for C arithmetic (we've already noted if it is to occur)
+       */
+      w *= 2;
+
+      /* Compute the additive step */
+      v = *pt + k;
+
+      /* If we do not already have an overflow carry, check to see
+        if the addition will cause one, and set the carry out if so 
+       */
+      u |= ((MP_WORD_MAX - v) < w);
+
+      /* Add in the rest, again ignoring overflow */
+      w += v;
+
+      /* Set the i,j digit of the output */
+      *pt = ACCUM(w);
+
+      /* Save carry information for the next iteration of the loop.
+        This is why k must be an mp_word, instead of an mp_digit */
+      k = CARRYOUT(w) | (u << DIGIT_BIT);
+
+    } /* for(jx ...) */
+
+    /* Set the last digit in the cycle and reset the carry */
+    k = DIGIT(&tmp, ix + jx) + k;
+    pbt[ix + jx] = ACCUM(k);
+    k = CARRYOUT(k);
+
+    /* If we are carrying out, propagate the carry to the next digit
+       in the output.  This may cascade, so we have to be somewhat
+       circumspect -- but we will have enough precision in the output
+       that we won't overflow 
+     */
+    kx = 1;
+    while(k) {
+      k = pbt[ix + jx + kx] + 1;
+      pbt[ix + jx + kx] = ACCUM(k);
+      k = CARRYOUT(k);
+      ++kx;
+    }
+  } /* for(ix ...) */
+
+  s_mp_clamp(&tmp);
+  s_mp_exch(&tmp, a);
+
+  mp_clear(&tmp);
+
+  return MP_OKAY;
+
+} /* end s_mp_sqr() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_div(a, b) */
+
+/*
+  s_mp_div(a, b)
+
+  Compute a = a / b and b = a mod b.  Assumes b > a.
+ */
+
+mp_err   s_mp_div(mp_int *a, mp_int *b)
+{
+  mp_int   quot, rem, t;
+  mp_word  q;
+  mp_err   res;
+  mp_digit d;
+  int      ix;
+
+  if(mp_cmp_z(b) == 0)
+    return MP_RANGE;
+
+  /* Shortcut if b is power of two */
+  if((ix = s_mp_ispow2(b)) >= 0) {
+    mp_copy(a, b);  /* need this for remainder */
+    s_mp_div_2d(a, (mp_digit)ix);
+    s_mp_mod_2d(b, (mp_digit)ix);
+
+    return MP_OKAY;
+  }
+
+  /* Allocate space to store the quotient */
+  if((res = mp_init_size(&quot, USED(a))) != MP_OKAY)
+    return res;
+
+  /* A working temporary for division     */
+  if((res = mp_init_size(&t, USED(a))) != MP_OKAY)
+    goto T;
+
+  /* Allocate space for the remainder     */
+  if((res = mp_init_size(&rem, USED(a))) != MP_OKAY)
+    goto REM;
+
+  /* Normalize to optimize guessing       */
+  d = s_mp_norm(a, b);
+
+  /* Perform the division itself...woo!   */
+  ix = USED(a) - 1;
+
+  while(ix >= 0) {
+    /* Find a partial substring of a which is at least b */
+    while(s_mp_cmp(&rem, b) < 0 && ix >= 0) {
+      if((res = s_mp_lshd(&rem, 1)) != MP_OKAY) 
+       goto CLEANUP;
+
+      if((res = s_mp_lshd(&quot, 1)) != MP_OKAY)
+       goto CLEANUP;
+
+      DIGIT(&rem, 0) = DIGIT(a, ix);
+      s_mp_clamp(&rem);
+      --ix;
+    }
+
+    /* If we didn't find one, we're finished dividing    */
+    if(s_mp_cmp(&rem, b) < 0) 
+      break;    
+
+    /* Compute a guess for the next quotient digit       */
+    q = DIGIT(&rem, USED(&rem) - 1);
+    if(q <= DIGIT(b, USED(b) - 1) && USED(&rem) > 1)
+      q = (q << DIGIT_BIT) | DIGIT(&rem, USED(&rem) - 2);
+
+    q /= DIGIT(b, USED(b) - 1);
+
+    /* The guess can be as much as RADIX + 1 */
+    if(q >= RADIX)
+      q = RADIX - 1;
+
+    /* See what that multiplies out to                   */
+    mp_copy(b, &t);
+    if((res = s_mp_mul_d(&t, q)) != MP_OKAY)
+      goto CLEANUP;
+
+    /* 
+       If it's too big, back it off.  We should not have to do this
+       more than once, or, in rare cases, twice.  Knuth describes a
+       method by which this could be reduced to a maximum of once, but
+       I didn't implement that here.
+     */
+    while(s_mp_cmp(&t, &rem) > 0) {
+      --q;
+      s_mp_sub(&t, b);
+    }
+
+    /* At this point, q should be the right next digit   */
+    if((res = s_mp_sub(&rem, &t)) != MP_OKAY)
+      goto CLEANUP;
+
+    /*
+      Include the digit in the quotient.  We allocated enough memory
+      for any quotient we could ever possibly get, so we should not
+      have to check for failures here
+     */
+    DIGIT(&quot, 0) = q;
+  }
+
+  /* Denormalize remainder                */
+  if(d != 0) 
+    s_mp_div_2d(&rem, d);
+
+  s_mp_clamp(&quot);
+  s_mp_clamp(&rem);
+
+  /* Copy quotient back to output         */
+  s_mp_exch(&quot, a);
+  
+  /* Copy remainder back to output        */
+  s_mp_exch(&rem, b);
+
+CLEANUP:
+  mp_clear(&rem);
+REM:
+  mp_clear(&t);
+T:
+  mp_clear(&quot);
+
+  return res;
+
+} /* end s_mp_div() */
+
+/* }}} */
+
+/* {{{ s_mp_2expt(a, k) */
+
+mp_err   s_mp_2expt(mp_int *a, mp_digit k)
+{
+  mp_err    res;
+  mp_size   dig, bit;
+
+  dig = k / DIGIT_BIT;
+  bit = k % DIGIT_BIT;
+
+  mp_zero(a);
+  if((res = s_mp_pad(a, dig + 1)) != MP_OKAY)
+    return res;
+  
+  DIGIT(a, dig) |= (1 << bit);
+
+  return MP_OKAY;
+
+} /* end s_mp_2expt() */
+
+/* }}} */
+
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive comparisons */
+
+/* {{{ s_mp_cmp(a, b) */
+
+/* Compare |a| <=> |b|, return 0 if equal, <0 if a<b, >0 if a>b           */
+int      s_mp_cmp(mp_int *a, mp_int *b)
+{
+  mp_size   ua = USED(a), ub = USED(b);
+
+  if(ua > ub)
+    return MP_GT;
+  else if(ua < ub)
+    return MP_LT;
+  else {
+    int      ix = ua - 1;
+    mp_digit *ap = DIGITS(a) + ix, *bp = DIGITS(b) + ix;
+
+    while(ix >= 0) {
+      if(*ap > *bp)
+       return MP_GT;
+      else if(*ap < *bp)
+       return MP_LT;
+
+      --ap; --bp; --ix;
+    }
+
+    return MP_EQ;
+  }
+
+} /* end s_mp_cmp() */
+
+/* }}} */
+
+/* {{{ s_mp_cmp_d(a, d) */
+
+/* Compare |a| <=> d, return 0 if equal, <0 if a<d, >0 if a>d             */
+int      s_mp_cmp_d(mp_int *a, mp_digit d)
+{
+  mp_size  ua = USED(a);
+  mp_digit *ap = DIGITS(a);
+
+  if(ua > 1)
+    return MP_GT;
+
+  if(*ap < d) 
+    return MP_LT;
+  else if(*ap > d)
+    return MP_GT;
+  else
+    return MP_EQ;
+
+} /* end s_mp_cmp_d() */
+
+/* }}} */
+
+/* {{{ s_mp_ispow2(v) */
+
+/*
+  Returns -1 if the value is not a power of two; otherwise, it returns
+  k such that v = 2^k, i.e. lg(v).
+ */
+int      s_mp_ispow2(mp_int *v)
+{
+  mp_digit d, *dp;
+  mp_size  uv = USED(v);
+  int      extra = 0, ix;
+
+  d = DIGIT(v, uv - 1); /* most significant digit of v */
+
+  while(d && ((d & 1) == 0)) {
+    d >>= 1;
+    ++extra;
+  }
+
+  if(d == 1) {
+    ix = uv - 2;
+    dp = DIGITS(v) + ix;
+
+    while(ix >= 0) {
+      if(*dp)
+       return -1; /* not a power of two */
+
+      --dp; --ix;
+    }
+
+    return ((uv - 1) * DIGIT_BIT) + extra;
+  } 
+
+  return -1;
+
+} /* end s_mp_ispow2() */
+
+/* }}} */
+
+/* {{{ s_mp_ispow2d(d) */
+
+int      s_mp_ispow2d(mp_digit d)
+{
+  int   pow = 0;
+
+  while((d & 1) == 0) {
+    ++pow; d >>= 1;
+  }
+
+  if(d == 1)
+    return pow;
+
+  return -1;
+
+} /* end s_mp_ispow2d() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive I/O helpers */
+
+/* {{{ s_mp_tovalue(ch, r) */
+
+/*
+  Convert the given character to its digit value, in the given radix.
+  If the given character is not understood in the given radix, -1 is
+  returned.  Otherwise the digit's numeric value is returned.
+
+  The results will be odd if you use a radix < 2 or > 62, you are
+  expected to know what you're up to.
+ */
+int      s_mp_tovalue(char ch, int r)
+{
+  int    val, xch;
+  
+  if(r > 36)
+    xch = ch;
+  else
+    xch = toupper(ch);
+
+  if(isdigit(xch))
+    val = xch - '0';
+  else if(isupper(xch))
+    val = xch - 'A' + 10;
+  else if(islower(xch))
+    val = xch - 'a' + 36;
+  else if(xch == '+')
+    val = 62;
+  else if(xch == '/')
+    val = 63;
+  else 
+    return -1;
+
+  if(val < 0 || val >= r)
+    return -1;
+
+  return val;
+
+} /* end s_mp_tovalue() */
+
+/* }}} */
+
+/* {{{ s_mp_todigit(val, r, low) */
+
+/*
+  Convert val to a radix-r digit, if possible.  If val is out of range
+  for r, returns zero.  Otherwise, returns an ASCII character denoting
+  the value in the given radix.
+
+  The results may be odd if you use a radix < 2 or > 64, you are
+  expected to know what you're doing.
+ */
+  
+char     s_mp_todigit(int val, int r, int low)
+{
+  char   ch;
+
+  if(val < 0 || val >= r)
+    return 0;
+
+  ch = s_dmap_1[val];
+
+  if(r <= 36 && low)
+    ch = tolower(ch);
+
+  return ch;
+
+} /* end s_mp_todigit() */
+
+/* }}} */
+
+/* {{{ s_mp_outlen(bits, radix) */
+
+/* 
+   Return an estimate for how long a string is needed to hold a radix
+   r representation of a number with 'bits' significant bits.
+
+   Does not include space for a sign or a NUL terminator.
+ */
+int      s_mp_outlen(int bits, int r)
+{
+  return (int)((double)bits * LOG_V_2(r));
+
+} /* end s_mp_outlen() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* HERE THERE BE DRAGONS                                                  */
+/* crc==4242132123, version==2, Sat Feb 02 06:43:52 2002 */
+
+/* $Source: /cvs/libtom/libtommath/mtest/mpi.c,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/05/05 14:38:47 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.h b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.h
new file mode 100644 (file)
index 0000000..66ae873
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+    mpi.h
+
+    by Michael J. Fromberger <sting@linguist.dartmouth.edu>
+    Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
+
+    Arbitrary precision integer arithmetic library
+
+    $Id: mpi.h,v 1.2 2005/05/05 14:38:47 tom Exp $
+ */
+
+#ifndef _H_MPI_
+#define _H_MPI_
+
+#include "mpi-config.h"
+
+#define  MP_LT       -1
+#define  MP_EQ        0
+#define  MP_GT        1
+
+#if MP_DEBUG
+#undef MP_IOFUNC
+#define MP_IOFUNC 1
+#endif
+
+#if MP_IOFUNC
+#include <stdio.h>
+#include <ctype.h>
+#endif
+
+#include <limits.h>
+
+#define  MP_NEG  1
+#define  MP_ZPOS 0
+
+/* Included for compatibility... */
+#define  NEG     MP_NEG
+#define  ZPOS    MP_ZPOS
+
+#define  MP_OKAY          0 /* no error, all is well */
+#define  MP_YES           0 /* yes (boolean result)  */
+#define  MP_NO           -1 /* no (boolean result)   */
+#define  MP_MEM          -2 /* out of memory         */
+#define  MP_RANGE        -3 /* argument out of range */
+#define  MP_BADARG       -4 /* invalid parameter     */
+#define  MP_UNDEF        -5 /* answer is undefined   */
+#define  MP_LAST_CODE    MP_UNDEF
+
+#include "mpi-types.h"
+
+/* Included for compatibility... */
+#define DIGIT_BIT         MP_DIGIT_BIT
+#define DIGIT_MAX         MP_DIGIT_MAX
+
+/* Macros for accessing the mp_int internals           */
+#define  SIGN(MP)     ((MP)->sign)
+#define  USED(MP)     ((MP)->used)
+#define  ALLOC(MP)    ((MP)->alloc)
+#define  DIGITS(MP)   ((MP)->dp)
+#define  DIGIT(MP,N)  (MP)->dp[(N)]
+
+#if MP_ARGCHK == 1
+#define  ARGCHK(X,Y)  {if(!(X)){return (Y);}}
+#elif MP_ARGCHK == 2
+#include <assert.h>
+#define  ARGCHK(X,Y)  assert(X)
+#else
+#define  ARGCHK(X,Y)  /*  */
+#endif
+
+/* This defines the maximum I/O base (minimum is 2)   */
+#define MAX_RADIX         64
+
+typedef struct {
+  mp_sign       sign;    /* sign of this quantity      */
+  mp_size       alloc;   /* how many digits allocated  */
+  mp_size       used;    /* how many digits used       */
+  mp_digit     *dp;      /* the digits themselves      */
+} mp_int;
+
+/*------------------------------------------------------------------------*/
+/* Default precision                                                      */
+
+unsigned int mp_get_prec(void);
+void         mp_set_prec(unsigned int prec);
+
+/*------------------------------------------------------------------------*/
+/* Memory management                                                      */
+
+mp_err mp_init(mp_int *mp);
+mp_err mp_init_array(mp_int mp[], int count);
+mp_err mp_init_size(mp_int *mp, mp_size prec);
+mp_err mp_init_copy(mp_int *mp, mp_int *from);
+mp_err mp_copy(mp_int *from, mp_int *to);
+void   mp_exch(mp_int *mp1, mp_int *mp2);
+void   mp_clear(mp_int *mp);
+void   mp_clear_array(mp_int mp[], int count);
+void   mp_zero(mp_int *mp);
+void   mp_set(mp_int *mp, mp_digit d);
+mp_err mp_set_int(mp_int *mp, long z);
+mp_err mp_shrink(mp_int *a);
+
+
+/*------------------------------------------------------------------------*/
+/* Single digit arithmetic                                                */
+
+mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b);
+mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b);
+mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b);
+mp_err mp_mul_2(mp_int *a, mp_int *c);
+mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r);
+mp_err mp_div_2(mp_int *a, mp_int *c);
+mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c);
+
+/*------------------------------------------------------------------------*/
+/* Sign manipulations                                                     */
+
+mp_err mp_abs(mp_int *a, mp_int *b);
+mp_err mp_neg(mp_int *a, mp_int *b);
+
+/*------------------------------------------------------------------------*/
+/* Full arithmetic                                                        */
+
+mp_err mp_add(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_mul_2d(mp_int *a, mp_digit d, mp_int *c);
+#if MP_SQUARE
+mp_err mp_sqr(mp_int *a, mp_int *b);
+#else
+#define mp_sqr(a, b) mp_mul(a, a, b)
+#endif
+mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r);
+mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r);
+mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_2expt(mp_int *a, mp_digit k);
+mp_err mp_sqrt(mp_int *a, mp_int *b);
+
+/*------------------------------------------------------------------------*/
+/* Modular arithmetic                                                     */
+
+#if MP_MODARITH
+mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c);
+mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c);
+mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
+mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
+mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
+#if MP_SQUARE
+mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c);
+#else
+#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
+#endif
+mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
+mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c);
+#endif /* MP_MODARITH */
+
+/*------------------------------------------------------------------------*/
+/* Comparisons                                                            */
+
+int    mp_cmp_z(mp_int *a);
+int    mp_cmp_d(mp_int *a, mp_digit d);
+int    mp_cmp(mp_int *a, mp_int *b);
+int    mp_cmp_mag(mp_int *a, mp_int *b);
+int    mp_cmp_int(mp_int *a, long z);
+int    mp_isodd(mp_int *a);
+int    mp_iseven(mp_int *a);
+
+/*------------------------------------------------------------------------*/
+/* Number theoretic                                                       */
+
+#if MP_NUMTH
+mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y);
+mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c);
+#endif /* end MP_NUMTH */
+
+/*------------------------------------------------------------------------*/
+/* Input and output                                                       */
+
+#if MP_IOFUNC
+void   mp_print(mp_int *mp, FILE *ofp);
+#endif /* end MP_IOFUNC */
+
+/*------------------------------------------------------------------------*/
+/* Base conversion                                                        */
+
+#define BITS     1
+#define BYTES    CHAR_BIT
+
+mp_err mp_read_signed_bin(mp_int *mp, unsigned char *str, int len);
+int    mp_signed_bin_size(mp_int *mp);
+mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str);
+
+mp_err mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len);
+int    mp_unsigned_bin_size(mp_int *mp);
+mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str);
+
+int    mp_count_bits(mp_int *mp);
+
+#if MP_COMPAT_MACROS
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp)           mp_signed_bin_size(mp)
+#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))
+#endif
+
+mp_err mp_read_radix(mp_int *mp, unsigned char *str, int radix);
+int    mp_radix_size(mp_int *mp, int radix);
+int    mp_value_radix_size(int num, int qty, int radix);
+mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix);
+
+int    mp_char2value(char ch, int r);
+
+#define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S)     mp_toradix((M), (S), 16)
+
+/*------------------------------------------------------------------------*/
+/* Error strings                                                          */
+
+const  char  *mp_strerror(mp_err ec);
+
+#endif /* end _H_MPI_ */
+
+/* $Source: /cvs/libtom/libtommath/mtest/mpi.h,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/05/05 14:38:47 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/mtest/mtest.c b/source4/heimdal/lib/hcrypto/libtommath/mtest/mtest.c
new file mode 100644 (file)
index 0000000..bdfe612
--- /dev/null
@@ -0,0 +1,308 @@
+/* makes a bignum test harness with NUM tests per operation
+ *
+ * the output is made in the following format [one parameter per line]
+
+operation
+operand1
+operand2
+[... operandN]
+result1
+result2
+[... resultN]
+
+So for example "a * b mod n" would be
+
+mulmod
+a
+b
+n
+a*b mod n
+
+e.g. if a=3, b=4 n=11 then
+
+mulmod
+3
+4
+11
+1
+
+ */
+
+#ifdef MP_8BIT
+#define THE_MASK 127
+#else
+#define THE_MASK 32767
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "mpi.c"
+
+FILE *rng;
+
+void rand_num(mp_int *a)
+{
+   int n, size;
+   unsigned char buf[2048];
+
+   size = 1 + ((fgetc(rng)<<8) + fgetc(rng)) % 101;
+   buf[0] = (fgetc(rng)&1)?1:0;
+   fread(buf+1, 1, size, rng);
+   while (buf[1] == 0) buf[1] = fgetc(rng);
+   mp_read_raw(a, buf, 1+size);
+}
+
+void rand_num2(mp_int *a)
+{
+   int n, size;
+   unsigned char buf[2048];
+
+   size = 10 + ((fgetc(rng)<<8) + fgetc(rng)) % 101;
+   buf[0] = (fgetc(rng)&1)?1:0;
+   fread(buf+1, 1, size, rng);
+   while (buf[1] == 0) buf[1] = fgetc(rng);
+   mp_read_raw(a, buf, 1+size);
+}
+
+#define mp_to64(a, b) mp_toradix(a, b, 64)
+
+int main(void)
+{
+   int n, tmp;
+   mp_int a, b, c, d, e;
+   clock_t t1;
+   char buf[4096];
+
+   mp_init(&a);
+   mp_init(&b);
+   mp_init(&c);
+   mp_init(&d);
+   mp_init(&e);
+
+
+   /* initial (2^n - 1)^2 testing, makes sure the comba multiplier works [it has the new carry code] */
+/*
+   mp_set(&a, 1);
+   for (n = 1; n < 8192; n++) {
+       mp_mul(&a, &a, &c);
+       printf("mul\n");
+       mp_to64(&a, buf);
+       printf("%s\n%s\n", buf, buf);
+       mp_to64(&c, buf);
+       printf("%s\n", buf);
+
+       mp_add_d(&a, 1, &a);
+       mp_mul_2(&a, &a);
+       mp_sub_d(&a, 1, &a);
+   }
+*/
+
+   rng = fopen("/dev/urandom", "rb");
+   if (rng == NULL) {
+      rng = fopen("/dev/random", "rb");
+      if (rng == NULL) {
+         fprintf(stderr, "\nWarning:  stdin used as random source\n\n");
+         rng = stdin;
+      }
+   }
+
+   t1 = clock();
+   for (;;) {
+#if 0
+      if (clock() - t1 > CLOCKS_PER_SEC) {
+         sleep(2);
+         t1 = clock();
+      }
+#endif
+       n = fgetc(rng) % 15;
+
+   if (n == 0) {
+       /* add tests */
+       rand_num(&a);
+       rand_num(&b);
+       mp_add(&a, &b, &c);
+       printf("add\n");
+       mp_to64(&a, buf);
+       printf("%s\n", buf);
+       mp_to64(&b, buf);
+       printf("%s\n", buf);
+       mp_to64(&c, buf);
+       printf("%s\n", buf);
+   } else if (n == 1) {
+      /* sub tests */
+       rand_num(&a);
+       rand_num(&b);
+       mp_sub(&a, &b, &c);
+       printf("sub\n");
+       mp_to64(&a, buf);
+       printf("%s\n", buf);
+       mp_to64(&b, buf);
+       printf("%s\n", buf);
+       mp_to64(&c, buf);
+       printf("%s\n", buf);
+   } else if (n == 2) {
+       /* mul tests */
+       rand_num(&a);
+       rand_num(&b);
+       mp_mul(&a, &b, &c);
+       printf("mul\n");
+       mp_to64(&a, buf);
+       printf("%s\n", buf);
+       mp_to64(&b, buf);
+       printf("%s\n", buf);
+       mp_to64(&c, buf);
+       printf("%s\n", buf);
+   } else if (n == 3) {
+      /* div tests */
+       rand_num(&a);
+       rand_num(&b);
+       mp_div(&a, &b, &c, &d);
+       printf("div\n");
+       mp_to64(&a, buf);
+       printf("%s\n", buf);
+       mp_to64(&b, buf);
+       printf("%s\n", buf);
+       mp_to64(&c, buf);
+       printf("%s\n", buf);
+       mp_to64(&d, buf);
+       printf("%s\n", buf);
+   } else if (n == 4) {
+      /* sqr tests */
+       rand_num(&a);
+       mp_sqr(&a, &b);
+       printf("sqr\n");
+       mp_to64(&a, buf);
+       printf("%s\n", buf);
+       mp_to64(&b, buf);
+       printf("%s\n", buf);
+   } else if (n == 5) {
+      /* mul_2d test */
+      rand_num(&a);
+      mp_copy(&a, &b);
+      n = fgetc(rng) & 63;
+      mp_mul_2d(&b, n, &b);
+      mp_to64(&a, buf);
+      printf("mul2d\n");
+      printf("%s\n", buf);
+      printf("%d\n", n);
+      mp_to64(&b, buf);
+      printf("%s\n", buf);
+   } else if (n == 6) {
+      /* div_2d test */
+      rand_num(&a);
+      mp_copy(&a, &b);
+      n = fgetc(rng) & 63;
+      mp_div_2d(&b, n, &b, NULL);
+      mp_to64(&a, buf);
+      printf("div2d\n");
+      printf("%s\n", buf);
+      printf("%d\n", n);
+      mp_to64(&b, buf);
+      printf("%s\n", buf);
+   } else if (n == 7) {
+      /* gcd test */
+      rand_num(&a);
+      rand_num(&b);
+      a.sign = MP_ZPOS;
+      b.sign = MP_ZPOS;
+      mp_gcd(&a, &b, &c);
+      printf("gcd\n");
+      mp_to64(&a, buf);
+      printf("%s\n", buf);
+      mp_to64(&b, buf);
+      printf("%s\n", buf);
+      mp_to64(&c, buf);
+      printf("%s\n", buf);
+   } else if (n == 8) {
+      /* lcm test */
+      rand_num(&a);
+      rand_num(&b);
+      a.sign = MP_ZPOS;
+      b.sign = MP_ZPOS;
+      mp_lcm(&a, &b, &c);
+      printf("lcm\n");
+      mp_to64(&a, buf);
+      printf("%s\n", buf);
+      mp_to64(&b, buf);
+      printf("%s\n", buf);
+      mp_to64(&c, buf);
+      printf("%s\n", buf);
+   } else if (n == 9) {
+      /* exptmod test */
+      rand_num2(&a);
+      rand_num2(&b);
+      rand_num2(&c);
+//      if (c.dp[0]&1) mp_add_d(&c, 1, &c);
+      a.sign = b.sign = c.sign = 0;
+      mp_exptmod(&a, &b, &c, &d);
+      printf("expt\n");
+      mp_to64(&a, buf);
+      printf("%s\n", buf);
+      mp_to64(&b, buf);
+      printf("%s\n", buf);
+      mp_to64(&c, buf);
+      printf("%s\n", buf);
+      mp_to64(&d, buf);
+      printf("%s\n", buf);
+   } else if (n == 10) {
+      /* invmod test */
+      rand_num2(&a);
+      rand_num2(&b);
+      b.sign = MP_ZPOS;
+      a.sign = MP_ZPOS;
+      mp_gcd(&a, &b, &c);
+      if (mp_cmp_d(&c, 1) != 0) continue;
+      if (mp_cmp_d(&b, 1) == 0) continue;
+      mp_invmod(&a, &b, &c);
+      printf("invmod\n");
+      mp_to64(&a, buf);
+      printf("%s\n", buf);
+      mp_to64(&b, buf);
+      printf("%s\n", buf);
+      mp_to64(&c, buf);
+      printf("%s\n", buf);
+   } else if (n == 11) {
+      rand_num(&a);
+      mp_mul_2(&a, &a);
+      mp_div_2(&a, &b);
+      printf("div2\n");
+      mp_to64(&a, buf);
+      printf("%s\n", buf);
+      mp_to64(&b, buf);
+      printf("%s\n", buf);
+   } else if (n == 12) {
+      rand_num2(&a);
+      mp_mul_2(&a, &b);
+      printf("mul2\n");
+      mp_to64(&a, buf);
+      printf("%s\n", buf);
+      mp_to64(&b, buf);
+      printf("%s\n", buf);
+   } else if (n == 13) {
+      rand_num2(&a);
+      tmp = abs(rand()) & THE_MASK;
+      mp_add_d(&a, tmp, &b);
+      printf("add_d\n");
+      mp_to64(&a, buf);
+      printf("%s\n%d\n", buf, tmp);
+      mp_to64(&b, buf);
+      printf("%s\n", buf);
+   } else if (n == 14) {
+      rand_num2(&a);
+      tmp = abs(rand()) & THE_MASK;
+      mp_sub_d(&a, tmp, &b);
+      printf("sub_d\n");
+      mp_to64(&a, buf);
+      printf("%s\n%d\n", buf, tmp);
+      mp_to64(&b, buf);
+      printf("%s\n", buf);
+   }
+   }
+   fclose(rng);
+   return 0;
+}
+
+/* $Source: /cvs/libtom/libtommath/mtest/mtest.c,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/05/05 14:38:47 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/design_process.sxd b/source4/heimdal/lib/hcrypto/libtommath/pics/design_process.sxd
new file mode 100644 (file)
index 0000000..7414dbb
Binary files /dev/null and b/source4/heimdal/lib/hcrypto/libtommath/pics/design_process.sxd differ
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/design_process.tif b/source4/heimdal/lib/hcrypto/libtommath/pics/design_process.tif
new file mode 100644 (file)
index 0000000..4a0c012
Binary files /dev/null and b/source4/heimdal/lib/hcrypto/libtommath/pics/design_process.tif differ
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.sxd b/source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.sxd
new file mode 100644 (file)
index 0000000..6518404
Binary files /dev/null and b/source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.sxd differ
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.tif b/source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.tif
new file mode 100644 (file)
index 0000000..cb06e8e
Binary files /dev/null and b/source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.tif differ
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/makefile b/source4/heimdal/lib/hcrypto/libtommath/pics/makefile
new file mode 100644 (file)
index 0000000..3ecb02f
--- /dev/null
@@ -0,0 +1,35 @@
+# makes the images... yeah
+
+default:  pses
+
+design_process.ps: design_process.tif
+       tiff2ps -s -e design_process.tif > design_process.ps
+
+sliding_window.ps: sliding_window.tif
+       tiff2ps -s -e sliding_window.tif > sliding_window.ps
+       
+expt_state.ps: expt_state.tif
+       tiff2ps -s -e expt_state.tif > expt_state.ps
+
+primality.ps: primality.tif
+       tiff2ps -s -e primality.tif > primality.ps
+
+design_process.pdf: design_process.ps
+       epstopdf design_process.ps
+
+sliding_window.pdf: sliding_window.ps
+       epstopdf sliding_window.ps
+       
+expt_state.pdf: expt_state.ps
+       epstopdf expt_state.ps
+
+primality.pdf: primality.ps
+       epstopdf primality.ps
+
+
+pses: sliding_window.ps expt_state.ps primality.ps design_process.ps
+pdfes: sliding_window.pdf expt_state.pdf primality.pdf design_process.pdf
+
+clean:
+       rm -rf *.ps *.pdf .xvpics
+   
\ No newline at end of file
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/primality.tif b/source4/heimdal/lib/hcrypto/libtommath/pics/primality.tif
new file mode 100644 (file)
index 0000000..76d6be3
Binary files /dev/null and b/source4/heimdal/lib/hcrypto/libtommath/pics/primality.tif differ
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/radix.sxd b/source4/heimdal/lib/hcrypto/libtommath/pics/radix.sxd
new file mode 100644 (file)
index 0000000..b9eb9a0
Binary files /dev/null and b/source4/heimdal/lib/hcrypto/libtommath/pics/radix.sxd differ
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.sxd b/source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.sxd
new file mode 100644 (file)
index 0000000..91e7c0d
Binary files /dev/null and b/source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.sxd differ
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.tif b/source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.tif
new file mode 100644 (file)
index 0000000..bb4cb96
Binary files /dev/null and b/source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.tif differ
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pretty.build b/source4/heimdal/lib/hcrypto/libtommath/pretty.build
new file mode 100644 (file)
index 0000000..a708b8a
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/perl -w
+#
+# Cute little builder for perl 
+# Total waste of development time...
+#
+# This will build all the object files and then the archive .a file
+# requires GCC, GNU make and a sense of humour.
+#
+# Tom St Denis
+use strict;
+
+my $count = 0;
+my $starttime = time;
+my $rate  = 0;
+print "Scanning for source files...\n";
+foreach my $filename (glob "*.c") {
+       ++$count;
+}
+print "Source files to build: $count\nBuilding...\n";
+my $i = 0;
+my $lines = 0;
+my $filesbuilt = 0;
+foreach my $filename (glob "*.c") {
+       printf("Building %3.2f%%, ", (++$i/$count)*100.0);
+       if ($i % 4 == 0) { print "/, "; }
+       if ($i % 4 == 1) { print "-, "; }
+       if ($i % 4 == 2) { print "\\, "; }
+       if ($i % 4 == 3) { print "|, "; }
+       if ($rate > 0) {
+           my $tleft = ($count - $i) / $rate;
+           my $tsec  = $tleft%60;
+           my $tmin  = ($tleft/60)%60;
+           my $thour = ($tleft/3600)%60;
+           printf("%2d:%02d:%02d left, ", $thour, $tmin, $tsec);
+       }
+       my $cnt = ($i/$count)*30.0;
+       my $x   = 0;
+       print "[";
+       for (; $x < $cnt; $x++) { print "#"; }
+       for (; $x < 30; $x++)   { print " "; }
+       print "]\r";
+       my $tmp = $filename;
+       $tmp =~ s/\.c/".o"/ge;
+       if (open(SRC, "<$tmp")) {
+          close SRC;
+       } else {
+          !system("make $tmp > /dev/null 2>/dev/null") or die "\nERROR: Failed to make $tmp!!!\n";
+          open( SRC, "<$filename" ) or die "Couldn't open $filename for reading: $!";
+          ++$lines while (<SRC>);
+          close SRC or die "Error closing $filename after reading: $!";
+          ++$filesbuilt;
+       }      
+
+       # update timer 
+       if (time != $starttime) {
+          my $delay = time - $starttime;
+          $rate = $i/$delay;
+       }
+}
+
+# finish building the library 
+printf("\nFinished building source (%d seconds, %3.2f files per second).\n", time - $starttime, $rate);
+print "Compiled approximately $filesbuilt files and $lines lines of code.\n";
+print "Doing final make (building archive...)\n";
+!system("make > /dev/null 2>/dev/null") or die "\nERROR: Failed to perform last make command!!!\n";
+print "done.\n";
\ No newline at end of file
diff --git a/source4/heimdal/lib/hcrypto/libtommath/tombc/grammar.txt b/source4/heimdal/lib/hcrypto/libtommath/tombc/grammar.txt
new file mode 100644 (file)
index 0000000..a780e75
--- /dev/null
@@ -0,0 +1,35 @@
+program       := program statement | statement | empty
+statement     := { statement }                                                                              | 
+                 identifier = numexpression;                                                                | 
+                 identifier[numexpression] = numexpression;                                                 |
+                 function(expressionlist);                                                                  | 
+                 for (identifer = numexpression; numexpression; identifier = numexpression) { statement }   |
+                 while (numexpression) { statement }                                                        | 
+                 if (numexpresion) { statement } elif                                                       | 
+                 break;                                                                                     | 
+                 continue;                                                                                  
+                 
+elif          := else statement | empty
+function      := abs | countbits | exptmod | jacobi | print | isprime | nextprime | issquare | readinteger | exit
+expressionlist := expressionlist, expression | expression
+
+// LR(1) !!!?
+expression    := string | numexpression
+numexpression := cmpexpr && cmpexpr | cmpexpr \|\| cmpexpr | cmpexpr
+cmpexpr       := boolexpr  < boolexpr | boolexpr  > boolexpr | boolexpr == boolexpr | 
+                 boolexpr <= boolexpr | boolexpr >= boolexpr | boolexpr
+boolexpr      := shiftexpr & shiftexpr | shiftexpr ^ shiftexpr | shiftexpr \| shiftexpr | shiftexpr
+shiftexpr     := addsubexpr << addsubexpr | addsubexpr >> addsubexpr | addsubexpr
+addsubexpr    := mulexpr + mulexpr | mulexpr - mulexpr | mulexpr
+mulexpr       := expr * expr       | expr / expr | expr % expr | expr
+expr          := -nexpr | nexpr 
+nexpr         := integer | identifier | ( numexpression ) | identifier[numexpression] 
+
+identifier    := identifer digits | identifier alpha | alpha
+alpha         := a ... z | A ... Z
+integer       := hexnumber | digits 
+hexnumber     := 0xhexdigits
+hexdigits     := hexdigits hexdigit | hexdigit
+hexdigit      := 0 ... 9 | a ... f | A ... F
+digits        := digits digit | digit 
+digit         := 0 ... 9
diff --git a/source4/heimdal/lib/hcrypto/libtommath/tommath.h b/source4/heimdal/lib/hcrypto/libtommath/tommath.h
new file mode 100644 (file)
index 0000000..426207a
--- /dev/null
@@ -0,0 +1,592 @@
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
+ */
+#ifndef BN_H_
+#define BN_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include <tommath_class.h>
+
+#ifndef MIN
+   #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+   #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+
+/* C++ compilers don't like assigning void * to mp_digit * */
+#define  OPT_CAST(x)  (x *)
+
+#else
+
+/* C on the other hand doesn't care */
+#define  OPT_CAST(x)
+
+#endif
+
+
+/* detect 64-bit mode if possible */
+#if defined(__x86_64__) 
+   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
+      #define MP_64BIT
+   #endif
+#endif
+
+/* some default configurations.
+ *
+ * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
+ * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
+ *
+ * At the very least a mp_digit must be able to hold 7 bits
+ * [any size beyond that is ok provided it doesn't overflow the data type]
+ */
+#ifdef MP_8BIT
+   typedef unsigned char      mp_digit;
+   typedef unsigned short     mp_word;
+#elif defined(MP_16BIT)
+   typedef unsigned short     mp_digit;
+   typedef unsigned long      mp_word;
+#elif defined(MP_64BIT)
+   /* for GCC only on supported platforms */
+#ifndef CRYPT
+   typedef unsigned long long ulong64;
+   typedef signed long long   long64;
+#endif
+
+   typedef unsigned long      mp_digit;
+   typedef unsigned long      mp_word __attribute__ ((mode(TI)));
+
+   #define DIGIT_BIT          60
+#else
+   /* this is the default case, 28-bit digits */
+
+   /* this is to make porting into LibTomCrypt easier :-) */
+#ifndef CRYPT
+   #if defined(_MSC_VER) || defined(__BORLANDC__) 
+      typedef unsigned __int64   ulong64;
+      typedef signed __int64     long64;
+   #else
+      typedef unsigned long long ulong64;
+      typedef signed long long   long64;
+   #endif
+#endif
+
+   typedef unsigned long      mp_digit;
+   typedef ulong64            mp_word;
+
+#ifdef MP_31BIT   
+   /* this is an extension that uses 31-bit digits */
+   #define DIGIT_BIT          31
+#else
+   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
+   #define DIGIT_BIT          28
+   #define MP_28BIT
+#endif   
+#endif
+
+/* define heap macros */
+#ifndef CRYPT
+   /* default to libc stuff */
+   #ifndef XMALLOC 
+       #define XMALLOC  malloc
+       #define XFREE    free
+       #define XREALLOC realloc
+       #define XCALLOC  calloc
+   #else
+      /* prototypes for our heap functions */
+      extern void *XMALLOC(size_t n);
+      extern void *XREALLOC(void *p, size_t n);
+      extern void *XCALLOC(size_t n, size_t s);
+      extern void XFREE(void *p);
+   #endif
+#endif
+
+
+/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
+#ifndef DIGIT_BIT
+   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
+#endif
+
+#define MP_DIGIT_BIT     DIGIT_BIT
+#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+#define MP_DIGIT_MAX     MP_MASK
+
+/* equalities */
+#define MP_LT        -1   /* less than */
+#define MP_EQ         0   /* equal to */
+#define MP_GT         1   /* greater than */
+
+#define MP_ZPOS       0   /* positive integer */
+#define MP_NEG        1   /* negative */
+
+#define MP_OKAY       0   /* ok result */
+#define MP_MEM        -2  /* out of mem */
+#define MP_VAL        -3  /* invalid input */
+#define MP_RANGE      MP_VAL
+
+#define MP_YES        1   /* yes response */
+#define MP_NO         0   /* no response */
+
+/* Primality generation flags */
+#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
+#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
+#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */
+
+typedef int           mp_err;
+
+/* you'll have to tune these... */
+extern int KARATSUBA_MUL_CUTOFF,
+           KARATSUBA_SQR_CUTOFF,
+           TOOM_MUL_CUTOFF,
+           TOOM_SQR_CUTOFF;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+/* #define MP_LOW_MEM */
+
+/* default precision */
+#ifndef MP_PREC
+   #ifndef MP_LOW_MEM
+      #define MP_PREC                 32     /* default digits of precision */
+   #else
+      #define MP_PREC                 8      /* default digits of precision */
+   #endif   
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct  {
+    int used, alloc, sign;
+    mp_digit *dp;
+} mp_int;
+
+/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+
+
+#define USED(m)    ((m)->used)
+#define DIGIT(m,k) ((m)->dp[(k)])
+#define SIGN(m)    ((m)->sign)
+
+/* error code to char* string */
+char *mp_error_to_string(int code);
+
+/* ---> init and deinit bignum functions <--- */
+/* init a bignum */
+int mp_init(mp_int *a);
+
+/* free a bignum */
+void mp_clear(mp_int *a);
+
+/* init a null terminated series of arguments */
+int mp_init_multi(mp_int *mp, ...);
+
+/* clear a null terminated series of arguments */
+void mp_clear_multi(mp_int *mp, ...);
+
+/* exchange two ints */
+void mp_exch(mp_int *a, mp_int *b);
+
+/* shrink ram required for a bignum */
+int mp_shrink(mp_int *a);
+
+/* grow an int to a given size */
+int mp_grow(mp_int *a, int size);
+
+/* init to a given number of digits */
+int mp_init_size(mp_int *a, int size);
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+#define mp_isneg(a)  (((a)->sign) ? MP_YES : MP_NO)
+
+/* set to zero */
+void mp_zero(mp_int *a);
+
+/* set to zero, multi */
+void mp_zero_multi(mp_int *a, ...);
+
+/* set to a digit */
+void mp_set(mp_int *a, mp_digit b);
+
+/* set a 32-bit const */
+int mp_set_int(mp_int *a, unsigned long b);
+
+/* get a 32-bit value */
+unsigned long mp_get_int(mp_int * a);
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b);
+
+/* initialize and set 32-bit value */
+int mp_init_set_int (mp_int * a, unsigned long b);
+
+/* copy, b = a */
+int mp_copy(mp_int *a, mp_int *b);
+
+/* inits and copies, a = b */
+int mp_init_copy(mp_int *a, mp_int *b);
+
+/* trim unused digits */
+void mp_clamp(mp_int *a);
+
+/* ---> digit manipulation <--- */
+
+/* right shift by "b" digits */
+void mp_rshd(mp_int *a, int b);
+
+/* left shift by "b" digits */
+int mp_lshd(mp_int *a, int b);
+
+/* c = a / 2**b */
+int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
+
+/* b = a/2 */
+int mp_div_2(mp_int *a, mp_int *b);
+
+/* c = a * 2**b */
+int mp_mul_2d(mp_int *a, int b, mp_int *c);
+
+/* b = a*2 */
+int mp_mul_2(mp_int *a, mp_int *b);
+
+/* c = a mod 2**d */
+int mp_mod_2d(mp_int *a, int b, mp_int *c);
+
+/* computes a = 2**b */
+int mp_2expt(mp_int *a, int b);
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a);
+
+/* I Love Earth! */
+
+/* makes a pseudo-random int of a given size */
+int mp_rand(mp_int *a, int digits);
+
+/* ---> binary operations <--- */
+/* c = a XOR b  */
+int mp_xor(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a OR b */
+int mp_or(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a AND b */
+int mp_and(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> Basic arithmetic <--- */
+
+/* b = -a */
+int mp_neg(mp_int *a, mp_int *b);
+
+/* b = |a| */
+int mp_abs(mp_int *a, mp_int *b);
+
+/* compare a to b */
+int mp_cmp(mp_int *a, mp_int *b);
+
+/* compare |a| to |b| */
+int mp_cmp_mag(mp_int *a, mp_int *b);
+
+/* c = a + b */
+int mp_add(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a - b */
+int mp_sub(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a * b */
+int mp_mul(mp_int *a, mp_int *b, mp_int *c);
+
+/* b = a*a  */
+int mp_sqr(mp_int *a, mp_int *b);
+
+/* a/b => cb + d == a */
+int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a mod b, 0 <= c < b  */
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> single digit functions <--- */
+
+/* compare against a single digit */
+int mp_cmp_d(mp_int *a, mp_digit b);
+
+/* c = a + b */
+int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a - b */
+int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a * b */
+int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* a/b => cb + d == a */
+int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+
+/* a/3 => 3c + d == a */
+int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
+
+/* c = a**b */
+int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a mod b, 0 <= c < b  */
+int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
+
+/* ---> number theory <--- */
+
+/* d = a + b (mod c) */
+int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a - b (mod c) */
+int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a * b (mod c) */
+int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a * a (mod b) */
+int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = 1/a (mod b) */
+int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = (a, b) */
+int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+
+/* produces value such that U1*a + U2*b = U3 */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
+
+/* c = [a, b] or (a*b)/(a, b) */
+int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+
+/* finds one of the b'th root of a, such that |c|**b <= |a|
+ *
+ * returns error if a < 0 and b is even
+ */
+int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
+
+/* special sqrt algo */
+int mp_sqrt(mp_int *arg, mp_int *ret);
+
+/* is number a square? */
+int mp_is_square(mp_int *arg, int *ret);
+
+/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
+int mp_jacobi(mp_int *a, mp_int *n, int *c);
+
+/* used to setup the Barrett reduction for a given modulus b */
+int mp_reduce_setup(mp_int *a, mp_int *b);
+
+/* Barrett Reduction, computes a (mod b) with a precomputed value c
+ *
+ * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
+ * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
+ */
+int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
+
+/* setups the montgomery reduction */
+int mp_montgomery_setup(mp_int *a, mp_digit *mp);
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+
+/* returns 1 if a is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a);
+
+/* sets the value of "d" required for mp_dr_reduce */
+void mp_dr_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b using the Diminished Radix method */
+int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
+
+/* returns true if a can be reduced with mp_reduce_2k */
+int mp_reduce_is_2k(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+
+/* returns true if a can be reduced with mp_reduce_2k_l */
+int mp_reduce_is_2k_l(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+
+/* d = a**b (mod c) */
+int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* ---> Primes <--- */
+
+/* number of primes */
+#ifdef MP_8BIT
+   #define PRIME_SIZE      31
+#else
+   #define PRIME_SIZE      256
+#endif
+
+/* table of first PRIME_SIZE primes */
+extern const mp_digit ltm_prime_tab[];
+
+/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
+int mp_prime_is_divisible(mp_int *a, int *result);
+
+/* performs one Fermat test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
+
+/* performs one Miller-Rabin test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
+
+/* This gives [for a given bit size] the number of trials required
+ * such that Miller-Rabin gives a prob of failure lower than 2^-96 
+ */
+int mp_prime_rabin_miller_trials(int size);
+
+/* performs t rounds of Miller-Rabin on "a" using the first
+ * t prime bases.  Also performs an initial sieve of trial
+ * division.  Determines if "a" is prime with probability
+ * of error no more than (1/4)**t.
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime(mp_int *a, int t, int *result);
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
+
+/* makes a truly random prime of a given size (bytes),
+ * call with bbs = 1 if you want it to be congruent to 3 mod 4 
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ * The prime generated will be larger than 2^(8*size).
+ */
+#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ * 
+ *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
+ *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);
+
+int mp_find_prime(mp_int *a);
+
+int mp_isprime(mp_int *a);
+
+/* ---> radix conversion <--- */
+int mp_count_bits(mp_int *a);
+
+int mp_unsigned_bin_size(mp_int *a);
+int mp_read_unsigned_bin(mp_int *a, const unsigned char *b, int c);
+int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+
+int mp_signed_bin_size(mp_int *a);
+int mp_read_signed_bin(mp_int *a, const unsigned char *b, int c);
+int mp_to_signed_bin(mp_int *a,  unsigned char *b);
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+
+int mp_read_radix(mp_int *a, const char *str, int radix);
+int mp_toradix(mp_int *a, char *str, int radix);
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
+int mp_radix_size(mp_int *a, int radix, int *size);
+
+int mp_fread(mp_int *a, int radix, FILE *stream);
+int mp_fwrite(mp_int *a, int radix, FILE *stream);
+
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp)           mp_signed_bin_size(mp)
+#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))
+
+#define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S)     mp_toradix((M), (S), 16)
+
+/* lowlevel functions, do not call! */
+int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
+int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_sqr(mp_int *a, mp_int *b);
+int s_mp_sqr(mp_int *a, mp_int *b);
+int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_karatsuba_sqr(mp_int *a, mp_int *b);
+int mp_toom_sqr(mp_int *a, mp_int *b);
+int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
+int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int mode);
+void bn_reverse(unsigned char *s, int len);
+
+extern const char *mp_s_rmap;
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif
+
+
+/* $Source: /cvs/libtom/libtommath/tommath.h,v $ */
+/* $Revision: 1.8 $ */
+/* $Date: 2006/03/31 14:18:44 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/tommath_class.h b/source4/heimdal/lib/hcrypto/libtommath/tommath_class.h
new file mode 100644 (file)
index 0000000..fa95a02
--- /dev/null
@@ -0,0 +1,1000 @@
+#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
+#if defined(LTM2)
+#define LTM3
+#endif
+#if defined(LTM1)
+#define LTM2
+#endif
+#define LTM1
+
+#if defined(LTM_ALL)
+#define BN_ERROR_C
+#define BN_FAST_MP_INVMOD_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_FAST_S_MP_MUL_DIGS_C
+#define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+#define BN_FAST_S_MP_SQR_C
+#define BN_MP_2EXPT_C
+#define BN_MP_ABS_C
+#define BN_MP_ADD_C
+#define BN_MP_ADD_D_C
+#define BN_MP_ADDMOD_C
+#define BN_MP_AND_C
+#define BN_MP_CLAMP_C
+#define BN_MP_CLEAR_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_CMP_C
+#define BN_MP_CMP_D_C
+#define BN_MP_CMP_MAG_C
+#define BN_MP_CNT_LSB_C
+#define BN_MP_COPY_C
+#define BN_MP_COUNT_BITS_C
+#define BN_MP_DIV_C
+#define BN_MP_DIV_2_C
+#define BN_MP_DIV_2D_C
+#define BN_MP_DIV_3_C
+#define BN_MP_DIV_D_C
+#define BN_MP_DR_IS_MODULUS_C
+#define BN_MP_DR_REDUCE_C
+#define BN_MP_DR_SETUP_C
+#define BN_MP_EXCH_C
+#define BN_MP_EXPT_D_C
+#define BN_MP_EXPTMOD_C
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_EXTEUCLID_C
+#define BN_MP_FREAD_C
+#define BN_MP_FWRITE_C
+#define BN_MP_GCD_C
+#define BN_MP_GET_INT_C
+#define BN_MP_GROW_C
+#define BN_MP_INIT_C
+#define BN_MP_INIT_COPY_C
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_INIT_SET_C
+#define BN_MP_INIT_SET_INT_C
+#define BN_MP_INIT_SIZE_C
+#define BN_MP_INVMOD_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_MP_IS_SQUARE_C
+#define BN_MP_JACOBI_C
+#define BN_MP_KARATSUBA_MUL_C
+#define BN_MP_KARATSUBA_SQR_C
+#define BN_MP_LCM_C
+#define BN_MP_LSHD_C
+#define BN_MP_MOD_C
+#define BN_MP_MOD_2D_C
+#define BN_MP_MOD_D_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_MP_MUL_C
+#define BN_MP_MUL_2_C
+#define BN_MP_MUL_2D_C
+#define BN_MP_MUL_D_C
+#define BN_MP_MULMOD_C
+#define BN_MP_N_ROOT_C
+#define BN_MP_NEG_C
+#define BN_MP_OR_C
+#define BN_MP_PRIME_FERMAT_C
+#define BN_MP_PRIME_IS_DIVISIBLE_C
+#define BN_MP_PRIME_IS_PRIME_C
+#define BN_MP_PRIME_MILLER_RABIN_C
+#define BN_MP_PRIME_NEXT_PRIME_C
+#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+#define BN_MP_PRIME_RANDOM_EX_C
+#define BN_MP_RADIX_SIZE_C
+#define BN_MP_RADIX_SMAP_C
+#define BN_MP_RAND_C
+#define BN_MP_READ_RADIX_C
+#define BN_MP_READ_SIGNED_BIN_C
+#define BN_MP_READ_UNSIGNED_BIN_C
+#define BN_MP_REDUCE_C
+#define BN_MP_REDUCE_2K_C
+#define BN_MP_REDUCE_2K_L_C
+#define BN_MP_REDUCE_2K_SETUP_C
+#define BN_MP_REDUCE_2K_SETUP_L_C
+#define BN_MP_REDUCE_IS_2K_C
+#define BN_MP_REDUCE_IS_2K_L_C
+#define BN_MP_REDUCE_SETUP_C
+#define BN_MP_RSHD_C
+#define BN_MP_SET_C
+#define BN_MP_SET_INT_C
+#define BN_MP_SHRINK_C
+#define BN_MP_SIGNED_BIN_SIZE_C
+#define BN_MP_SQR_C
+#define BN_MP_SQRMOD_C
+#define BN_MP_SQRT_C
+#define BN_MP_SUB_C
+#define BN_MP_SUB_D_C
+#define BN_MP_SUBMOD_C
+#define BN_MP_TO_SIGNED_BIN_C
+#define BN_MP_TO_SIGNED_BIN_N_C
+#define BN_MP_TO_UNSIGNED_BIN_C
+#define BN_MP_TO_UNSIGNED_BIN_N_C
+#define BN_MP_TOOM_MUL_C
+#define BN_MP_TOOM_SQR_C
+#define BN_MP_TORADIX_C
+#define BN_MP_TORADIX_N_C
+#define BN_MP_UNSIGNED_BIN_SIZE_C
+#define BN_MP_XOR_C
+#define BN_MP_ZERO_C
+#define BN_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
+#endif
+
+#if defined(BN_ERROR_C)
+   #define BN_MP_ERROR_TO_STRING_C
+#endif
+
+#if defined(BN_FAST_MP_INVMOD_C)
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_COPY_C
+   #define BN_MP_MOD_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_DIGS_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_SQR_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_2EXPT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_ABS_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_ADD_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_ADD_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_ADDMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_AND_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CLAMP_C)
+#endif
+
+#if defined(BN_MP_CLEAR_C)
+#endif
+
+#if defined(BN_MP_CLEAR_MULTI_C)
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CMP_C)
+   #define BN_MP_CMP_MAG_C
+#endif
+
+#if defined(BN_MP_CMP_D_C)
+#endif
+
+#if defined(BN_MP_CMP_MAG_C)
+#endif
+
+#if defined(BN_MP_CNT_LSB_C)
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_COPY_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_COUNT_BITS_C)
+#endif
+
+#if defined(BN_MP_DIV_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_ABS_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_2_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_DIV_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_DIV_3_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_D_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DR_IS_MODULUS_C)
+#endif
+
+#if defined(BN_MP_DR_REDUCE_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_DR_SETUP_C)
+#endif
+
+#if defined(BN_MP_EXCH_C)
+#endif
+
+#if defined(BN_MP_EXPT_D_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SET_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MUL_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ABS_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_REDUCE_IS_2K_L_C
+   #define BN_S_MP_EXPTMOD_C
+   #define BN_MP_DR_IS_MODULUS_C
+   #define BN_MP_REDUCE_IS_2K_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_EXPTMOD_FAST_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_FAST_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MONTGOMERY_SETUP_C
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_DR_SETUP_C
+   #define BN_MP_DR_REDUCE_C
+   #define BN_MP_REDUCE_2K_SETUP_C
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_SET_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_EXTEUCLID_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_NEG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_FREAD_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CMP_D_C
+#endif
+
+#if defined(BN_MP_FWRITE_C)
+   #define BN_MP_RADIX_SIZE_C
+   #define BN_MP_TORADIX_C
+#endif
+
+#if defined(BN_MP_GCD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ABS_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_GET_INT_C)
+#endif
+
+#if defined(BN_MP_GROW_C)
+#endif
+
+#if defined(BN_MP_INIT_C)
+#endif
+
+#if defined(BN_MP_INIT_COPY_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_INIT_MULTI_C)
+   #define BN_MP_ERR_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_INIT_SET_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+#endif
+
+#if defined(BN_MP_INIT_SET_INT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_INT_C
+#endif
+
+#if defined(BN_MP_INIT_SIZE_C)
+   #define BN_MP_INIT_C
+#endif
+
+#if defined(BN_MP_INVMOD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ISODD_C
+   #define BN_FAST_MP_INVMOD_C
+   #define BN_MP_INVMOD_SLOW_C
+#endif
+
+#if defined(BN_MP_INVMOD_SLOW_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_IS_SQUARE_C)
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_SET_INT_C
+   #define BN_MP_MOD_C
+   #define BN_MP_GET_INT_C
+   #define BN_MP_SQRT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_JACOBI_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_MUL_C)
+   #define BN_MP_MUL_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_SQR_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SQR_C
+   #define BN_MP_SUB_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_LCM_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_GCD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_LSHD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+#endif
+
+#if defined(BN_MP_MOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_MOD_2D_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MOD_D_C)
+   #define BN_MP_DIV_D_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_SET_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_REDUCE_C)
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_SETUP_C)
+#endif
+
+#if defined(BN_MP_MUL_C)
+   #define BN_MP_TOOM_MUL_C
+   #define BN_MP_KARATSUBA_MUL_C
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_S_MP_MUL_C
+   #define BN_S_MP_MUL_DIGS_C
+#endif
+
+#if defined(BN_MP_MUL_2_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_MUL_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_GROW_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MUL_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MULMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_N_ROOT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_EXPT_D_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_NEG_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_OR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_FERMAT_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_DIVISIBLE_C)
+   #define BN_MP_MOD_D_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_PRIME_IS_DIVISIBLE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_MILLER_RABIN_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SQRMOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_NEXT_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
+#endif
+
+#if defined(BN_MP_PRIME_RANDOM_EX_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+   #define BN_MP_PRIME_IS_PRIME_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_D_C
+#endif
+
+#if defined(BN_MP_RADIX_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_RADIX_SMAP_C)
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_RAND_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_LSHD_C
+#endif
+
+#if defined(BN_MP_READ_RADIX_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_RADIX_SMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_READ_SIGNED_BIN_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_READ_UNSIGNED_BIN_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_REDUCE_C)
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_S_MP_MUL_HIGH_DIGS_C
+   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_MOD_2D_C
+   #define BN_S_MP_MUL_DIGS_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CMP_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_L_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MUL_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_CLEAR_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_L_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_C)
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_L_C)
+#endif
+
+#if defined(BN_MP_REDUCE_SETUP_C)
+   #define BN_MP_2EXPT_C
+   #define BN_MP_DIV_C
+#endif
+
+#if defined(BN_MP_RSHD_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_INT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SHRINK_C)
+#endif
+
+#if defined(BN_MP_SIGNED_BIN_SIZE_C)
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+#endif
+
+#if defined(BN_MP_SQR_C)
+   #define BN_MP_TOOM_SQR_C
+   #define BN_MP_KARATSUBA_SQR_C
+   #define BN_FAST_S_MP_SQR_C
+   #define BN_S_MP_SQR_C
+#endif
+
+#if defined(BN_MP_SQRMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_SQRT_C)
+   #define BN_MP_N_ROOT_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_DIV_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_SUB_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_SUB_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SUBMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_C)
+   #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_N_C)
+   #define BN_MP_SIGNED_BIN_SIZE_C
+   #define BN_MP_TO_SIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_N_C)
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+   #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TOOM_MUL_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TOOM_SQR_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TORADIX_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_TORADIX_N_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_UNSIGNED_BIN_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_XOR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_ZERO_C)
+#endif
+
+#if defined(BN_PRIME_TAB_C)
+#endif
+
+#if defined(BN_REVERSE_C)
+#endif
+
+#if defined(BN_S_MP_ADD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_S_MP_EXPTMOD_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_REDUCE_C
+   #define BN_MP_REDUCE_2K_SETUP_L_C
+   #define BN_MP_REDUCE_2K_L_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SET_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_S_MP_MUL_DIGS_C)
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SQR_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SUB_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BNCORE_C)
+#endif
+
+#ifdef LTM3
+#define LTM_LAST
+#endif
+#include <tommath_superclass.h>
+#include <tommath_class.h>
+#else
+#define LTM_LAST
+#endif
+
+/* $Source: /cvs/libtom/libtommath/tommath_class.h,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/07/28 11:59:32 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/tommath_superclass.h b/source4/heimdal/lib/hcrypto/libtommath/tommath_superclass.h
new file mode 100644 (file)
index 0000000..2fdebe6
--- /dev/null
@@ -0,0 +1,76 @@
+/* super class file for PK algos */
+
+/* default ... include all MPI */
+#define LTM_ALL
+
+/* RSA only (does not support DH/DSA/ECC) */
+/* #define SC_RSA_1 */
+
+/* For reference.... On an Athlon64 optimizing for speed...
+
+   LTM's mpi.o with all functions [striped] is 142KiB in size.
+
+*/
+
+/* Works for RSA only, mpi.o is 68KiB */
+#ifdef SC_RSA_1
+   #define BN_MP_SHRINK_C
+   #define BN_MP_LCM_C
+   #define BN_MP_PRIME_RANDOM_EX_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_GCD_C
+   #define BN_MP_MOD_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_ADDMOD_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_SET_INT_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+   #define BN_MP_TO_UNSIGNED_BIN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+   #define BN_REVERSE_C
+   #define BN_PRIME_TAB_C
+
+   /* other modifiers */
+   #define BN_MP_DIV_SMALL                    /* Slower division, not critical */
+
+   /* here we are on the last pass so we turn things off.  The functions classes are still there
+    * but we remove them specifically from the build.  This also invokes tweaks in functions
+    * like removing support for even moduli, etc...
+    */
+#ifdef LTM_LAST
+   #undef  BN_MP_TOOM_MUL_C
+   #undef  BN_MP_TOOM_SQR_C
+   #undef  BN_MP_KARATSUBA_MUL_C
+   #undef  BN_MP_KARATSUBA_SQR_C
+   #undef  BN_MP_REDUCE_C
+   #undef  BN_MP_REDUCE_SETUP_C
+   #undef  BN_MP_DR_IS_MODULUS_C
+   #undef  BN_MP_DR_SETUP_C
+   #undef  BN_MP_DR_REDUCE_C
+   #undef  BN_MP_REDUCE_IS_2K_C
+   #undef  BN_MP_REDUCE_2K_SETUP_C
+   #undef  BN_MP_REDUCE_2K_C
+   #undef  BN_S_MP_EXPTMOD_C
+   #undef  BN_MP_DIV_3_C
+   #undef  BN_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_MP_INVMOD_C
+
+   /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
+    * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] 
+    * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
+    * trouble.  
+    */
+   #undef  BN_S_MP_MUL_DIGS_C
+   #undef  BN_S_MP_SQR_C
+   #undef  BN_MP_MONTGOMERY_REDUCE_C
+#endif
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/tommath_superclass.h,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/14 13:29:17 $ */
index 435e662a42abf99262d5220bab4532af6789e484..1a9f77fed250ef45c9bec0924febf6861ac58dd0 100644 (file)
@@ -191,10 +191,10 @@ MD4_Update (struct md4 *m, const void *v, size_t len)
 #if defined(WORDS_BIGENDIAN)
            int i;
            uint32_t current[16];
-           struct x32 *u = (struct x32*)m->save;
+           struct x32 *us = (struct x32*)m->save;
            for(i = 0; i < 8; i++){
-               current[2*i+0] = swap_uint32_t(u[i].a);
-               current[2*i+1] = swap_uint32_t(u[i].b);
+               current[2*i+0] = swap_uint32_t(us[i].a);
+               current[2*i+1] = swap_uint32_t(us[i].b);
            }
            calc(m, current);
 #else
index f99078737b9d1279d81d5082b91bc0e73f0765bd..b35c76e2937e3b5125999b098ed973025b6d18e8 100644 (file)
@@ -215,10 +215,10 @@ MD5_Update (struct md5 *m, const void *v, size_t len)
 #if defined(WORDS_BIGENDIAN)
       int i;
       uint32_t current[16];
-      struct x32 *u = (struct x32*)m->save;
+      struct x32 *us = (struct x32*)m->save;
       for(i = 0; i < 8; i++){
-       current[2*i+0] = swap_uint32_t(u[i].a);
-       current[2*i+1] = swap_uint32_t(u[i].b);
+       current[2*i+0] = swap_uint32_t(us[i].a);
+       current[2*i+1] = swap_uint32_t(us[i].b);
       }
       calc(m, current);
 #else
index c81eb9e2d729e3667083b96099903bd996ea2897..11027b46cf4acd2ffac6d4b708512c64d0240632 100644 (file)
@@ -34,6 +34,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <rand.h>
+#include <heim_threads.h>
 
 #ifdef KRB5
 #include <krb5-types.h>
@@ -441,11 +442,21 @@ static int        have_entropy;
 #define FORTUNA_RESEED_BYTE    10000
 static unsigned        resend_bytes;
 
+/*
+ * This mutex protects all of the above static elements from concurrent
+ * access by multiple threads
+ */
+static HEIMDAL_MUTEX fortuna_mutex = HEIMDAL_MUTEX_INITIALIZER;
+
 /*
  * Try our best to do an inital seed
  */
 #define INIT_BYTES     128
 
+/*
+ * fortuna_mutex must be held across calls to this function
+ */
+
 static int
 fortuna_reseed(void)
 {
@@ -537,6 +548,9 @@ fortuna_reseed(void)
     return entropy_p;
 }
 
+/*
+ * fortuna_mutex must be held by callers of this function
+ */
 static int
 fortuna_init(void)
 {
@@ -555,32 +569,50 @@ fortuna_init(void)
 static void
 fortuna_seed(const void *indata, int size)
 {
+    HEIMDAL_MUTEX_lock(&fortuna_mutex);
+
     fortuna_init();
     add_entropy(&main_state, indata, size);
     if (size >= INIT_BYTES)
        have_entropy = 1;
+
+    HEIMDAL_MUTEX_unlock(&fortuna_mutex);
 }
 
 static int
 fortuna_bytes(unsigned char *outdata, int size)
 {
+    int ret = 0;
+
+    HEIMDAL_MUTEX_lock(&fortuna_mutex);
+
     if (!fortuna_init())
-       return 0;
+       goto out;
+
     resend_bytes += size;
     if (resend_bytes > FORTUNA_RESEED_BYTE || resend_bytes < size) {
        resend_bytes = 0;
        fortuna_reseed();
     }
     extract_data(&main_state, size, outdata);
-    return 1;
+    ret = 1;
+
+out:
+    HEIMDAL_MUTEX_unlock(&fortuna_mutex);
+
+    return ret;
 }
 
 static void
 fortuna_cleanup(void)
 {
+    HEIMDAL_MUTEX_lock(&fortuna_mutex);
+
     init_done = 0;
     have_entropy = 0;
     memset(&main_state, 0, sizeof(main_state));
+
+    HEIMDAL_MUTEX_unlock(&fortuna_mutex);
 }
 
 static void
@@ -598,7 +630,13 @@ fortuna_pseudorand(unsigned char *outdata, int size)
 static int
 fortuna_status(void)
 {
-    return fortuna_init() ? 1 : 0;
+    int result;
+
+    HEIMDAL_MUTEX_lock(&fortuna_mutex);
+    result = fortuna_init();
+    HEIMDAL_MUTEX_unlock(&fortuna_mutex);
+
+    return result ? 1 : 0;
 }
 
 const RAND_METHOD hc_rand_fortuna_method = {
index 63dc97fbfa7b9e53d3d6104b77a12bd934217f1c..c52155baaa8120d7424e8ef4e15d61900bd3d9b4 100644 (file)
@@ -47,7 +47,7 @@
  */
 
 int
-_hc_unix_device_fd(int flags, char **fn)
+_hc_unix_device_fd(int flags, const char **fn)
 {
     static const char *rnd_devices[] = {
        "/dev/urandom",
index d360ffcab4c02d8e1e902bb4ecbf1a7b74255935..d5c1f687b910d2848eda53d5dfd9b781f34acad4 100644 (file)
 #define O_BINARY 0
 #endif
 
+#ifdef _WIN32
+#include<shlobj.h>
+#endif
+
 /**
  * @page page_rand RAND - random number
  *
@@ -342,7 +346,7 @@ RAND_write_file(const char *filename)
 const char *
 RAND_file_name(char *filename, size_t size)
 {
-    char *e = NULL;
+    const char *e = NULL;
     int pathp = 0, ret;
 
     if (!issuid()) {
@@ -352,6 +356,8 @@ RAND_file_name(char *filename, size_t size)
        if (e)
            pathp = 1;
     }
+
+#ifndef _WIN32
     /*
      * Here we really want to call getpwuid(getuid()) but this will
      * cause recursive lookups if the nss library uses
@@ -359,7 +365,6 @@ RAND_file_name(char *filename, size_t size)
      *
      * So at least return the unix /dev/random if we have one
      */
-#ifndef _WIN32
     if (e == NULL) {
        int fd;
 
@@ -367,7 +372,22 @@ RAND_file_name(char *filename, size_t size)
        if (fd >= 0)
            close(fd);
     }
+#else  /* Win32 */
+
+    if (e == NULL) {
+       char profile[MAX_PATH];
+
+       if (SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL,
+                           SHGFP_TYPE_CURRENT, profile) == S_OK) {
+           ret = snprintf(filename, size, "%s\\.rnd", profile);
+
+           if (ret > 0 && ret < size)
+               return filename;
+       }
+    }
+
 #endif
+
     if (e == NULL)
        return NULL;
 
index f4e2485166ca6001518ecd23db452fc2cd4afba6..590bd8cf1a43de83d7bd39fa17e10a3ad2c10c76 100644 (file)
@@ -41,7 +41,6 @@
 
 typedef struct RAND_METHOD RAND_METHOD;
 
-#include <hcrypto/bn.h>
 #include <hcrypto/engine.h>
 
 /* symbol renaming */
@@ -105,5 +104,6 @@ int RAND_egd_bytes(const char *, int);
 const RAND_METHOD *    RAND_fortuna_method(void);
 const RAND_METHOD *    RAND_unix_method(void);
 const RAND_METHOD *    RAND_egd_method(void);
+const RAND_METHOD *    RAND_w32crypto_method(void);
 
 #endif /* _HEIM_RAND_H */
index a6d921413a3d5998dae2ceb0b995a9e103c6762b..fe021a80ecddddb052ef31c08f398a5ded244414 100644 (file)
@@ -45,6 +45,6 @@ extern const RAND_METHOD hc_rand_timer_method;
 extern const RAND_METHOD hc_rand_w32crypto_method;
 
 const RAND_METHOD * RAND_timer_method(void);
-int _hc_unix_device_fd(int, char **);
+int _hc_unix_device_fd(int, const char **);
 
 #endif /* _HEIM_RANDI_H */
index 9a7f0fd3d60ca822f0188115517746dd752f1d85..bf335afd9f3234241722d2485c73e84ba3bd3414 100644 (file)
 
 #include "rijndael-alg-fst.h"
 
-/* the file should not be used from outside */
-typedef uint8_t                        u8;
-typedef uint16_t               u16;    
-typedef uint32_t               u32;
-
 /*
 Te0[x] = S [x].[02, 01, 01, 03];
 Te1[x] = S [x].[03, 02, 01, 01];
@@ -57,7 +52,7 @@ Td3[x] = Si[x].[09, 0d, 0b, 0e];
 Td4[x] = Si[x].[01, 01, 01, 01];
 */
 
-static const u32 Te0[256] = {
+static const uint32_t Te0[256] = {
     0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
     0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
     0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
@@ -123,7 +118,7 @@ static const u32 Te0[256] = {
     0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
     0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
 };
-static const u32 Te1[256] = {
+static const uint32_t Te1[256] = {
     0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
     0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
     0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
@@ -189,7 +184,7 @@ static const u32 Te1[256] = {
     0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
     0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
 };
-static const u32 Te2[256] = {
+static const uint32_t Te2[256] = {
     0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
     0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
     0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
@@ -255,7 +250,7 @@ static const u32 Te2[256] = {
     0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
     0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
 };
-static const u32 Te3[256] = {
+static const uint32_t Te3[256] = {
 
     0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
     0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
@@ -322,7 +317,7 @@ static const u32 Te3[256] = {
     0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
     0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
 };
-static const u32 Te4[256] = {
+static const uint32_t Te4[256] = {
     0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
     0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
     0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
@@ -388,7 +383,7 @@ static const u32 Te4[256] = {
     0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
     0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
 };
-static const u32 Td0[256] = {
+static const uint32_t Td0[256] = {
     0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
     0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
     0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
@@ -454,7 +449,7 @@ static const u32 Td0[256] = {
     0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
     0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
 };
-static const u32 Td1[256] = {
+static const uint32_t Td1[256] = {
     0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
     0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
     0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
@@ -520,7 +515,7 @@ static const u32 Td1[256] = {
     0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
     0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
 };
-static const u32 Td2[256] = {
+static const uint32_t Td2[256] = {
     0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
     0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
     0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
@@ -587,7 +582,7 @@ static const u32 Td2[256] = {
     0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
     0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
 };
-static const u32 Td3[256] = {
+static const uint32_t Td3[256] = {
     0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
     0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
     0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
@@ -653,7 +648,7 @@ static const u32 Td3[256] = {
     0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
     0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
 };
-static const u32 Td4[256] = {
+static const uint32_t Td4[256] = {
     0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
     0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
     0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
@@ -719,7 +714,7 @@ static const u32 Td4[256] = {
     0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
     0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
 };
-static const u32 rcon[] = {
+static const uint32_t rcon[] = {
        0x01000000, 0x02000000, 0x04000000, 0x08000000,
        0x10000000, 0x20000000, 0x40000000, 0x80000000,
        0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
@@ -728,11 +723,11 @@ static const u32 rcon[] = {
 #define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
 
 #ifdef _MSC_VER
-#define GETU32(p) SWAP(*((u32 *)(p)))
-#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
+#define GETU32(p) SWAP(*((uint32_t *)(p)))
+#define PUTU32(ct, st) { *((uint32_t *)(ct)) = SWAP((st)); }
 #else
-#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
-#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
+#define GETU32(pt) (((uint32_t)(pt)[0] << 24) ^ ((uint32_t)(pt)[1] << 16) ^ ((uint32_t)(pt)[2] <<  8) ^ ((uint32_t)(pt)[3]))
+#define PUTU32(ct, st) { (ct)[0] = (uint8_t)((st) >> 24); (ct)[1] = (uint8_t)((st) >> 16); (ct)[2] = (uint8_t)((st) >>  8); (ct)[3] = (uint8_t)(st); }
 #endif
 
 /**
@@ -740,9 +735,9 @@ static const u32 rcon[] = {
  *
  * @return     the number of rounds for the given cipher key size.
  */
-int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+int rijndaelKeySetupEnc(uint32_t rk[/*4*(Nr + 1)*/], const uint8_t cipherKey[], int keyBits) {
        int i = 0;
-       u32 temp;
+       uint32_t temp;
 
        rk[0] = GETU32(cipherKey     );
        rk[1] = GETU32(cipherKey +  4);
@@ -826,9 +821,9 @@ int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBit
  *
  * @return     the number of rounds for the given cipher key size.
  */
-int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+int rijndaelKeySetupDec(uint32_t rk[/*4*(Nr + 1)*/], const uint8_t cipherKey[], int keyBits) {
        int Nr, i, j;
-       u32 temp;
+       uint32_t temp;
 
        /* expand the cipher key: */
        Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
@@ -866,8 +861,8 @@ int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBit
        return Nr;
 }
 
-void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) {
-       u32 s0, s1, s2, s3, t0, t1, t2, t3;
+void rijndaelEncrypt(const uint32_t rk[/*4*(Nr + 1)*/], int Nr, const uint8_t pt[16], uint8_t ct[16]) {
+       uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
 #ifndef FULL_UNROLL
     int r;
 #endif /* ?FULL_UNROLL */
@@ -1047,8 +1042,8 @@ void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 c
        PUTU32(ct + 12, s3);
 }
 
-void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) {
-       u32 s0, s1, s2, s3, t0, t1, t2, t3;
+void rijndaelDecrypt(const uint32_t rk[/*4*(Nr + 1)*/], int Nr, const uint8_t ct[16], uint8_t pt[16]) {
+       uint32_t s0, s1, s2, s3, t0, t1, t2, t3;
 #ifndef FULL_UNROLL
     int r;
 #endif /* ?FULL_UNROLL */
index a2b9d2a6787c0c7095e92c5da09f6cf3dc0ef82d..23d53527002f37b2b91a076ddeceac4c7fdecb9a 100644 (file)
@@ -42,6 +42,8 @@
 
 #include <roken.h>
 
+#ifdef USE_HCRYPTO_IMATH
+
 #include "imath/imath.h"
 #include "imath/iprime.h"
 
@@ -406,7 +408,7 @@ imath_rsa_private_decrypt(int flen, const unsigned char* from,
 {
     unsigned char *ptr;
     mp_result res;
-    size_t size;
+    int size;
     mpz_t in, out, n, e, b, bi;
     int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
     int do_unblind = 0;
@@ -673,9 +675,14 @@ const RSA_METHOD hc_rsa_imath_method = {
     NULL,
     imath_rsa_generate_key
 };
+#endif
 
 const RSA_METHOD *
 RSA_imath_method(void)
 {
+#ifdef USE_HCRYPTO_IMATH
     return &hc_rsa_imath_method;
+#else
+    return NULL;
+#endif
 }
diff --git a/source4/heimdal/lib/hcrypto/rsa-ltm.c b/source4/heimdal/lib/hcrypto/rsa-ltm.c
new file mode 100644 (file)
index 0000000..ad3686e
--- /dev/null
@@ -0,0 +1,630 @@
+/*
+ * Copyright (c) 2006 - 2007, 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <krb5-types.h>
+#include <assert.h>
+
+#include <rsa.h>
+
+#include <roken.h>
+
+#include "tommath.h"
+
+static int
+random_num(mp_int *num, size_t len)
+{
+    unsigned char *p;
+
+    len = (len + 7) / 8;
+    p = malloc(len);
+    if (p == NULL)
+       return 1;
+    if (RAND_bytes(p, len) != 1) {
+       free(p);
+       return 1;
+    }
+    mp_read_unsigned_bin(num, p, len);
+    free(p);
+    return 0;
+}
+
+static void
+BN2mpz(mp_int *s, const BIGNUM *bn)
+{
+    size_t len;
+    void *p;
+
+    len = BN_num_bytes(bn);
+    p = malloc(len);
+    BN_bn2bin(bn, p);
+    mp_read_unsigned_bin(s, p, len);
+    free(p);
+}
+
+static void
+setup_blind(mp_int *n, mp_int *b, mp_int *bi)
+{
+    random_num(b, mp_count_bits(n));
+    mp_mod(b, n, b);
+    mp_invmod(b, n, bi);
+}
+
+static void
+blind(mp_int *in, mp_int *b, mp_int *e, mp_int *n)
+{
+    mp_int t1;
+    mp_init(&t1);
+    /* in' = (in * b^e) mod n */
+    mp_exptmod(b, e, n, &t1);
+    mp_mul(&t1, in, in);
+    mp_mod(in, n, in);
+    mp_clear(&t1);
+}
+
+static void
+unblind(mp_int *out, mp_int *bi, mp_int *n)
+{
+    /* out' = (out * 1/b) mod n */
+    mp_mul(out, bi, out);
+    mp_mod(out, n, out);
+}
+
+static int
+ltm_rsa_private_calculate(mp_int * in, mp_int * p,  mp_int * q,
+                         mp_int * dmp1, mp_int * dmq1, mp_int * iqmp,
+                         mp_int * out)
+{
+    mp_int vp, vq, u;
+
+    mp_init_multi(&vp, &vq, &u, NULL);
+
+    /* vq = c ^ (d mod (q - 1)) mod q */
+    /* vp = c ^ (d mod (p - 1)) mod p */
+    mp_mod(in, p, &u);
+    mp_exptmod(&u, dmp1, p, &vp);
+    mp_mod(in, q, &u);
+    mp_exptmod(&u, dmq1, q, &vq);
+
+    /* C2 = 1/q mod p  (iqmp) */
+    /* u = (vp - vq)C2 mod p. */
+    mp_sub(&vp, &vq, &u);
+    if (mp_isneg(&u))
+       mp_add(&u, p, &u);
+    mp_mul(&u, iqmp, &u);
+    mp_mod(&u, p, &u);
+
+    /* c ^ d mod n = vq + u q */
+    mp_mul(&u, q, &u);
+    mp_add(&u, &vq, out);
+
+    mp_clear_multi(&vp, &vq, &u, NULL);
+
+    return 0;
+}
+
+/*
+ *
+ */
+
+static int
+ltm_rsa_public_encrypt(int flen, const unsigned char* from,
+                       unsigned char* to, RSA* rsa, int padding)
+{
+    unsigned char *p, *p0;
+    int res;
+    size_t size, padlen;
+    mp_int enc, dec, n, e;
+
+    if (padding != RSA_PKCS1_PADDING)
+       return -1;
+
+    mp_init_multi(&n, &e, &enc, &dec, NULL);
+
+    size = RSA_size(rsa);
+
+    if (size < RSA_PKCS1_PADDING_SIZE || size - RSA_PKCS1_PADDING_SIZE < flen) {
+       mp_clear_multi(&n, &e, &enc, &dec);
+       return -2;
+    }
+
+    BN2mpz(&n, rsa->n);
+    BN2mpz(&e, rsa->e);
+
+    p = p0 = malloc(size - 1);
+    if (p0 == NULL) {
+       mp_clear_multi(&e, &n, &enc, &dec, NULL);
+       return -3;
+    }
+
+    padlen = size - flen - 3;
+
+    *p++ = 2;
+    if (RAND_bytes(p, padlen) != 1) {
+       mp_clear_multi(&e, &n, &enc, &dec, NULL);
+       free(p0);
+       return -4;
+    }
+    while(padlen) {
+       if (*p == 0)
+           *p = 1;
+       padlen--;
+       p++;
+    }
+    *p++ = 0;
+    memcpy(p, from, flen);
+    p += flen;
+    assert((p - p0) == size - 1);
+    
+    mp_read_unsigned_bin(&dec, p0, size - 1);
+    free(p0);
+
+    res = mp_exptmod(&dec, &e, &n, &enc);
+
+    mp_clear_multi(&dec, &e, &n, NULL);
+
+    if (res != 0) {
+       mp_clear(&enc);
+       return -4;
+    }
+
+    {
+       size_t ssize;
+       ssize = mp_unsigned_bin_size(&enc);
+       assert(size >= ssize);
+       mp_to_unsigned_bin(&enc, to);
+       size = ssize;
+    }
+    mp_clear(&enc);
+
+    return size;
+}
+
+static int
+ltm_rsa_public_decrypt(int flen, const unsigned char* from,
+                      unsigned char* to, RSA* rsa, int padding)
+{
+    unsigned char *p;
+    int res;
+    size_t size;
+    mp_int s, us, n, e;
+
+    if (padding != RSA_PKCS1_PADDING)
+       return -1;
+
+    if (flen > RSA_size(rsa))
+       return -2;
+
+    mp_init_multi(&e, &n, &s, &us, NULL);
+
+    BN2mpz(&n, rsa->n);
+    BN2mpz(&e, rsa->e);
+
+#if 0
+    /* Check that the exponent is larger then 3 */
+    if (mp_int_compare_value(&e, 3) <= 0) {
+       mp_clear_multi(&e, &n, &s, &us, NULL);
+       return -3;
+    }
+#endif
+
+    mp_read_unsigned_bin(&s, rk_UNCONST(from), flen);
+
+    if (mp_cmp(&s, &n) >= 0) {
+       mp_clear_multi(&e, &n, &s, &us, NULL);
+       return -4;
+    }
+
+    res = mp_exptmod(&s, &e, &n, &us);
+
+    mp_clear_multi(&e, &n, &s, NULL);
+
+    if (res != 0) {
+       mp_clear(&us);
+       return -5;
+    }
+    p = to;
+
+
+    size = mp_unsigned_bin_size(&us);
+    assert(size <= RSA_size(rsa));
+    mp_to_unsigned_bin(&us, p);
+
+    mp_clear(&us);
+
+    /* head zero was skipped by mp_to_unsigned_bin */
+    if (*p == 0)
+       return -6;
+    if (*p != 1)
+       return -7;
+    size--; p++;
+    while (size && *p == 0xff) {
+       size--; p++;
+    }
+    if (size == 0 || *p != 0)
+       return -8;
+    size--; p++;
+
+    memmove(to, p, size);
+
+    return size;
+}
+
+static int
+ltm_rsa_private_encrypt(int flen, const unsigned char* from,
+                       unsigned char* to, RSA* rsa, int padding)
+{
+    unsigned char *p, *p0;
+    int res;
+    int size;
+    mp_int in, out, n, e;
+    mp_int bi, b;
+    int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
+    int do_unblind = 0;
+
+    if (padding != RSA_PKCS1_PADDING)
+       return -1;
+
+    mp_init_multi(&e, &n, &in, &out, &b, &bi, NULL);
+
+    size = RSA_size(rsa);
+
+    if (size < RSA_PKCS1_PADDING_SIZE || size - RSA_PKCS1_PADDING_SIZE < flen)
+       return -2;
+
+    p0 = p = malloc(size);
+    *p++ = 0;
+    *p++ = 1;
+    memset(p, 0xff, size - flen - 3);
+    p += size - flen - 3;
+    *p++ = 0;
+    memcpy(p, from, flen);
+    p += flen;
+    assert((p - p0) == size);
+
+    BN2mpz(&n, rsa->n);
+    BN2mpz(&e, rsa->e);
+
+    mp_read_unsigned_bin(&in, p0, size);
+    free(p0);
+
+    if(mp_isneg(&in) || mp_cmp(&in, &n) >= 0) {
+       size = -3;
+       goto out;
+    }
+
+    if (blinding) {
+       setup_blind(&n, &b, &bi);
+       blind(&in, &b, &e, &n);
+       do_unblind = 1;
+    }
+
+    if (rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp) {
+       mp_int p, q, dmp1, dmq1, iqmp;
+
+       mp_init_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL);
+
+       BN2mpz(&p, rsa->p);
+       BN2mpz(&q, rsa->q);
+       BN2mpz(&dmp1, rsa->dmp1);
+       BN2mpz(&dmq1, rsa->dmq1);
+       BN2mpz(&iqmp, rsa->iqmp);
+
+       res = ltm_rsa_private_calculate(&in, &p, &q, &dmp1, &dmq1, &iqmp, &out);
+
+       mp_clear_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL);
+
+       if (res != 0) {
+           size = -4;
+           goto out;
+       }
+    } else {
+       mp_int d;
+
+       BN2mpz(&d, rsa->d);
+       res = mp_exptmod(&in, &d, &n, &out);
+       mp_clear(&d);
+       if (res != 0) {
+           size = -5;
+           goto out;
+       }
+    }
+
+    if (do_unblind)
+       unblind(&out, &bi, &n);
+
+    if (size > 0) {
+       size_t ssize;
+       ssize = mp_unsigned_bin_size(&out);
+       assert(size >= ssize);
+       mp_to_unsigned_bin(&out, to);
+       size = ssize;
+    }
+
+ out:
+    mp_clear_multi(&e, &n, &in, &out, &b, &bi, NULL);
+
+    return size;
+}
+
+static int
+ltm_rsa_private_decrypt(int flen, const unsigned char* from,
+                       unsigned char* to, RSA* rsa, int padding)
+{
+    unsigned char *ptr;
+    int res;
+    size_t size;
+    mp_int in, out, n, e, b, bi;
+    int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
+    int do_unblind = 0;
+
+    if (padding != RSA_PKCS1_PADDING)
+       return -1;
+
+    size = RSA_size(rsa);
+    if (flen > size)
+       return -2;
+
+    mp_init_multi(&in, &n, &e, &out, &bi, &b, NULL);
+
+    BN2mpz(&n, rsa->n);
+    BN2mpz(&e, rsa->e);
+
+    mp_read_unsigned_bin(&in, rk_UNCONST(from), flen);
+
+    if(mp_isneg(&in) || mp_cmp(&in, &n) >= 0) {
+       size = -2;
+       goto out;
+    }
+
+    if (blinding) {
+       setup_blind(&n, &b, &bi);
+       blind(&in, &b, &e, &n);
+       do_unblind = 1;
+    }
+
+    if (rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp) {
+       mp_int p, q, dmp1, dmq1, iqmp;
+
+       mp_init_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL);
+
+       BN2mpz(&p, rsa->p);
+       BN2mpz(&q, rsa->q);
+       BN2mpz(&dmp1, rsa->dmp1);
+       BN2mpz(&dmq1, rsa->dmq1);
+       BN2mpz(&iqmp, rsa->iqmp);
+
+       res = ltm_rsa_private_calculate(&in, &p, &q, &dmp1, &dmq1, &iqmp, &out);
+
+       mp_clear_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL);
+
+       if (res != 0) {
+           size = -3;
+           goto out;
+       }
+
+    } else {
+       mp_int d;
+
+       if(mp_isneg(&in) || mp_cmp(&in, &n) >= 0)
+           return -4;
+
+       BN2mpz(&d, rsa->d);
+       res = mp_exptmod(&in, &d, &n, &out);
+       mp_clear(&d);
+       if (res != 0) {
+           size = -5;
+           goto out;
+       }
+    }
+
+    if (do_unblind)
+       unblind(&out, &bi, &n);
+
+    ptr = to;
+    {
+       size_t ssize;
+       ssize = mp_unsigned_bin_size(&out);
+       assert(size >= ssize);
+       mp_to_unsigned_bin(&out, ptr);
+       size = ssize;
+    }
+
+    /* head zero was skipped by mp_int_to_unsigned */
+    if (*ptr != 2) {
+       size = -6;
+       goto out;
+    }
+    size--; ptr++;
+    while (size && *ptr != 0) {
+       size--; ptr++;
+    }
+    if (size == 0)
+       return -7;
+    size--; ptr++;
+
+    memmove(to, ptr, size);
+
+ out:
+    mp_clear_multi(&e, &n, &in, &out, NULL);
+
+    return size;
+}
+
+static BIGNUM *
+mpz2BN(mp_int *s)
+{
+    size_t size;
+    BIGNUM *bn;
+    void *p;
+
+    size = mp_unsigned_bin_size(s);
+    p = malloc(size);
+    if (p == NULL && size != 0)
+       return NULL;
+
+    mp_to_unsigned_bin(s, p);
+
+    bn = BN_bin2bn(p, size, NULL);
+    free(p);
+    return bn;
+}
+
+#define CHECK(f, v) if ((f) != (v)) { goto out; }
+
+static int
+ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
+{
+    mp_int el, p, q, n, d, dmp1, dmq1, iqmp, t1, t2, t3;
+    int counter, ret, bitsp;
+
+    if (bits < 789)
+       return -1;
+
+    bitsp = (bits + 1) / 2;
+
+    ret = -1;
+
+    mp_init_multi(&el, &p, &q, &n, &n, &d, &dmp1, &dmq1, &iqmp, &t1, &t2, &t3, NULL);
+
+    BN2mpz(&el, e);
+
+    /* generate p and q so that p != q and bits(pq) ~ bits */
+    counter = 0;
+    do {
+       BN_GENCB_call(cb, 2, counter++);
+       CHECK(random_num(&p, bitsp), 0);
+       CHECK(mp_find_prime(&p), MP_YES);
+
+       mp_sub_d(&p, 1, &t1);
+       mp_gcd(&t1, &el, &t2);
+    } while(mp_cmp_d(&t2, 1) != 0);
+
+    BN_GENCB_call(cb, 3, 0);
+
+    counter = 0;
+    do {
+       BN_GENCB_call(cb, 2, counter++);
+       CHECK(random_num(&q, bits - bitsp), 0);
+       CHECK(mp_find_prime(&q), MP_YES);
+
+       if (mp_cmp(&p, &q) == 0) /* don't let p and q be the same */
+           continue;
+
+       mp_sub_d(&q, 1, &t1);
+       mp_gcd(&t1, &el, &t2);
+    } while(mp_cmp_d(&t2, 1) != 0);
+
+    /* make p > q */
+    if (mp_cmp(&p, &q) < 0) {
+       mp_int c;
+       c = p;
+       p = q;
+       q = c;
+    }
+
+    BN_GENCB_call(cb, 3, 1);
+
+    /* calculate n,            n = p * q */
+    mp_mul(&p, &q, &n);
+
+    /* calculate d,            d = 1/e mod (p - 1)(q - 1) */
+    mp_sub_d(&p, 1, &t1);
+    mp_sub_d(&q, 1, &t2);
+    mp_mul(&t1, &t2, &t3);
+    mp_invmod(&el, &t3, &d);
+
+    /* calculate dmp1          dmp1 = d mod (p-1) */
+    mp_mod(&d, &t1, &dmp1);
+    /* calculate dmq1          dmq1 = d mod (q-1) */
+    mp_mod(&d, &t2, &dmq1);
+    /* calculate iqmp          iqmp = 1/q mod p */
+    mp_invmod(&q, &p, &iqmp);
+
+    /* fill in RSA key */
+
+    rsa->e = mpz2BN(&el);
+    rsa->p = mpz2BN(&p);
+    rsa->q = mpz2BN(&q);
+    rsa->n = mpz2BN(&n);
+    rsa->d = mpz2BN(&d);
+    rsa->dmp1 = mpz2BN(&dmp1);
+    rsa->dmq1 = mpz2BN(&dmq1);
+    rsa->iqmp = mpz2BN(&iqmp);
+
+    ret = 1;
+
+out:
+    mp_clear_multi(&el, &p, &q, &n, &d, &dmp1,
+                 &dmq1, &iqmp, &t1, &t2, &t3, NULL);
+
+    return ret;
+}
+
+static int
+ltm_rsa_init(RSA *rsa)
+{
+    return 1;
+}
+
+static int
+ltm_rsa_finish(RSA *rsa)
+{
+    return 1;
+}
+
+const RSA_METHOD hc_rsa_ltm_method = {
+    "hcrypto ltm RSA",
+    ltm_rsa_public_encrypt,
+    ltm_rsa_public_decrypt,
+    ltm_rsa_private_encrypt,
+    ltm_rsa_private_decrypt,
+    NULL,
+    NULL,
+    ltm_rsa_init,
+    ltm_rsa_finish,
+    0,
+    NULL,
+    NULL,
+    NULL,
+    ltm_rsa_generate_key
+};
+
+const RSA_METHOD *
+RSA_ltm_method(void)
+{
+    return &hc_rsa_ltm_method;
+}
index 6a883454a3e333ff30fa249f8dd0205fa255aa28..a6e09fe2834bb0ddcc38e499dfe146682a687233 100644 (file)
 #include <krb5-types.h>
 #include <rfc2459_asn1.h>
 
+#include <der.h>
+
 #include <rsa.h>
 
+#include "common.h"
+
 #include <roken.h>
 
 /**
  * RSA is named by its inventors (Ron Rivest, Adi Shamir, and Leonard
  * Adleman) (published in 1977), patented expired in 21 September 2000.
  *
+ *
+ * Speed for RSA in seconds
+ *   no key blinding
+ *   1000 iteration, 
+ *   same rsa key
+ *   operation performed each eteration sign, verify, encrypt, decrypt on a random bit pattern
+ *
+ * gmp:         0.733615
+ * tfm:         2.450173
+ * ltm:                 3.79 (default in hcrypto)
+ * openssl:     4.04
+ * cdsa:       15.89
+ * imath:      40.62
+ *
  * See the library functions here: @ref hcrypto_rsa
  */
 
@@ -237,7 +255,7 @@ RSA_set_app_data(RSA *rsa, void *arg)
  */
 
 void *
-RSA_get_app_data(RSA *rsa)
+RSA_get_app_data(const RSA *rsa)
 {
     return rsa->ex_data.sk;
 }
@@ -303,19 +321,136 @@ RSAFUNC(RSA_public_decrypt, (r)->meth->rsa_pub_dec(flen, f, t, r, p))
 RSAFUNC(RSA_private_encrypt, (r)->meth->rsa_priv_enc(flen, f, t, r, p))
 RSAFUNC(RSA_private_decrypt, (r)->meth->rsa_priv_dec(flen, f, t, r, p))
 
-/* XXX */
+static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };
+
+static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
+static const AlgorithmIdentifier _signature_sha1_data = {
+    { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
+static const AlgorithmIdentifier _signature_sha256_data = {
+    { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 };
+static const AlgorithmIdentifier _signature_md5_data = {
+    { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+
 int
 RSA_sign(int type, const unsigned char *from, unsigned int flen,
         unsigned char *to, unsigned int *tlen, RSA *rsa)
 {
-    return -1;
+    if (rsa->meth->rsa_sign)
+       return rsa->meth->rsa_sign(type, from, flen, to, tlen, rsa);
+
+    if (rsa->meth->rsa_priv_enc) {
+       heim_octet_string indata;
+       DigestInfo di;
+       size_t size;
+       int ret;
+
+       memset(&di, 0, sizeof(di));
+
+       if (type == NID_sha1) {
+           di.digestAlgorithm = _signature_sha1_data;
+       } else if (type == NID_md5) {
+           di.digestAlgorithm = _signature_md5_data;
+       } else if (type == NID_sha256) {
+           di.digestAlgorithm = _signature_sha256_data;
+       } else
+           return -1;
+
+       di.digest.data = rk_UNCONST(from);
+       di.digest.length = flen;
+
+       ASN1_MALLOC_ENCODE(DigestInfo,
+                          indata.data,
+                          indata.length,
+                          &di,
+                          &size,
+                          ret);
+       if (ret)
+           return ret;
+       if (indata.length != size)
+           abort();
+
+       ret = rsa->meth->rsa_priv_enc(indata.length, indata.data, to,
+                                     rsa, RSA_PKCS1_PADDING);
+       free(indata.data);
+       if (ret > 0) {
+           *tlen = ret;
+           ret = 1;
+       } else
+           ret = 0;
+
+       return ret;
+    }
+
+    return 0;
 }
 
 int
 RSA_verify(int type, const unsigned char *from, unsigned int flen,
-          unsigned char *to, unsigned int tlen, RSA *rsa)
+          unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
 {
-    return -1;
+    if (rsa->meth->rsa_verify)
+       return rsa->meth->rsa_verify(type, from, flen, sigbuf, siglen, rsa);
+
+    if (rsa->meth->rsa_pub_dec) {
+       const AlgorithmIdentifier *digest_alg;
+       void *data;
+       DigestInfo di;
+       size_t size;
+       int ret, ret2;
+
+       data = malloc(RSA_size(rsa));
+       if (data == NULL)
+           return -1;
+
+       memset(&di, 0, sizeof(di));
+
+       ret = rsa->meth->rsa_pub_dec(siglen, sigbuf, data, rsa, RSA_PKCS1_PADDING);
+       if (ret <= 0) {
+           free(data);
+           return -2;
+       }
+
+       ret2 = decode_DigestInfo(data, ret, &di, &size);
+       free(data);
+       if (ret2 != 0)
+           return -3;
+       if (ret != size) {
+           free_DigestInfo(&di);
+           return -4;
+       }
+
+       if (flen != di.digest.length || memcmp(di.digest.data, from, flen) != 0) {
+           free_DigestInfo(&di);
+           return -5;
+       }
+
+       if (type == NID_sha1) {
+           digest_alg = &_signature_sha1_data;
+       } else if (type == NID_md5) {
+           digest_alg = &_signature_md5_data;
+       } else if (type == NID_sha256) {
+           digest_alg = &_signature_sha256_data;
+       } else {
+           free_DigestInfo(&di);
+           return -1;
+       }
+       
+       ret = der_heim_oid_cmp(&digest_alg->algorithm,
+                              &di.digestAlgorithm.algorithm);
+       free_DigestInfo(&di);
+       
+       if (ret != 0)
+           return 0;
+       return 1;
+    }
+
+    return 0;
 }
 
 /*
@@ -380,12 +515,12 @@ RSA_null_method(void)
     return &rsa_null_method;
 }
 
+extern const RSA_METHOD hc_rsa_gmp_method;
 extern const RSA_METHOD hc_rsa_imath_method;
-#ifdef HAVE_GMP
-static const RSA_METHOD *default_rsa_method = &hc_rsa_gmp_method;
-#else
-static const RSA_METHOD *default_rsa_method = &hc_rsa_imath_method;
-#endif
+extern const RSA_METHOD hc_rsa_tfm_method;
+extern const RSA_METHOD hc_rsa_ltm_method;
+static const RSA_METHOD *default_rsa_method = &hc_rsa_ltm_method;
+
 
 const RSA_METHOD *
 RSA_get_default_method(void)
@@ -403,32 +538,6 @@ RSA_set_default_method(const RSA_METHOD *meth)
  *
  */
 
-static BIGNUM *
-heim_int2BN(const heim_integer *i)
-{
-    BIGNUM *bn;
-
-    bn = BN_bin2bn(i->data, i->length, NULL);
-    if (bn)
-       BN_set_negative(bn, i->negative);
-    return bn;
-}
-
-static int
-bn2heim_int(BIGNUM *bn, heim_integer *integer)
-{
-    integer->length = BN_num_bytes(bn);
-    integer->data = malloc(integer->length);
-    if (integer->data == NULL) {
-       integer->length = 0;
-       return ENOMEM;
-    }
-    BN_bn2bin(bn, integer->data);
-    integer->negative = BN_is_negative(bn);
-    return 0;
-}
-
-
 RSA *
 d2i_RSAPrivateKey(RSA *rsa, const unsigned char **pp, size_t len)
 {
@@ -451,14 +560,14 @@ d2i_RSAPrivateKey(RSA *rsa, const unsigned char **pp, size_t len)
        }
     }
 
-    k->n = heim_int2BN(&data.modulus);
-    k->e = heim_int2BN(&data.publicExponent);
-    k->d = heim_int2BN(&data.privateExponent);
-    k->p = heim_int2BN(&data.prime1);
-    k->q = heim_int2BN(&data.prime2);
-    k->dmp1 = heim_int2BN(&data.exponent1);
-    k->dmq1 = heim_int2BN(&data.exponent2);
-    k->iqmp = heim_int2BN(&data.coefficient);
+    k->n = _hc_integer_to_BN(&data.modulus, NULL);
+    k->e = _hc_integer_to_BN(&data.publicExponent, NULL);
+    k->d = _hc_integer_to_BN(&data.privateExponent, NULL);
+    k->p = _hc_integer_to_BN(&data.prime1, NULL);
+    k->q = _hc_integer_to_BN(&data.prime2, NULL);
+    k->dmp1 = _hc_integer_to_BN(&data.exponent1, NULL);
+    k->dmq1 = _hc_integer_to_BN(&data.exponent2, NULL);
+    k->iqmp = _hc_integer_to_BN(&data.coefficient, NULL);
     free_RSAPrivateKey(&data);
 
     if (k->n == NULL || k->e == NULL || k->d == NULL || k->p == NULL ||
@@ -485,14 +594,14 @@ i2d_RSAPrivateKey(RSA *rsa, unsigned char **pp)
 
     memset(&data, 0, sizeof(data));
 
-    ret  = bn2heim_int(rsa->n, &data.modulus);
-    ret |= bn2heim_int(rsa->e, &data.publicExponent);
-    ret |= bn2heim_int(rsa->d, &data.privateExponent);
-    ret |= bn2heim_int(rsa->p, &data.prime1);
-    ret |= bn2heim_int(rsa->q, &data.prime2);
-    ret |= bn2heim_int(rsa->dmp1, &data.exponent1);
-    ret |= bn2heim_int(rsa->dmq1, &data.exponent2);
-    ret |= bn2heim_int(rsa->iqmp, &data.coefficient);
+    ret  = _hc_BN_to_integer(rsa->n, &data.modulus);
+    ret |= _hc_BN_to_integer(rsa->e, &data.publicExponent);
+    ret |= _hc_BN_to_integer(rsa->d, &data.privateExponent);
+    ret |= _hc_BN_to_integer(rsa->p, &data.prime1);
+    ret |= _hc_BN_to_integer(rsa->q, &data.prime2);
+    ret |= _hc_BN_to_integer(rsa->dmp1, &data.exponent1);
+    ret |= _hc_BN_to_integer(rsa->dmq1, &data.exponent2);
+    ret |= _hc_BN_to_integer(rsa->iqmp, &data.coefficient);
     if (ret) {
        free_RSAPrivateKey(&data);
        return -1;
@@ -530,8 +639,8 @@ i2d_RSAPublicKey(RSA *rsa, unsigned char **pp)
 
     memset(&data, 0, sizeof(data));
 
-    if (bn2heim_int(rsa->n, &data.modulus) ||
-       bn2heim_int(rsa->e, &data.publicExponent))
+    if (_hc_BN_to_integer(rsa->n, &data.modulus) ||
+       _hc_BN_to_integer(rsa->e, &data.publicExponent))
     {
        free_RSAPublicKey(&data);
        return -1;
@@ -582,8 +691,8 @@ d2i_RSAPublicKey(RSA *rsa, const unsigned char **pp, size_t len)
        }
     }
 
-    k->n = heim_int2BN(&data.modulus);
-    k->e = heim_int2BN(&data.publicExponent);
+    k->n = _hc_integer_to_BN(&data.modulus, NULL);
+    k->e = _hc_integer_to_BN(&data.publicExponent, NULL);
 
     free_RSAPublicKey(&data);
 
index 9354aaaa48ecf4242cbf81dbc4563a3ffac3af30..3fd805fcf07fb7afe3b388831310ec2f586bfc66 100644 (file)
@@ -41,7 +41,9 @@
 /* symbol renaming */
 #define RSA_null_method hc_RSA_null_method
 #define RSA_imath_method hc_RSA_imath_method
+#define RSA_ltm_method hc_RSA_ltm_method
 #define RSA_gmp_method hc_RSA_gmp_method
+#define RSA_tfm_method hc_RSA_tfm_method
 #define RSA_new hc_RSA_new
 #define RSA_new_method hc_RSA_new_method
 #define RSA_free hc_RSA_free
@@ -136,6 +138,8 @@ struct RSA {
 const RSA_METHOD *RSA_null_method(void);
 const RSA_METHOD *RSA_imath_method(void);
 const RSA_METHOD *RSA_gmp_method(void);
+const RSA_METHOD *RSA_tfm_method(void);
+const RSA_METHOD *RSA_ltm_method(void);
 
 /*
  *
@@ -153,7 +157,7 @@ const RSA_METHOD * RSA_get_method(const RSA *);
 int RSA_set_method(RSA *, const RSA_METHOD *);
 
 int    RSA_set_app_data(RSA *, void *arg);
-void * RSA_get_app_data(RSA *);
+void * RSA_get_app_data(const RSA *);
 
 int    RSA_check_key(const RSA *);
 int    RSA_size(const RSA *);
index 062f70509c024e83b0d4b3933bfc83bb8b1d029e..9c8b39e2419006ad51b7bfef27ffaa54294ac32a 100644 (file)
@@ -240,13 +240,13 @@ SHA1_Update (struct sha *m, const void *v, size_t len)
     if(offset == 64){
 #if !defined(WORDS_BIGENDIAN) || defined(_CRAY)
       int i;
-      uint32_t current[16];
-      struct x32 *u = (struct x32*)m->save;
+      uint32_t SHA1current[16];
+      struct x32 *us = (struct x32*)m->save;
       for(i = 0; i < 8; i++){
-       current[2*i+0] = swap_uint32_t(u[i].a);
-       current[2*i+1] = swap_uint32_t(u[i].b);
+       SHA1current[2*i+0] = swap_uint32_t(us[i].a);
+       SHA1current[2*i+1] = swap_uint32_t(us[i].b);
       }
-      calc(m, current);
+      calc(m, SHA1current);
 #else
       calc(m, (uint32_t*)m->save);
 #endif
index baa87d15ff0259d888ac85c4c4bcc8dd0277d3ba..5e601bb358c20139b665feeafed0f81de36b7b81 100644 (file)
@@ -183,10 +183,10 @@ SHA256_Update (SHA256_CTX *m, const void *v, size_t len)
 #if !defined(WORDS_BIGENDIAN) || defined(_CRAY)
            int i;
            uint32_t current[16];
-           struct x32 *u = (struct x32*)m->save;
+           struct x32 *us = (struct x32*)m->save;
            for(i = 0; i < 8; i++){
-               current[2*i+0] = swap_uint32_t(u[i].a);
-               current[2*i+1] = swap_uint32_t(u[i].b);
+               current[2*i+0] = swap_uint32_t(us[i].a);
+               current[2*i+1] = swap_uint32_t(us[i].b);
            }
            calc(m, current);
 #else
index f6f8a1ffe28b2cef34c1cd7804ba3b6a72bf42cf..e32bb9a0bec4bf4031875556b5110021b4fddbc0 100644 (file)
@@ -77,7 +77,7 @@ read_string(const char *preprompt, const char *prompt,
     p = buf;
     while(intr_flag == 0){
        c = ((echo)? _getche(): _getch());
-       if(c == '\n')
+       if(c == '\n' || c == '\r')
            break;
        if(of == 0)
            *p++ = c;
diff --git a/source4/heimdal/lib/hcrypto/validate.c b/source4/heimdal/lib/hcrypto/validate.c
new file mode 100644 (file)
index 0000000..3ed358d
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2010 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getarg.h>
+#include <roken.h>
+
+#include <evp.h>
+#include <hmac.h>
+#include <err.h>
+
+struct tests {
+    const EVP_CIPHER *(*cipher)(void);
+    const char *name;
+    void *key;
+    size_t keysize;
+    void *iv;
+    size_t datasize;
+    void *indata;
+    void *outdata;
+    void *outiv;
+};
+
+struct tests tests[] = {
+    {
+       EVP_aes_256_cbc,
+       "aes-256",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       32,
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\xdc\x95\xc0\x78\xa2\x40\x89\x89\xad\x48\xa2\x14\x92\x84\x20\x87"
+    },
+#if 0
+    { 
+       EVP_aes_128_cfb8,
+       "aes-cfb8-128",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x66\xe9\x4b\xd4\xef\x8a\x2c\x3b\x88\x4c\xfa\x59\xca\x34\x2b\x2e"
+    },
+#endif
+    {
+       EVP_des_ede3_cbc,
+       "des-ede3",
+       "\x19\x17\xff\xe6\xbb\x77\x2e\xfc"
+       "\x29\x76\x43\xbc\x63\x56\x7e\x9a"
+       "\x00\x2e\x4d\x43\x1d\x5f\xfd\x58",
+       24,
+       "\xbf\x9a\x12\xb7\x26\x69\xfd\x05",
+       16,
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x55\x95\x97\x76\xa9\x6c\x66\x40\x64\xc7\xf4\x1c\x21\xb7\x14\x1b"
+    },
+#if 0
+    { 
+       EVP_camellia_128_cbc,
+       "camellia128",
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x07\x92\x3A\x39\xEB\x0A\x81\x7D\x1C\x4D\x87\xBD\xB8\x2D\x1F\x1C",
+       NULL
+    },
+#endif
+    { 
+       EVP_rc4,
+       "rc4 8",
+       "\x01\x23\x45\x67\x89\xAB\xCD\xEF",
+       8,
+       NULL,
+       8,
+       "\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x74\x94\xC2\xE7\x10\x4B\x08\x79",
+       NULL
+    },
+    {
+       EVP_rc4,
+       "rc4 5",
+       "\x61\x8a\x63\xd2\xfb",
+       5,
+       NULL,
+       5,
+       "\xdc\xee\x4c\xf9\x2c",
+       "\xf1\x38\x29\xc9\xde",
+       NULL
+    },
+    {
+       EVP_rc4,
+       "rc4 309",
+       "\x29\x04\x19\x72\xfb\x42\xba\x5f\xc7\x12\x77\x12\xf1\x38\x29\xc9",
+       16,
+       NULL,
+       309,
+       "\x52\x75\x69\x73\x6c\x69\x6e\x6e"
+       "\x75\x6e\x20\x6c\x61\x75\x6c\x75"
+       "\x20\x6b\x6f\x72\x76\x69\x73\x73"
+       "\x73\x61\x6e\x69\x2c\x20\x74\xe4"
+       "\x68\x6b\xe4\x70\xe4\x69\x64\x65"
+       "\x6e\x20\x70\xe4\xe4\x6c\x6c\xe4"
+       "\x20\x74\xe4\x79\x73\x69\x6b\x75"
+       "\x75\x2e\x20\x4b\x65\x73\xe4\x79"
+       "\xf6\x6e\x20\x6f\x6e\x20\x6f\x6e"
+       "\x6e\x69\x20\x6f\x6d\x61\x6e\x61"
+       "\x6e\x69\x2c\x20\x6b\x61\x73\x6b"
+       "\x69\x73\x61\x76\x75\x75\x6e\x20"
+       "\x6c\x61\x61\x6b\x73\x6f\x74\x20"
+       "\x76\x65\x72\x68\x6f\x75\x75\x2e"
+       "\x20\x45\x6e\x20\x6d\x61\x20\x69"
+       "\x6c\x6f\x69\x74\x73\x65\x2c\x20"
+       "\x73\x75\x72\x65\x20\x68\x75\x6f"
+       "\x6b\x61\x61\x2c\x20\x6d\x75\x74"
+       "\x74\x61\x20\x6d\x65\x74\x73\xe4"
+       "\x6e\x20\x74\x75\x6d\x6d\x75\x75"
+       "\x73\x20\x6d\x75\x6c\x6c\x65\x20"
+       "\x74\x75\x6f\x6b\x61\x61\x2e\x20"
+       "\x50\x75\x75\x6e\x74\x6f\x20\x70"
+       "\x69\x6c\x76\x65\x6e\x2c\x20\x6d"
+       "\x69\x20\x68\x75\x6b\x6b\x75\x75"
+       "\x2c\x20\x73\x69\x69\x6e\x74\x6f"
+       "\x20\x76\x61\x72\x61\x6e\x20\x74"
+       "\x75\x75\x6c\x69\x73\x65\x6e\x2c"
+       "\x20\x6d\x69\x20\x6e\x75\x6b\x6b"
+       "\x75\x75\x2e\x20\x54\x75\x6f\x6b"
+       "\x73\x75\x74\x20\x76\x61\x6e\x61"
+       "\x6d\x6f\x6e\x20\x6a\x61\x20\x76"
+       "\x61\x72\x6a\x6f\x74\x20\x76\x65"
+       "\x65\x6e\x2c\x20\x6e\x69\x69\x73"
+       "\x74\xe4\x20\x73\x79\x64\xe4\x6d"
+       "\x65\x6e\x69\x20\x6c\x61\x75\x6c"
+       "\x75\x6e\x20\x74\x65\x65\x6e\x2e"
+       "\x20\x2d\x20\x45\x69\x6e\x6f\x20"
+       "\x4c\x65\x69\x6e\x6f",
+       "\x35\x81\x86\x99\x90\x01\xe6\xb5"
+       "\xda\xf0\x5e\xce\xeb\x7e\xee\x21"
+       "\xe0\x68\x9c\x1f\x00\xee\xa8\x1f"
+       "\x7d\xd2\xca\xae\xe1\xd2\x76\x3e"
+       "\x68\xaf\x0e\xad\x33\xd6\x6c\x26"
+       "\x8b\xc9\x46\xc4\x84\xfb\xe9\x4c"
+       "\x5f\x5e\x0b\x86\xa5\x92\x79\xe4"
+       "\xf8\x24\xe7\xa6\x40\xbd\x22\x32"
+       "\x10\xb0\xa6\x11\x60\xb7\xbc\xe9"
+       "\x86\xea\x65\x68\x80\x03\x59\x6b"
+       "\x63\x0a\x6b\x90\xf8\xe0\xca\xf6"
+       "\x91\x2a\x98\xeb\x87\x21\x76\xe8"
+       "\x3c\x20\x2c\xaa\x64\x16\x6d\x2c"
+       "\xce\x57\xff\x1b\xca\x57\xb2\x13"
+       "\xf0\xed\x1a\xa7\x2f\xb8\xea\x52"
+       "\xb0\xbe\x01\xcd\x1e\x41\x28\x67"
+       "\x72\x0b\x32\x6e\xb3\x89\xd0\x11"
+       "\xbd\x70\xd8\xaf\x03\x5f\xb0\xd8"
+       "\x58\x9d\xbc\xe3\xc6\x66\xf5\xea"
+       "\x8d\x4c\x79\x54\xc5\x0c\x3f\x34"
+       "\x0b\x04\x67\xf8\x1b\x42\x59\x61"
+       "\xc1\x18\x43\x07\x4d\xf6\x20\xf2"
+       "\x08\x40\x4b\x39\x4c\xf9\xd3\x7f"
+       "\xf5\x4b\x5f\x1a\xd8\xf6\xea\x7d"
+       "\xa3\xc5\x61\xdf\xa7\x28\x1f\x96"
+       "\x44\x63\xd2\xcc\x35\xa4\xd1\xb0"
+       "\x34\x90\xde\xc5\x1b\x07\x11\xfb"
+       "\xd6\xf5\x5f\x79\x23\x4d\x5b\x7c"
+       "\x76\x66\x22\xa6\x6d\xe9\x2b\xe9"
+       "\x96\x46\x1d\x5e\x4d\xc8\x78\xef"
+       "\x9b\xca\x03\x05\x21\xe8\x35\x1e"
+       "\x4b\xae\xd2\xfd\x04\xf9\x46\x73"
+       "\x68\xc4\xad\x6a\xc1\x86\xd0\x82"
+       "\x45\xb2\x63\xa2\x66\x6d\x1f\x6c"
+       "\x54\x20\xf1\x59\x9d\xfd\x9f\x43"
+       "\x89\x21\xc2\xf5\xa4\x63\x93\x8c"
+       "\xe0\x98\x22\x65\xee\xf7\x01\x79"
+       "\xbc\x55\x3f\x33\x9e\xb1\xa4\xc1"
+       "\xaf\x5f\x6a\x54\x7f"
+    }
+};
+
+static int
+test_cipher(struct tests *t)
+{
+    const EVP_CIPHER *c = t->cipher();
+    EVP_CIPHER_CTX ectx;
+    EVP_CIPHER_CTX dctx;
+    void *d;
+
+    EVP_CIPHER_CTX_init(&ectx);
+    EVP_CIPHER_CTX_init(&dctx);
+
+    if (EVP_CipherInit_ex(&ectx, c, NULL, NULL, NULL, 1) != 1)
+       errx(1, "%s: EVP_CipherInit_ex einit", t->name);
+    if (EVP_CipherInit_ex(&dctx, c, NULL, NULL, NULL, 0) != 1)
+       errx(1, "%s: EVP_CipherInit_ex dinit", t->name);
+
+    EVP_CIPHER_CTX_set_key_length(&ectx, t->keysize);
+    EVP_CIPHER_CTX_set_key_length(&dctx, t->keysize);
+
+    if (EVP_CipherInit_ex(&ectx, NULL, NULL, t->key, t->iv, 1) != 1)
+       errx(1, "%s: EVP_CipherInit_ex encrypt", t->name);
+    if (EVP_CipherInit_ex(&dctx, NULL, NULL, t->key, t->iv, 0) != 1)
+       errx(1, "%s: EVP_CipherInit_ex decrypt", t->name);
+
+    d = emalloc(t->datasize);
+
+    if (!EVP_Cipher(&ectx, d, t->indata, t->datasize))
+       return 1;
+
+    if (memcmp(d, t->outdata, t->datasize) != 0)
+       errx(1, "%s: encrypt not the same", t->name);
+
+    if (!EVP_Cipher(&dctx, d, d, t->datasize))
+       return 1;
+
+    if (memcmp(d, t->indata, t->datasize) != 0)
+       errx(1, "%s: decrypt not the same", t->name);
+
+    if (t->outiv)
+       /* XXXX check  */;
+
+    EVP_CIPHER_CTX_cleanup(&ectx);
+    EVP_CIPHER_CTX_cleanup(&dctx);
+    free(d);
+
+    return 0;
+}
+
+static void
+check_hmac(void)
+{
+    unsigned char buf[4] = { 0, 0, 0, 0 };
+    char hmackey[] = "hello-world";
+    size_t hmackey_size = sizeof(hmackey);
+    unsigned int hmaclen;
+    unsigned char hmac[EVP_MAX_MD_SIZE];
+    HMAC_CTX c;
+
+    char answer[20] = "\x2c\xfa\x32\xb7\x2b\x8a\xf6\xdf\xcf\xda"
+                     "\x6f\xd1\x52\x4d\x54\x58\x73\x0f\xf3\x24";
+
+    HMAC_CTX_init(&c);
+    HMAC_Init_ex(&c, hmackey, hmackey_size, EVP_sha1(), NULL);
+    HMAC_Update(&c, buf, sizeof(buf));
+    HMAC_Final(&c, hmac, &hmaclen);
+    HMAC_CTX_cleanup(&c);
+
+    if (hmaclen != 20)
+       errx(1, "hmaclen = %d\n", (int)hmaclen);
+
+    if (ct_memcmp(hmac, answer, hmaclen) != 0)
+       errx(1, "wrong answer\n");
+}
+
+void
+hcrypto_validate(void)
+{
+    static int validated = 0;
+    unsigned int i;
+
+    /* its ok to run this twice, do don't check for races */
+    if (validated)
+       return;
+    validated++;
+
+    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
+       test_cipher(&tests[i]);
+
+    check_hmac();
+}
index faf0b6bdf29149227bb5dfc4afb50ad074e923d6..fb32fdb845e644e0562e6a7bcc43dcaf6c9bc4de 100644 (file)
@@ -316,7 +316,7 @@ hdb_entry_get_password(krb5_context context, HDB *db,
 
        str = pw.data;
        if (str[pw.length - 1] != '\0') {
-           krb5_set_error_message(context, EINVAL, "password malformated");
+           krb5_set_error_message(context, EINVAL, "malformed password");
            return EINVAL;
        }
 
@@ -332,7 +332,8 @@ hdb_entry_get_password(krb5_context context, HDB *db,
 
     ret = krb5_unparse_name(context, entry->principal, &str);
     if (ret == 0) {
-       krb5_set_error_message(context, ENOENT, "no password attributefor %s", str);
+       krb5_set_error_message(context, ENOENT,
+                              "no password attribute for %s", str);
        free(str);
     } else
        krb5_clear_error_message(context);
index 120dbfb9fa13a8f2a3aa116f4adc1dc6cecec976..2cad4daba41478c57e511f503e5859bb3e75ae74 100644 (file)
@@ -24,6 +24,7 @@ error_code EXISTS,            "Entry already exists in database"
 error_code BADVERSION,         "Wrong database version"
 error_code NO_MKEY,            "No correct master key"
 error_code MANDATORY_OPTION,   "Entry contains unknown mandatory extension"
+error_code NO_WRITE_SUPPORT,   "HDB backend doesn't contain write support"
 error_code NOT_FOUND_HERE,     "The secret for this entry is not replicated to this database"
 
 end
index 524cea6f4589d220ee779c2e74bb82a3f2d31b9f..efaed7f420fba65549c0d888ca27430667486735 100644 (file)
@@ -52,7 +52,7 @@ struct hdb_cursor {
  * HDB:[HDBFORMAT:database-specific-data[:mkey=mkey-file]]
  */
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 hdb_resolve(krb5_context context, const char *name, krb5_keytab id)
 {
     struct hdb_data *d;
@@ -99,7 +99,7 @@ hdb_resolve(krb5_context context, const char *name, krb5_keytab id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 hdb_close(krb5_context context, krb5_keytab id)
 {
     struct hdb_data *d = id->data;
@@ -110,7 +110,7 @@ hdb_close(krb5_context context, krb5_keytab id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 hdb_get_name(krb5_context context,
             krb5_keytab id,
             char *name,
@@ -169,7 +169,7 @@ find_db (krb5_context context,
  * it in `entry'.  return 0 or an error code
  */
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 hdb_get_entry(krb5_context context,
              krb5_keytab id,
              krb5_const_principal principal,
@@ -256,7 +256,7 @@ hdb_get_entry(krb5_context context,
  * it in `entry'.  return 0 or an error code
  */
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 hdb_start_seq_get(krb5_context context,
                  krb5_keytab id,
                  krb5_kt_cursor *cursor)
@@ -309,7 +309,7 @@ hdb_start_seq_get(krb5_context context,
     return ret;
 }
 
-static int
+static int KRB5_CALLCONV
 hdb_next_entry(krb5_context context,
               krb5_keytab id,
               krb5_keytab_entry *entry,
@@ -391,7 +391,7 @@ hdb_next_entry(krb5_context context,
 }
 
 
-static int
+static int KRB5_CALLCONV
 hdb_end_seq_get(krb5_context context,
                krb5_keytab id,
                krb5_kt_cursor *cursor)
index 360bb33a3a1f6c605a7ec6430a01f20c62628e1e..760eccfd430733ebe93c4552bde278fb8acfc390 100644 (file)
@@ -146,7 +146,7 @@ read_master_keytab(krb5_context context, const char *filename,
 /* read a MIT master keyfile */
 static krb5_error_code
 read_master_mit(krb5_context context, const char *filename,
-               hdb_master_key *mkey)
+               int byteorder, hdb_master_key *mkey)
 {
     int fd;
     krb5_error_code ret;
@@ -166,20 +166,16 @@ read_master_mit(krb5_context context, const char *filename,
        close(fd);
        return errno;
     }
-    krb5_storage_set_flags(sp, KRB5_STORAGE_HOST_BYTEORDER);
+    krb5_storage_set_flags(sp, byteorder);
     /* could possibly use ret_keyblock here, but do it with more
        checks for now */
     {
        ret = krb5_ret_int16(sp, &enctype);
        if (ret)
            goto out;
-       if((htons(enctype) & 0xff00) == 0x3000) {
-           ret = HEIM_ERR_BAD_MKEY;
-           krb5_set_error_message(context, ret, "unknown keytype in %s: "
-                                  "%#x, expected %#x",
-                                  filename, htons(enctype), 0x3000);
-           goto out;
-       }
+       ret = krb5_enctype_valid(context, enctype);
+       if (ret)
+          goto out;
        key.keytype = enctype;
        ret = krb5_ret_data(sp, &key.keyvalue);
        if(ret)
@@ -330,7 +326,14 @@ hdb_read_master_key(krb5_context context, const char *filename,
     } else if(buf[0] == 5 && buf[1] >= 1 && buf[1] <= 2) {
        ret = read_master_keytab(context, filename, mkey);
     } else {
-       ret = read_master_mit(context, filename, mkey);
+      /*
+       * Check both LittleEndian and BigEndian since they key file
+       * might be moved from a machine with diffrent byte order, or
+       * its running on MacOS X that always uses BE master keys.
+       */
+      ret = read_master_mit(context, filename, KRB5_STORAGE_BYTEORDER_LE, mkey);
+      if (ret)
+          ret = read_master_mit(context, filename, KRB5_STORAGE_BYTEORDER_BE, mkey);
     }
     return ret;
 }
index bad3c497428bab2cacb963ae9de76337503231dd..2a57d2ac27dd0a3a3454dd0e4c91731f1c5ea35a 100644 (file)
 
 #if defined(HAVE_GDBM_NDBM_H)
 #include <gdbm/ndbm.h>
+#define WRITE_SUPPORT 1
 #elif defined(HAVE_NDBM_H)
 #include <ndbm.h>
 #elif defined(HAVE_DBM_H)
+#define WRITE_SUPPORT 1
 #include <dbm.h>
 #endif
 
@@ -243,6 +245,7 @@ static krb5_error_code
 NDBM__put(krb5_context context, HDB *db, int replace,
        krb5_data key, krb5_data value)
 {
+#ifdef WRITE_SUPPORT
     struct ndbm_db *d = (struct ndbm_db *)db->hdb_db;
     datum k, v;
     int code;
@@ -262,6 +265,9 @@ NDBM__put(krb5_context context, HDB *db, int replace,
     if (code < 0)
        return code;
     return 0;
+#else
+    return HDB_ERR_NO_WRITE_SUPPORT;
+#endif
 }
 
 static krb5_error_code
index 8ec6eae22a6398b46243ba426b66206edd363d23..492064d86d7d940a712e467fe4db173d6e228209 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2010 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
  * All rights reserved.
  *
@@ -53,11 +53,15 @@ struct hx509_ca_tbs {
        unsigned int key:1;
        unsigned int serial:1;
        unsigned int domaincontroller:1;
+       unsigned int xUniqueID:1;
     } flags;
     time_t notBefore;
     time_t notAfter;
     int pathLenConstraint; /* both for CA and Proxy */
     CRLDistributionPoints crldp;
+    heim_bit_string subjectUniqueID;
+    heim_bit_string issuerUniqueID;
+
 };
 
 /**
@@ -80,15 +84,6 @@ hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
     if (*tbs == NULL)
        return ENOMEM;
 
-    (*tbs)->subject = NULL;
-    (*tbs)->san.len = 0;
-    (*tbs)->san.val = NULL;
-    (*tbs)->eku.len = 0;
-    (*tbs)->eku.val = NULL;
-    (*tbs)->pathLenConstraint = 0;
-    (*tbs)->crldp.len = 0;
-    (*tbs)->crldp.val = NULL;
-
     return 0;
 }
 
@@ -111,7 +106,8 @@ hx509_ca_tbs_free(hx509_ca_tbs *tbs)
     free_ExtKeyUsage(&(*tbs)->eku);
     der_free_heim_integer(&(*tbs)->serial);
     free_CRLDistributionPoints(&(*tbs)->crldp);
-
+    der_free_bit_string(&(*tbs)->subjectUniqueID);
+    der_free_bit_string(&(*tbs)->issuerUniqueID);
     hx509_name_free(&(*tbs)->subject);
 
     memset(*tbs, 0, sizeof(**tbs));
@@ -485,7 +481,8 @@ hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
        name.u.fullName.val = &gn;
 
        gn.element = choice_GeneralName_uniformResourceIdentifier;
-       gn.u.uniformResourceIdentifier = rk_UNCONST(uri);
+       gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
+       gn.u.uniformResourceIdentifier.length = strlen(uri);
 
        ASN1_MALLOC_ENCODE(DistributionPointName,
                           dp.distributionPoint->data,
@@ -785,7 +782,8 @@ hx509_ca_tbs_add_san_hostname(hx509_context context,
 
     memset(&gn, 0, sizeof(gn));
     gn.element = choice_GeneralName_dNSName;
-    gn.u.dNSName = rk_UNCONST(dnsname);
+    gn.u.dNSName.data = rk_UNCONST(dnsname);
+    gn.u.dNSName.length = strlen(dnsname);
 
     return add_GeneralNames(&tbs->san, &gn);
 }
@@ -812,7 +810,8 @@ hx509_ca_tbs_add_san_rfc822name(hx509_context context,
 
     memset(&gn, 0, sizeof(gn));
     gn.element = choice_GeneralName_rfc822Name;
-    gn.u.rfc822Name = rk_UNCONST(rfc822Name);
+    gn.u.rfc822Name.data = rk_UNCONST(rfc822Name);
+    gn.u.rfc822Name.length = strlen(rfc822Name);
 
     return add_GeneralNames(&tbs->san, &gn);
 }
@@ -839,6 +838,50 @@ hx509_ca_tbs_set_subject(hx509_context context,
     return hx509_name_copy(context, subject, &tbs->subject);
 }
 
+/**
+ * Set the issuerUniqueID and subjectUniqueID
+ *
+ * These are only supposed to be used considered with version 2
+ * certificates, replaced by the two extensions SubjectKeyIdentifier
+ * and IssuerKeyIdentifier. This function is to allow application
+ * using legacy protocol to issue them.
+ *
+ * @param context A hx509 context.
+ * @param tbs object to be signed.
+ * @param issuerUniqueID to be set
+ * @param subjectUniqueID to be set
+ *
+ * @return An hx509 error code, see hx509_get_error_string().
+ *
+ * @ingroup hx509_ca
+ */
+
+int
+hx509_ca_tbs_set_unique(hx509_context context,
+                       hx509_ca_tbs tbs,
+                       const heim_bit_string *subjectUniqueID,
+                       const heim_bit_string *issuerUniqueID)
+{
+    int ret;
+
+    der_free_bit_string(&tbs->subjectUniqueID);
+    der_free_bit_string(&tbs->issuerUniqueID);
+    
+    if (subjectUniqueID) {
+       ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
+       if (ret)
+           return ret;
+    }
+
+    if (issuerUniqueID) {
+       ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
+       if (ret)
+           return ret;
+    }
+
+    return 0;
+}
+
 /**
  * Expand the the subject name in the to-be-signed certificate object
  * using hx509_name_expand().
@@ -861,6 +904,10 @@ hx509_ca_tbs_subject_expand(hx509_context context,
     return hx509_name_expand(context, tbs->subject, env);
 }
 
+/*
+ *
+ */
+
 static int
 add_extension(hx509_context context,
              TBSCertificate *tbsc,
@@ -1090,7 +1137,35 @@ ca_sign(hx509_context context,
        goto out;
     }
     /* issuerUniqueID  [1]  IMPLICIT BIT STRING OPTIONAL */
+    if (tbs->issuerUniqueID.length) {
+       tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
+       if (tbsc->issuerUniqueID == NULL) {
+           ret = ENOMEM;
+           hx509_set_error_string(context, 0, ret, "Out of memory");
+           goto out;
+       }
+       ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
+       if (ret) {
+           hx509_set_error_string(context, 0, ret, "Out of memory");
+           goto out;
+       }
+    }
     /* subjectUniqueID [2]  IMPLICIT BIT STRING OPTIONAL */
+    if (tbs->subjectUniqueID.length) {
+       tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
+       if (tbsc->subjectUniqueID == NULL) {
+           ret = ENOMEM;
+           hx509_set_error_string(context, 0, ret, "Out of memory");
+           goto out;
+       }
+
+       ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
+       if (ret) {
+           hx509_set_error_string(context, 0, ret, "Out of memory");
+           goto out;
+       }
+    }
+
     /* extensions      [3]  EXPLICIT Extensions OPTIONAL */
     tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
     if (tbsc->extensions == NULL) {
index 4783edd681339c75da08ad46c9bbf709c341a1e6..93a172e553045e5bff1b7af0201f0364c1037525 100644 (file)
@@ -1510,6 +1510,65 @@ hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context,
     return ret;
 }
 
+static int
+get_x_unique_id(hx509_context context, const char *name, 
+               const heim_bit_string *cert, heim_bit_string *subject)
+{
+    int ret;
+
+    if (cert == NULL) {
+       ret = HX509_EXTENSION_NOT_FOUND;
+       hx509_set_error_string(context, 0, ret, "%s unique id doesn't exists", name);
+       return ret;
+    }
+    ret = der_copy_bit_string(cert, subject);
+    if (ret) {
+       hx509_set_error_string(context, 0, ret, "malloc out of memory", name);
+       return ret;
+    }
+    return 0;
+}
+
+/**
+ * Get a copy of the Issuer Unique ID
+ *
+ * @param context a hx509_context
+ * @param p a hx509 certificate
+ * @param issuer the issuer id returned, free with der_free_bit_string()
+ *
+ * @return An hx509 error code, see hx509_get_error_string(). The
+ * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
+ * doesn't have a issuerUniqueID
+ *
+ * @ingroup hx509_cert
+ */
+
+int
+hx509_cert_get_issuer_unique_id(hx509_context context, hx509_cert p, heim_bit_string *issuer)
+{
+    return get_x_unique_id(context, "issuer", p->data->tbsCertificate.issuerUniqueID, issuer);
+}
+
+/**
+ * Get a copy of the Subect Unique ID
+ *
+ * @param context a hx509_context
+ * @param p a hx509 certificate
+ * @param subject the subject id returned, free with der_free_bit_string()
+ *
+ * @return An hx509 error code, see hx509_get_error_string(). The
+ * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
+ * doesn't have a subjectUniqueID
+ *
+ * @ingroup hx509_cert
+ */
+
+int
+hx509_cert_get_subject_unique_id(hx509_context context, hx509_cert p, heim_bit_string *subject)
+{
+    return get_x_unique_id(context, "subject", p->data->tbsCertificate.subjectUniqueID, subject);
+}
+
 
 hx509_private_key
 _hx509_cert_private_key(hx509_cert p)
@@ -1696,19 +1755,20 @@ match_general_name(const GeneralName *c, const GeneralName *n, int *match)
     case choice_GeneralName_rfc822Name: {
        const char *s;
        size_t len1, len2;
-       s = strchr(c->u.rfc822Name, '@');
+       s = memchr(c->u.rfc822Name.data, '@', c->u.rfc822Name.length);
        if (s) {
-           if (strcasecmp(c->u.rfc822Name, n->u.rfc822Name) != 0)
+           if (der_printable_string_cmp(&c->u.rfc822Name, &n->u.rfc822Name) != 0)
                return HX509_NAME_CONSTRAINT_ERROR;
        } else {
-           s = strchr(n->u.rfc822Name, '@');
+           s = memchr(n->u.rfc822Name.data, '@', n->u.rfc822Name.length);
            if (s == NULL)
                return HX509_NAME_CONSTRAINT_ERROR;
-           len1 = strlen(c->u.rfc822Name);
-           len2 = strlen(s + 1);
+           len1 = c->u.rfc822Name.length;
+           len2 = n->u.rfc822Name.length -
+               (s - ((char *)n->u.rfc822Name.data));
            if (len1 > len2)
                return HX509_NAME_CONSTRAINT_ERROR;
-           if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 0)
+           if (memcmp(s + 1 + len2 - len1, c->u.rfc822Name.data, len1) != 0)
                return HX509_NAME_CONSTRAINT_ERROR;
            if (len1 < len2 && s[len2 - len1 + 1] != '.')
                return HX509_NAME_CONSTRAINT_ERROR;
@@ -1718,14 +1778,16 @@ match_general_name(const GeneralName *c, const GeneralName *n, int *match)
     }
     case choice_GeneralName_dNSName: {
        size_t lenc, lenn;
+       char *ptr;
 
-       lenc = strlen(c->u.dNSName);
-       lenn = strlen(n->u.dNSName);
+       lenc = c->u.dNSName.length;
+       lenn = n->u.dNSName.length;
        if (lenc > lenn)
            return HX509_NAME_CONSTRAINT_ERROR;
-       if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0)
+       ptr = n->u.dNSName.data;
+       if (memcmp(&ptr[lenn - lenc], c->u.dNSName.data, lenc) != 0)
            return HX509_NAME_CONSTRAINT_ERROR;
-       if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.')
+       if (lenn != lenc && ptr[lenn - lenc - 1] != '.')
            return HX509_NAME_CONSTRAINT_ERROR;
        *match = 1;
        return 0;
@@ -2405,12 +2467,17 @@ hx509_verify_hostname(hx509_context context,
 
        for (j = 0; j < san.len; j++) {
            switch (san.val[j].element) {
-           case choice_GeneralName_dNSName:
-               if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) {
+           case choice_GeneralName_dNSName: {
+               heim_printable_string hn;
+               hn.data = rk_UNCONST(hostname);
+               hn.length = strlen(hostname);
+               
+               if (der_printable_string_cmp(&san.val[j].u.dNSName, &hn) == 0) {
                    free_GeneralNames(&san);
                    return 0;
                }
                break;
+           }
            default:
                break;
            }
@@ -2428,14 +2495,24 @@ hx509_verify_hostname(hx509_context context,
            if (der_heim_oid_cmp(&n->type, &asn1_oid_id_at_commonName) == 0) {
                DirectoryString *ds = &n->value;
                switch (ds->element) {
-               case choice_DirectoryString_printableString:
-                   if (strcasecmp(ds->u.printableString, hostname) == 0)
+               case choice_DirectoryString_printableString: {
+                   heim_printable_string hn;
+                   hn.data = rk_UNCONST(hostname);
+                   hn.length = strlen(hostname);
+
+                   if (der_printable_string_cmp(&ds->u.printableString, &hn) == 0)
                        return 0;
                    break;
-               case choice_DirectoryString_ia5String:
-                   if (strcasecmp(ds->u.ia5String, hostname) == 0)
-                   return 0;
+               }
+               case choice_DirectoryString_ia5String: {
+                   heim_ia5_string hn;
+                   hn.data = rk_UNCONST(hostname);
+                   hn.length = strlen(hostname);
+
+                   if (der_ia5_string_cmp(&ds->u.ia5String, &hn) == 0)
+                       return 0;
                    break;
+               }
                case choice_DirectoryString_utf8String:
                    if (strcasecmp(ds->u.utf8String, hostname) == 0)
                        return 0;
diff --git a/source4/heimdal/lib/hx509/char_map.h b/source4/heimdal/lib/hx509/char_map.h
new file mode 100644 (file)
index 0000000..d2b39d0
--- /dev/null
@@ -0,0 +1,45 @@
+#define Q_CONTROL_CHAR         1
+#define Q_PRINTABLE            2
+#define Q_RFC2253_QUOTE_FIRST  4
+#define Q_RFC2253_QUOTE_LAST   8
+#define Q_RFC2253_QUOTE                16
+#define Q_RFC2253_HEX          32
+
+#define Q_RFC2253              (Q_RFC2253_QUOTE_FIRST|Q_RFC2253_QUOTE_LAST|Q_RFC2253_QUOTE|Q_RFC2253_HEX)
+
+
+
+unsigned char char_map[] = {
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x06 ,  0x00 ,  0x00 ,  0x10 ,  0x00 ,  0x00 ,  0x00 ,  0x00 ,  
+       0x00 ,  0x00 ,  0x00 ,  0x12 ,  0x12 ,  0x02 ,  0x02 ,  0x02 ,  
+       0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  
+       0x02 ,  0x02 ,  0x02 ,  0x10 ,  0x10 ,  0x12 ,  0x10 ,  0x02 ,  
+       0x00 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  
+       0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  
+       0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  
+       0x02 ,  0x02 ,  0x02 ,  0x00 ,  0x00 ,  0x00 ,  0x00 ,  0x00 ,  
+       0x00 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  
+       0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  
+       0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  0x02 ,  
+       0x02 ,  0x02 ,  0x02 ,  0x00 ,  0x00 ,  0x00 ,  0x00 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  
+       0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 ,  0x21 
+};
index 5506cee4638b8ad013331811ed138160be7e0d04..224c39086c4e064360d525c594a5b98844988116 100644 (file)
@@ -1170,6 +1170,7 @@ struct sigctx {
     heim_octet_string content;
     hx509_peer_info peer;
     int cmsidflag;
+    int leafonly;
     hx509_certs certs;
     hx509_certs anchors;
     hx509_certs pool;
@@ -1360,7 +1361,7 @@ sig_process(hx509_context context, void *ctx, hx509_cert cert)
     if (sigctx->certs) {
        unsigned int i;
 
-       if (sigctx->pool) {
+       if (sigctx->pool && sigctx->leafonly == 0) {
            _hx509_calculate_path(context,
                                  HX509_CALCULATE_PATH_NO_ANCHOR,
                                  time(NULL),
@@ -1415,6 +1416,12 @@ cert_process(hx509_context context, void *ctx, hx509_cert cert)
     return ret;
 }
 
+static int
+cmp_AlgorithmIdentifier(const AlgorithmIdentifier *p, const AlgorithmIdentifier *q)
+{
+    return der_heim_oid_cmp(&p->algorithm, &q->algorithm);
+}
+
 int
 hx509_cms_create_signed(hx509_context context,
                        int flags,
@@ -1427,7 +1434,7 @@ hx509_cms_create_signed(hx509_context context,
                        hx509_certs pool,
                        heim_octet_string *signed_data)
 {
-    unsigned int i;
+    unsigned int i, j;
     hx509_name name;
     int ret;
     size_t size;
@@ -1454,9 +1461,22 @@ hx509_cms_create_signed(hx509_context context,
     else
        sigctx.cmsidflag = CMS_ID_SKI;
 
-    ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &sigctx.certs);
-    if (ret)
-       return ret;
+    /**
+     * Use HX509_CMS_SIGNATURE_LEAF_ONLY to only request leaf
+     * certificates to be added to the SignedData.
+     */
+    sigctx.leafonly = (flags & HX509_CMS_SIGNATURE_LEAF_ONLY) ? 1 : 0;
+
+    /**
+     * Use HX509_CMS_NO_CERTS to make the SignedData contain no
+     * certificates, overrides HX509_CMS_SIGNATURE_LEAF_ONLY.
+     */
+
+    if ((flags & HX509_CMS_SIGNATURE_NO_CERTS) == 0) {
+       ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &sigctx.certs);
+       if (ret)
+           return ret;
+    }
 
     sigctx.anchors = anchors;
     sigctx.pool = pool;
@@ -1497,22 +1517,19 @@ hx509_cms_create_signed(hx509_context context,
     }
 
     if (sigctx.sd.signerInfos.len) {
-       ALLOC_SEQ(&sigctx.sd.digestAlgorithms, sigctx.sd.signerInfos.len);
-       if (sigctx.sd.digestAlgorithms.val == NULL) {
-           ret = ENOMEM;
-           hx509_clear_error_string(context);
-           goto out;
-       }
-       
-       /* XXX remove dups */
        for (i = 0; i < sigctx.sd.signerInfos.len; i++) {
            AlgorithmIdentifier *di =
                &sigctx.sd.signerInfos.val[i].digestAlgorithm;
-           ret = copy_AlgorithmIdentifier(di,
-                                          &sigctx.sd.digestAlgorithms.val[i]);
-           if (ret) {
-               hx509_clear_error_string(context);
-               goto out;
+
+           for (j = 0; j < sigctx.sd.digestAlgorithms.len; j++)
+               if (cmp_AlgorithmIdentifier(di, &sigctx.sd.digestAlgorithms.val[j]) == 0)
+                   break;
+           if (j < sigctx.sd.digestAlgorithms.len) {
+               ret = add_DigestAlgorithmIdentifiers(&sigctx.sd.digestAlgorithms, di);
+               if (ret) {
+                   hx509_clear_error_string(context);
+                   goto out;
+               }
            }
        }
     }
index 77be4413ac9b03aa82f8cb988eb3078c30d8364d..c2e5e70748f98fd0f441200c1b7f046418b93f4c 100644 (file)
@@ -149,11 +149,6 @@ const AlgorithmIdentifier _hx509_signature_md5_data = {
     { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
 };
 
-static const unsigned md2_oid_tree[] = { 1, 2, 840, 113549, 2, 2 };
-const AlgorithmIdentifier _hx509_signature_md2_data = {
-    { 6, rk_UNCONST(md2_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
 static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };
 const AlgorithmIdentifier _hx509_signature_ecPublicKey = {
     { 6, rk_UNCONST(ecPublicKey) }, NULL
@@ -194,11 +189,6 @@ const AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = {
     { 7, rk_UNCONST(rsa_with_md5_oid) }, NULL
 };
 
-static const unsigned rsa_with_md2_oid[] ={ 1, 2, 840, 113549, 1, 1, 2 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_md2_data = {
-    { 7, rk_UNCONST(rsa_with_md2_oid) }, NULL
-};
-
 static const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 };
 const AlgorithmIdentifier _hx509_signature_rsa_data = {
     { 7, rk_UNCONST(rsa_oid) }, NULL
@@ -283,11 +273,11 @@ heim_oid2ecnid(heim_oid *oid)
      * Now map to openssl OID fun
      */
 
-    if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp256r1) == 0)
+    if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP256R1) == 0)
        return NID_X9_62_prime256v1;
-    else if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp160r1) == 0)
+    else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R1) == 0)
        return NID_secp160r1;
-    else if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp160r2) == 0)
+    else if (der_heim_oid_cmp(oid, ASN1_OID_ID_EC_GROUP_SECP160R2) == 0)
        return NID_secp160r2;
 
     return -1;
@@ -370,7 +360,7 @@ ecdsa_verify_signature(hx509_context context,
     /* set up EC KEY */
     spi = &signer->tbsCertificate.subjectPublicKeyInfo;
 
-    if (der_heim_oid_cmp(&spi->algorithm.algorithm, &asn1_oid_id_ecPublicKey) != 0)
+    if (der_heim_oid_cmp(&spi->algorithm.algorithm, ASN1_OID_ID_ECPUBLICKEY) != 0)
        return HX509_CRYPTO_SIG_INVALID_FORMAT;
 
 #ifdef HAVE_OPENSSL
@@ -431,7 +421,7 @@ ecdsa_create_signature(hx509_context context,
     unsigned int siglen;
     int ret;
 
-    if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
+    if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) != 0)
        _hx509_abort("internal error passing private key to wrong ops");
 
     sig_oid = sig_alg->sig_oid;
@@ -661,7 +651,7 @@ rsa_create_signature(hx509_context context,
     size_t size;
     int ret;
 
-    if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_pkcs1_rsaEncryption) != 0)
+    if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0)
        return HX509_ALG_NOT_SUPP;
 
     if (alg)
@@ -669,19 +659,19 @@ rsa_create_signature(hx509_context context,
     else
        sig_oid = signer->signature_alg;
 
-    if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_sha256WithRSAEncryption) == 0) {
+    if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION) == 0) {
        digest_alg = hx509_signature_sha256();
-    } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_sha1WithRSAEncryption) == 0) {
+    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION) == 0) {
        digest_alg = hx509_signature_sha1();
-    } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_md5WithRSAEncryption) == 0) {
+    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) {
        digest_alg = hx509_signature_md5();
-    } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_md5WithRSAEncryption) == 0) {
+    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION) == 0) {
        digest_alg = hx509_signature_md5();
-    } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_dsa_with_sha1) == 0) {
+    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_DSA_WITH_SHA1) == 0) {
        digest_alg = hx509_signature_sha1();
-    } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_rsaEncryption) == 0) {
+    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {
        digest_alg = hx509_signature_sha1();
-    } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_heim_rsa_pkcs1_x509) == 0) {
+    } else if (der_heim_oid_cmp(sig_oid, ASN1_OID_ID_HEIM_RSA_PKCS1_X509) == 0) {
        digest_alg = NULL;
     } else
        return HX509_ALG_NOT_SUPP;
@@ -767,7 +757,7 @@ rsa_private_key_import(hx509_context context,
                               "Failed to parse RSA key");
        return HX509_PARSING_KEY_FAILED;
     }
-    private_key->signature_alg = &asn1_oid_id_pkcs1_sha1WithRSAEncryption;
+    private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
 
     return 0;
 }
@@ -790,7 +780,7 @@ rsa_private_key2SPKI(hx509_context context,
     }
     spki->subjectPublicKey.length = len * 8;
 
-    ret = set_digest_alg(&spki->algorithm, &asn1_oid_id_pkcs1_rsaEncryption,
+    ret = set_digest_alg(&spki->algorithm, ASN1_OID_ID_PKCS1_RSAENCRYPTION,
                         "\x05\x00", 2);
     if (ret) {
        hx509_set_error_string(context, 0, ret, "malloc - out of memory");
@@ -844,7 +834,7 @@ rsa_generate_private_key(hx509_context context,
                               "Failed to generate RSA key");
        return HX509_PARSING_KEY_FAILED;
     }
-    private_key->signature_alg = &asn1_oid_id_pkcs1_sha1WithRSAEncryption;
+    private_key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
 
     return 0;
 }
@@ -900,7 +890,7 @@ rsa_get_internal(hx509_context context,
 
 static hx509_private_key_ops rsa_private_key_ops = {
     "RSA PRIVATE KEY",
-    &asn1_oid_id_pkcs1_rsaEncryption,
+    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     NULL,
     rsa_private_key2SPKI,
     rsa_private_key_export,
@@ -973,7 +963,7 @@ ecdsa_private_key_import(hx509_context context,
                               "Failed to parse EC private key");
        return HX509_PARSING_KEY_FAILED;
     }
-    private_key->signature_alg = &asn1_oid_id_ecdsa_with_SHA256;
+    private_key->signature_alg = ASN1_OID_ID_ECDSA_WITH_SHA256;
 
     return 0;
 }
@@ -997,7 +987,7 @@ ecdsa_get_internal(hx509_context context,
 
 static hx509_private_key_ops ecdsa_private_key_ops = {
     "EC PRIVATE KEY",
-    &asn1_oid_id_ecPublicKey,
+    ASN1_OID_ID_ECPUBLICKEY,
     ecdsa_available,
     ecdsa_private_key2SPKI,
     ecdsa_private_key_export,
@@ -1110,7 +1100,7 @@ dsa_parse_private_key(hx509_context context,
        d2i_DSAPrivateKey(NULL, &p, len);
     if (private_key->private_key.dsa == NULL)
        return EINVAL;
-    private_key->signature_alg = &asn1_oid_id_dsa_with_sha1;
+    private_key->signature_alg = ASN1_OID_ID_DSA_WITH_SHA1;
 
     return 0;
 /* else */
@@ -1197,9 +1187,9 @@ evp_md_verify_signature(hx509_context context,
 
 static const struct signature_alg ecdsa_with_sha256_alg = {
     "ecdsa-with-sha256",
-    &asn1_oid_id_ecdsa_with_SHA256,
+    ASN1_OID_ID_ECDSA_WITH_SHA256,
     &_hx509_signature_ecdsa_with_sha256_data,
-    &asn1_oid_id_ecPublicKey,
+    ASN1_OID_ID_ECPUBLICKEY,
     &_hx509_signature_sha256_data,
     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     0,
@@ -1211,9 +1201,9 @@ static const struct signature_alg ecdsa_with_sha256_alg = {
 
 static const struct signature_alg ecdsa_with_sha1_alg = {
     "ecdsa-with-sha1",
-    &asn1_oid_id_ecdsa_with_SHA1,
+    ASN1_OID_ID_ECDSA_WITH_SHA1,
     &_hx509_signature_ecdsa_with_sha1_data,
-    &asn1_oid_id_ecPublicKey,
+    ASN1_OID_ID_ECPUBLICKEY,
     &_hx509_signature_sha1_data,
     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     0,
@@ -1227,9 +1217,9 @@ static const struct signature_alg ecdsa_with_sha1_alg = {
 
 static const struct signature_alg heim_rsa_pkcs1_x509 = {
     "rsa-pkcs1-x509",
-    &asn1_oid_id_heim_rsa_pkcs1_x509,
+    ASN1_OID_ID_HEIM_RSA_PKCS1_X509,
     &_hx509_signature_rsa_pkcs1_x509_data,
-    &asn1_oid_id_pkcs1_rsaEncryption,
+    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     NULL,
     PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
     0,
@@ -1240,9 +1230,9 @@ static const struct signature_alg heim_rsa_pkcs1_x509 = {
 
 static const struct signature_alg pkcs1_rsa_sha1_alg = {
     "rsa",
-    &asn1_oid_id_pkcs1_rsaEncryption,
+    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     &_hx509_signature_rsa_with_sha1_data,
-    &asn1_oid_id_pkcs1_rsaEncryption,
+    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     NULL,
     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     0,
@@ -1253,9 +1243,9 @@ static const struct signature_alg pkcs1_rsa_sha1_alg = {
 
 static const struct signature_alg rsa_with_sha256_alg = {
     "rsa-with-sha256",
-    &asn1_oid_id_pkcs1_sha256WithRSAEncryption,
+    ASN1_OID_ID_PKCS1_SHA256WITHRSAENCRYPTION,
     &_hx509_signature_rsa_with_sha256_data,
-    &asn1_oid_id_pkcs1_rsaEncryption,
+    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     &_hx509_signature_sha256_data,
     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     0,
@@ -1266,9 +1256,9 @@ static const struct signature_alg rsa_with_sha256_alg = {
 
 static const struct signature_alg rsa_with_sha1_alg = {
     "rsa-with-sha1",
-    &asn1_oid_id_pkcs1_sha1WithRSAEncryption,
+    ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION,
     &_hx509_signature_rsa_with_sha1_data,
-    &asn1_oid_id_pkcs1_rsaEncryption,
+    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
     &_hx509_signature_sha1_data,
     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
     0,
@@ -1277,25 +1267,25 @@ static const struct signature_alg rsa_with_sha1_alg = {
     rsa_create_signature
 };
 
-static const struct signature_alg rsa_with_md5_alg = {
-    "rsa-with-md5",
-    &asn1_oid_id_pkcs1_md5WithRSAEncryption,
-    &_hx509_signature_rsa_with_md5_data,
-    &asn1_oid_id_pkcs1_rsaEncryption,
-    &_hx509_signature_md5_data,
-    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
-    1230739889,
+static const struct signature_alg rsa_with_sha1_alg_secsig = {
+    "rsa-with-sha1",
+    ASN1_OID_ID_SECSIG_SHA_1WITHRSAENCRYPTION,
+    &_hx509_signature_rsa_with_sha1_data,
+    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
+    &_hx509_signature_sha1_data,
+    PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG|SELF_SIGNED_OK,
+    0,
     NULL,
     rsa_verify_signature,
     rsa_create_signature
 };
 
-static const struct signature_alg rsa_with_md2_alg = {
-    "rsa-with-md2",
-    &asn1_oid_id_pkcs1_md2WithRSAEncryption,
-    &_hx509_signature_rsa_with_md2_data,
-    &asn1_oid_id_pkcs1_rsaEncryption,
-    &_hx509_signature_md2_data,
+static const struct signature_alg rsa_with_md5_alg = {
+    "rsa-with-md5",
+    ASN1_OID_ID_PKCS1_MD5WITHRSAENCRYPTION,
+    &_hx509_signature_rsa_with_md5_data,
+    ASN1_OID_ID_PKCS1_RSAENCRYPTION,
+    &_hx509_signature_md5_data,
     PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
     1230739889,
     NULL,
@@ -1305,9 +1295,9 @@ static const struct signature_alg rsa_with_md2_alg = {
 
 static const struct signature_alg dsa_sha1_alg = {
     "dsa-with-sha1",
-    &asn1_oid_id_dsa_with_sha1,
+    ASN1_OID_ID_DSA_WITH_SHA1,
     NULL,
-    &asn1_oid_id_dsa,
+    ASN1_OID_ID_DSA,
     &_hx509_signature_sha1_data,
     PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
     0,
@@ -1318,7 +1308,7 @@ static const struct signature_alg dsa_sha1_alg = {
 
 static const struct signature_alg sha256_alg = {
     "sha-256",
-    &asn1_oid_id_sha256,
+    ASN1_OID_ID_SHA256,
     &_hx509_signature_sha256_data,
     NULL,
     NULL,
@@ -1331,7 +1321,7 @@ static const struct signature_alg sha256_alg = {
 
 static const struct signature_alg sha1_alg = {
     "sha1",
-    &asn1_oid_id_secsig_sha_1,
+    ASN1_OID_ID_SECSIG_SHA_1,
     &_hx509_signature_sha1_data,
     NULL,
     NULL,
@@ -1344,7 +1334,7 @@ static const struct signature_alg sha1_alg = {
 
 static const struct signature_alg md5_alg = {
     "rsa-md5",
-    &asn1_oid_id_rsa_digest_md5,
+    ASN1_OID_ID_RSA_DIGEST_MD5,
     &_hx509_signature_md5_data,
     NULL,
     NULL,
@@ -1355,19 +1345,6 @@ static const struct signature_alg md5_alg = {
     NULL
 };
 
-static const struct signature_alg md2_alg = {
-    "rsa-md2",
-    &asn1_oid_id_rsa_digest_md2,
-    &_hx509_signature_md2_data,
-    NULL,
-    NULL,
-    SIG_DIGEST,
-    0,
-    EVP_md2,
-    evp_md_verify_signature,
-    NULL
-};
-
 /*
  * Order matter in this structure, "best" first for each "key
  * compatible" type (type is ECDSA, RSA, DSA, none, etc)
@@ -1380,15 +1357,14 @@ static const struct signature_alg *sig_algs[] = {
 #endif
     &rsa_with_sha256_alg,
     &rsa_with_sha1_alg,
+    &rsa_with_sha1_alg_secsig,
     &pkcs1_rsa_sha1_alg,
     &rsa_with_md5_alg,
-    &rsa_with_md2_alg,
     &heim_rsa_pkcs1_x509,
     &dsa_sha1_alg,
     &sha256_alg,
     &sha1_alg,
     &md5_alg,
-    &md2_alg,
     NULL
 };
 
@@ -1641,7 +1617,7 @@ _hx509_public_encrypt(hx509_context context,
     ciphertext->length = ret;
     ciphertext->data = to;
 
-    ret = der_copy_oid(&asn1_oid_id_pkcs1_rsaEncryption, encryption_oid);
+    ret = der_copy_oid(ASN1_OID_ID_PKCS1_RSAENCRYPTION, encryption_oid);
     if (ret) {
        der_free_octet_string(ciphertext);
        hx509_set_error_string(context, 0, ENOMEM, "out of memory");
@@ -1750,7 +1726,7 @@ _hx509_generate_private_key_init(hx509_context context,
 {
     *ctx = NULL;
 
-    if (der_heim_oid_cmp(oid, &asn1_oid_id_pkcs1_rsaEncryption) != 0) {
+    if (der_heim_oid_cmp(oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) != 0) {
        hx509_set_error_string(context, 0, EINVAL,
                               "private key not an RSA key");
        return EINVAL;
@@ -1844,10 +1820,6 @@ const AlgorithmIdentifier *
 hx509_signature_md5(void)
 { return &_hx509_signature_md5_data; }
 
-const AlgorithmIdentifier *
-hx509_signature_md2(void)
-{ return &_hx509_signature_md2_data; }
-
 const AlgorithmIdentifier *
 hx509_signature_ecPublicKey(void)
 { return &_hx509_signature_ecPublicKey; }
@@ -1880,10 +1852,6 @@ const AlgorithmIdentifier *
 hx509_signature_rsa_with_md5(void)
 { return &_hx509_signature_rsa_with_md5_data; }
 
-const AlgorithmIdentifier *
-hx509_signature_rsa_with_md2(void)
-{ return &_hx509_signature_rsa_with_md2_data; }
-
 const AlgorithmIdentifier *
 hx509_signature_rsa(void)
 { return &_hx509_signature_rsa_data; }
@@ -1961,11 +1929,11 @@ _hx509_private_key_free(hx509_private_key *key)
     if (--(*key)->ref > 0)
        return 0;
 
-    if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, &asn1_oid_id_pkcs1_rsaEncryption) == 0) {
+    if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0) {
        if ((*key)->private_key.rsa)
            RSA_free((*key)->private_key.rsa);
 #ifdef HAVE_OPENSSL
-    } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, &asn1_oid_id_ecPublicKey) == 0) {
+    } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0) {
        if ((*key)->private_key.ecdsa)
            EC_KEY_free((*key)->private_key.ecdsa);
 #endif
@@ -1982,7 +1950,7 @@ _hx509_private_key_assign_rsa(hx509_private_key key, void *ptr)
     if (key->private_key.rsa)
        RSA_free(key->private_key.rsa);
     key->private_key.rsa = ptr;
-    key->signature_alg = &asn1_oid_id_pkcs1_sha1WithRSAEncryption;
+    key->signature_alg = ASN1_OID_ID_PKCS1_SHA1WITHRSAENCRYPTION;
     key->md = &pkcs1_rsa_sha1_alg;
 }
 
@@ -2048,7 +2016,11 @@ struct hx509cipher {
 struct hx509_crypto_data {
     char *name;
     int flags;
-#define ALLOW_WEAK 1
+#define ALLOW_WEAK     1
+
+#define PADDING_NONE   2
+#define PADDING_PKCS7  4
+#define PADDING_FLAGS  (2|4)
     const struct hx509cipher *cipher;
     const EVP_CIPHER *c;
     heim_octet_string key;
@@ -2204,7 +2176,7 @@ static const struct hx509cipher ciphers[] = {
     {
        "rc2-cbc",
        CIPHER_WEAK,
-       &asn1_oid_id_pkcs3_rc2_cbc,
+       ASN1_OID_ID_PKCS3_RC2_CBC,
        NULL,
        EVP_rc2_cbc,
        CMSRC2CBCParam_get,
@@ -2213,7 +2185,7 @@ static const struct hx509cipher ciphers[] = {
     {
        "rc2-cbc",
        CIPHER_WEAK,
-       &asn1_oid_id_rsadsi_rc2_cbc,
+       ASN1_OID_ID_RSADSI_RC2_CBC,
        NULL,
        EVP_rc2_cbc,
        CMSRC2CBCParam_get,
@@ -2231,7 +2203,7 @@ static const struct hx509cipher ciphers[] = {
     {
        "des-ede3-cbc",
        0,
-       &asn1_oid_id_pkcs3_des_ede3_cbc,
+       ASN1_OID_ID_PKCS3_DES_EDE3_CBC,
        NULL,
        EVP_des_ede3_cbc,
        CMSCBCParam_get,
@@ -2240,7 +2212,7 @@ static const struct hx509cipher ciphers[] = {
     {
        "des-ede3-cbc",
        0,
-       &asn1_oid_id_rsadsi_des_ede3_cbc,
+       ASN1_OID_ID_RSADSI_DES_EDE3_CBC,
        hx509_crypto_des_rsdi_ede3_cbc,
        EVP_des_ede3_cbc,
        CMSCBCParam_get,
@@ -2249,7 +2221,7 @@ static const struct hx509cipher ciphers[] = {
     {
        "aes-128-cbc",
        0,
-       &asn1_oid_id_aes_128_cbc,
+       ASN1_OID_ID_AES_128_CBC,
        hx509_crypto_aes128_cbc,
        EVP_aes_128_cbc,
        CMSCBCParam_get,
@@ -2258,7 +2230,7 @@ static const struct hx509cipher ciphers[] = {
     {
        "aes-192-cbc",
        0,
-       &asn1_oid_id_aes_192_cbc,
+       ASN1_OID_ID_AES_192_CBC,
        NULL,
        EVP_aes_192_cbc,
        CMSCBCParam_get,
@@ -2267,7 +2239,7 @@ static const struct hx509cipher ciphers[] = {
     {
        "aes-256-cbc",
        0,
-       &asn1_oid_id_aes_256_cbc,
+       ASN1_OID_ID_AES_256_CBC,
        hx509_crypto_aes256_cbc,
        EVP_aes_256_cbc,
        CMSCBCParam_get,
@@ -2334,6 +2306,7 @@ hx509_crypto_init(hx509_context context,
        return ENOMEM;
     }
 
+    (*crypto)->flags = PADDING_PKCS7;
     (*crypto)->cipher = cipher;
     (*crypto)->c = (*cipher->evp_func)();
 
@@ -2379,6 +2352,23 @@ hx509_crypto_allow_weak(hx509_crypto crypto)
     crypto->flags |= ALLOW_WEAK;
 }
 
+void
+hx509_crypto_set_padding(hx509_crypto crypto, int padding_type)
+{
+    switch (padding_type) {
+    case HX509_CRYPTO_PADDING_PKCS7:
+       crypto->flags &= ~PADDING_FLAGS;
+       crypto->flags |= PADDING_PKCS7;
+       break;
+    case HX509_CRYPTO_PADDING_NONE:
+       crypto->flags &= ~PADDING_FLAGS;
+       crypto->flags |= PADDING_NONE;
+       break;
+    default:
+       _hx509_abort("Invalid padding");
+    }
+}
+
 int
 hx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length)
 {
@@ -2497,12 +2487,17 @@ hx509_crypto_encrypt(hx509_crypto crypto,
        goto out;
     }
 
-    if (EVP_CIPHER_block_size(crypto->c) == 1) {
+    assert(crypto->flags & PADDING_FLAGS);
+    if (crypto->flags & PADDING_NONE) {
        padsize = 0;
-    } else {
-       int bsize = EVP_CIPHER_block_size(crypto->c);
-       padsize = bsize - (length % bsize);
+    } else if (crypto->flags & PADDING_PKCS7) {
+       if (EVP_CIPHER_block_size(crypto->c) == 1) {
+       } else {
+           int bsize = EVP_CIPHER_block_size(crypto->c);
+           padsize = bsize - (length % bsize);
+       }
     }
+
     (*ciphertext)->length = length + padsize;
     (*ciphertext)->data = malloc(length + padsize);
     if ((*ciphertext)->data == NULL) {
@@ -2592,7 +2587,7 @@ hx509_crypto_decrypt(hx509_crypto crypto,
     }
     EVP_CIPHER_CTX_cleanup(&evp);
 
-    if (EVP_CIPHER_block_size(crypto->c) > 1) {
+    if ((crypto->flags & PADDING_PKCS7) && EVP_CIPHER_block_size(crypto->c) > 1) {
        int padsize;
        unsigned char *p;
        int j, bsize = EVP_CIPHER_block_size(crypto->c);
@@ -2704,33 +2699,33 @@ find_string2key(const heim_oid *oid,
                const EVP_MD **md,
                PBE_string2key_func *s2k)
 {
-    if (der_heim_oid_cmp(oid, &asn1_oid_id_pbewithSHAAnd40BitRC2_CBC) == 0) {
+    if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC2_CBC) == 0) {
        *c = EVP_rc2_40_cbc();
        *md = EVP_sha1();
        *s2k = PBE_string2key;
        return &asn1_oid_private_rc2_40;
-    } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd128BitRC2_CBC) == 0) {
+    } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC2_CBC) == 0) {
        *c = EVP_rc2_cbc();
        *md = EVP_sha1();
        *s2k = PBE_string2key;
-       return &asn1_oid_id_pkcs3_rc2_cbc;
+       return ASN1_OID_ID_PKCS3_RC2_CBC;
 #if 0
-    } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd40BitRC4) == 0) {
+    } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND40BITRC4) == 0) {
        *c = EVP_rc4_40();
        *md = EVP_sha1();
        *s2k = PBE_string2key;
        return NULL;
-    } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd128BitRC4) == 0) {
+    } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND128BITRC4) == 0) {
        *c = EVP_rc4();
        *md = EVP_sha1();
        *s2k = PBE_string2key;
-       return &asn1_oid_id_pkcs3_rc4;
+       return ASN1_OID_ID_PKCS3_RC4;
 #endif
-    } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd3_KeyTripleDES_CBC) == 0) {
+    } else if (der_heim_oid_cmp(oid, ASN1_OID_ID_PBEWITHSHAAND3_KEYTRIPLEDES_CBC) == 0) {
        *c = EVP_des_ede3_cbc();
        *md = EVP_sha1();
        *s2k = PBE_string2key;
-       return &asn1_oid_id_pkcs3_des_ede3_cbc;
+       return ASN1_OID_ID_PKCS3_DES_EDE3_CBC;
     }
 
     return NULL;
@@ -2907,9 +2902,9 @@ match_keys_ec(hx509_cert c, hx509_private_key private_key)
 int
 _hx509_match_keys(hx509_cert c, hx509_private_key key)
 {
-    if (der_heim_oid_cmp(key->ops->key_oid, &asn1_oid_id_pkcs1_rsaEncryption) == 0)
+    if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_PKCS1_RSAENCRYPTION) == 0)
        return match_keys_rsa(c, key);
-    if (der_heim_oid_cmp(key->ops->key_oid, &asn1_oid_id_ecPublicKey) == 0)
+    if (der_heim_oid_cmp(key->ops->key_oid, ASN1_OID_ID_ECPUBLICKEY) == 0)
        return match_keys_ec(c, key);
     return 0;
 
index 86aad7ec9cdd054c81736601021b1b2cc68c0254..b6eeac9d18a2f33de8ea3417ef4e54f3bafd76d7 100644 (file)
@@ -71,6 +71,11 @@ enum {
     HX509_VALIDATE_F_VERBOSE = 2
 };
 
+enum {
+    HX509_CRYPTO_PADDING_PKCS7 = 0,
+    HX509_CRYPTO_PADDING_NONE = 1
+};
+
 struct hx509_cert_attribute_data {
     heim_oid oid;
     heim_octet_string data;
@@ -157,6 +162,8 @@ typedef enum {
 #define HX509_CMS_SIGNATURE_DETACHED                   0x01
 #define HX509_CMS_SIGNATURE_ID_NAME                    0x02
 #define HX509_CMS_SIGNATURE_NO_SIGNER                  0x04
+#define HX509_CMS_SIGNATURE_LEAF_ONLY                  0x08
+#define HX509_CMS_SIGNATURE_NO_CERTS                   0x10
 
 /* hx509_verify_hostname nametype */
 typedef enum  {
index 52697f834b25192c207e139fe0c2045928eac396..23f6a4826a601292a7194c1d5ad29679080d170f 100644 (file)
@@ -835,7 +835,7 @@ p11_init(hx509_context context,
        goto out;
     }
 
-    getFuncs = dlsym(p->dl_handle, "C_GetFunctionList");
+    getFuncs = (CK_C_GetFunctionList) dlsym(p->dl_handle, "C_GetFunctionList");
     if (getFuncs == NULL) {
        ret = HX509_PKCS11_LOAD;
        hx509_set_error_string(context, 0, ret,
@@ -1139,7 +1139,6 @@ p11_printinfo(hx509_context context,
                MECHNAME(CKM_SHA256, "sha256");
                MECHNAME(CKM_SHA_1, "sha1");
                MECHNAME(CKM_MD5, "md5");
-               MECHNAME(CKM_MD2, "md2");
                MECHNAME(CKM_RIPEMD160, "ripemd-160");
                MECHNAME(CKM_DES_ECB, "des-ecb");
                MECHNAME(CKM_DES_CBC, "des-cbc");
index e795b1e44e44a5c8dcc99aa9a35f40cdca207169..83b8f86d4120b7cf524ece62ea0b8238e08f917f 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "hx_locl.h"
 #include <wind.h>
+#include "char_map.h"
 
 /**
  * @page page_name PKIX/X.509 Names
@@ -79,11 +80,11 @@ static const struct {
 };
 
 static char *
-quote_string(const char *f, size_t len, size_t *rlen)
+quote_string(const char *f, size_t len, int flags, size_t *rlen)
 {
     size_t i, j, tolen;
-    const char *from = f;
-    char *to;
+    const unsigned char *from = (const unsigned char *)f;
+    unsigned char *to;
 
     tolen = len * 3 + 1;
     to = malloc(tolen);
@@ -91,26 +92,29 @@ quote_string(const char *f, size_t len, size_t *rlen)
        return NULL;
 
     for (i = 0, j = 0; i < len; i++) {
-       if (from[i] == ' ' && i + 1 < len)
+       unsigned char map = char_map[from[i]] & flags;
+       if (i == 0 && (map & Q_RFC2253_QUOTE_FIRST)) {
+           to[j++] = '\\';
            to[j++] = from[i];
-       else if (from[i] == ',' || from[i] == '=' || from[i] == '+' ||
-                from[i] == '<' || from[i] == '>' || from[i] == '#' ||
-                from[i] == ';' || from[i] == ' ')
-       {
+       } else if ((i + 1) == len && (map & Q_RFC2253_QUOTE_LAST)) {
+
            to[j++] = '\\';
            to[j++] = from[i];
-       } else if (((unsigned char)from[i]) >= 32 && ((unsigned char)from[i]) <= 127) {
+       } else if (map & Q_RFC2253_QUOTE) {
+           to[j++] = '\\';
            to[j++] = from[i];
-       } else {
-           int l = snprintf(&to[j], tolen - j - 1,
+       } else if (map & Q_RFC2253_HEX) {
+           int l = snprintf((char *)&to[j], tolen - j - 1,
                             "#%02x", (unsigned char)from[i]);
            j += l;
+       } else {
+           to[j++] = from[i];
        }
     }
     to[j] = '\0';
     assert(j < tolen);
     *rlen = j;
-    return to;
+    return (char *)to;
 }
 
 
@@ -121,7 +125,7 @@ append_string(char **str, size_t *total_len, const char *ss,
     char *s, *qs;
 
     if (quote)
-       qs = quote_string(ss, len, &len);
+       qs = quote_string(ss, len, Q_RFC2253, &len);
     else
        qs = rk_UNCONST(ss);
 
@@ -203,7 +207,7 @@ _hx509_Name_to_string(const Name *n, char **str)
        return ENOMEM;
 
     for (i = n->u.rdnSequence.len - 1 ; i >= 0 ; i--) {
-       int len;
+       size_t len;
 
        for (j = 0; j < n->u.rdnSequence.val[i].len; j++) {
            DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value;
@@ -214,13 +218,16 @@ _hx509_Name_to_string(const Name *n, char **str)
 
            switch(ds->element) {
            case choice_DirectoryString_ia5String:
-               ss = ds->u.ia5String;
+               ss = ds->u.ia5String.data;
+               len = ds->u.ia5String.length;
                break;
            case choice_DirectoryString_printableString:
-               ss = ds->u.printableString;
+               ss = ds->u.printableString.data;
+               len = ds->u.printableString.length;
                break;
            case choice_DirectoryString_utf8String:
                ss = ds->u.utf8String;
+               len = strlen(ss);
                break;
            case choice_DirectoryString_bmpString: {
                const uint16_t *bmp = ds->u.bmpString.data;
@@ -240,10 +247,12 @@ _hx509_Name_to_string(const Name *n, char **str)
                    return ret;
                }
                ss[k] = '\0';
+               len = k;
                break;
            }
            case choice_DirectoryString_teletexString:
                ss = ds->u.teletexString;
+               len = strlen(ss);
                break;
            case choice_DirectoryString_universalString: {
                const uint32_t *uni = ds->u.universalString.data;
@@ -263,6 +272,7 @@ _hx509_Name_to_string(const Name *n, char **str)
                    return ret;
                }
                ss[k] = '\0';
+               len = k;
                break;
            }
            default:
@@ -272,10 +282,9 @@ _hx509_Name_to_string(const Name *n, char **str)
            append_string(str, &total_len, oidname, strlen(oidname), 0);
            free(oidname);
            append_string(str, &total_len, "=", 1, 0);
-           len = strlen(ss);
            append_string(str, &total_len, ss, len, 1);
-           if (ds->element == choice_DirectoryString_universalString ||
-               ds->element == choice_DirectoryString_bmpString)
+           if (ds->element == choice_DirectoryString_bmpString ||
+               ds->element == choice_DirectoryString_universalString)
            {
                free(ss);
            }
@@ -319,7 +328,7 @@ _hx509_Name_to_string(const Name *n, char **str)
 static int
 dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen)
 {
-    wind_profile_flags flags = 0;
+    wind_profile_flags flags;
     size_t i, len;
     int ret;
     uint32_t *name;
@@ -329,22 +338,28 @@ dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen)
 
     switch(ds->element) {
     case choice_DirectoryString_ia5String:
-       COPYCHARARRAY(ds, ia5String, len, name);
+       flags = WIND_PROFILE_LDAP;
+       COPYVOIDARRAY(ds, ia5String, len, name);
        break;
     case choice_DirectoryString_printableString:
-       flags = WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE;
-       COPYCHARARRAY(ds, printableString, len, name);
+       flags = WIND_PROFILE_LDAP;
+       flags |= WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE;
+       COPYVOIDARRAY(ds, printableString, len, name);
        break;
     case choice_DirectoryString_teletexString:
+       flags = WIND_PROFILE_LDAP_CASE;
        COPYCHARARRAY(ds, teletexString, len, name);
        break;
     case choice_DirectoryString_bmpString:
+       flags = WIND_PROFILE_LDAP;
        COPYVALARRAY(ds, bmpString, len, name);
        break;
     case choice_DirectoryString_universalString:
+       flags = WIND_PROFILE_LDAP;
        COPYVALARRAY(ds, universalString, len, name);
        break;
     case choice_DirectoryString_utf8String:
+       flags = WIND_PROFILE_LDAP;
        ret = wind_utf8ucs4_length(ds->u.utf8String, &len);
        if (ret)
            return ret;
@@ -367,8 +382,7 @@ dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen)
        *rlen = *rlen * 2;
        *rname = malloc(*rlen * sizeof((*rname)[0]));
 
-       ret = wind_stringprep(name, len, *rname, rlen,
-                             WIND_PROFILE_LDAP|flags);
+       ret = wind_stringprep(name, len, *rname, rlen, flags);
        if (ret == WIND_ERR_OVERRUN) {
            free(*rname);
            *rname = NULL;
@@ -934,12 +948,14 @@ hx509_general_name_unparse(GeneralName *name, char **str)
        break;
     }
     case choice_GeneralName_rfc822Name:
-       strpool = rk_strpoolprintf(strpool, "rfc822Name: %s\n",
-                                  name->u.rfc822Name);
+       strpool = rk_strpoolprintf(strpool, "rfc822Name: %.*s\n",
+                                  (int)name->u.rfc822Name.length,
+                                  (char *)name->u.rfc822Name.data);
        break;
     case choice_GeneralName_dNSName:
-       strpool = rk_strpoolprintf(strpool, "dNSName: %s\n",
-                                  name->u.dNSName);
+       strpool = rk_strpoolprintf(strpool, "dNSName: %.*s\n",
+                                  (int)name->u.dNSName.length,
+                                  (char *)name->u.dNSName.data);
        break;
     case choice_GeneralName_directoryName: {
        Name dir;
@@ -956,8 +972,9 @@ hx509_general_name_unparse(GeneralName *name, char **str)
        break;
     }
     case choice_GeneralName_uniformResourceIdentifier:
-       strpool = rk_strpoolprintf(strpool, "URI: %s",
-                                  name->u.uniformResourceIdentifier);
+       strpool = rk_strpoolprintf(strpool, "URI: %.*s",
+                                  (int)name->u.uniformResourceIdentifier.length,
+                                  (char *)name->u.uniformResourceIdentifier.data);
        break;
     case choice_GeneralName_iPAddress: {
        unsigned char *a = name->u.iPAddress.data;
index 0d174e0cece8aad1cfa2bf75215759128b47ae67..917f08891be22ed9fc258acb1ef2f337564c9035 100644 (file)
@@ -143,7 +143,8 @@ _hx509_request_add_dns_name(hx509_context context,
 
     memset(&name, 0, sizeof(name));
     name.element = choice_GeneralName_dNSName;
-    name.u.dNSName = rk_UNCONST(hostname);
+    name.u.dNSName.data = rk_UNCONST(hostname);
+    name.u.dNSName.length = strlen(hostname);
 
     return add_GeneralNames(&req->san, &name);
 }
@@ -157,7 +158,8 @@ _hx509_request_add_email(hx509_context context,
 
     memset(&name, 0, sizeof(name));
     name.element = choice_GeneralName_rfc822Name;
-    name.u.dNSName = rk_UNCONST(email);
+    name.u.dNSName.data = rk_UNCONST(email);
+    name.u.dNSName.length = strlen(email);
 
     return add_GeneralNames(&req->san, &name);
 }
index 5932ce84c3d4020c24987365221ceca131a48e7c..561818c9f1f963078e3085187946c121026b5c06 100644 (file)
@@ -175,6 +175,7 @@ _hx509_expr_eval(hx509_context context, hx509_env env, struct hx_expr *expr)
        return eval_comp(context, env, expr->arg1);
     default:
        _hx509_abort("hx509 eval expr with unknown op: %d", (int)expr->op);
+       UNREACHABLE(return 0);
     }
 }
 
index 19a59974531c0b24fafcae4f013bfcd2aa63c5c6..6f20cdcf6ca42c6f0a94241fbb24c283e4d43d63 100644 (file)
@@ -43,8 +43,8 @@
 
 static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER;
 static cc_initialize_func init_func;
-static void (*set_target_uid)(uid_t);
-static void (*clear_target)(void);
+static void (KRB5_CALLCONV *set_target_uid)(uid_t);
+static void (KRB5_CALLCONV *clear_target)(void);
 
 #ifdef HAVE_DLOPEN
 static void *cc_handle;
@@ -56,7 +56,7 @@ typedef struct krb5_acc {
     cc_ccache_t ccache;
 } krb5_acc;
 
-static krb5_error_code acc_close(krb5_context, krb5_ccache);
+static krb5_error_code KRB5_CALLCONV acc_close(krb5_context, krb5_ccache);
 
 #define ACACHE(X) ((krb5_acc *)(X)->data.data)
 
@@ -106,6 +106,8 @@ init_ccapi(krb5_context context)
     if (lib == NULL) {
 #ifdef __APPLE__
        lib = "/System/Library/Frameworks/Kerberos.framework/Kerberos";
+#elif defined(KRB5_USE_PATH_TOKENS) && defined(_WIN32)
+       lib = "%{LIBDIR}/libkrb5_cc.dll";
 #else
        lib = "/usr/lib/libkrb5_cc.so";
 #endif
@@ -120,7 +122,18 @@ init_ccapi(krb5_context context)
 #define RTLD_LOCAL 0
 #endif
 
+#ifdef KRB5_USE_PATH_TOKENS
+    {
+      char * explib = NULL;
+      if (_krb5_expand_path_tokens(context, lib, &explib) == 0) {
+       cc_handle = dlopen(explib, RTLD_LAZY|RTLD_LOCAL);
+       free(explib);
+      }
+    }
+#else
     cc_handle = dlopen(lib, RTLD_LAZY|RTLD_LOCAL);
+#endif
+
     if (cc_handle == NULL) {
        HEIMDAL_MUTEX_unlock(&acc_mutex);
        if (context)
@@ -131,8 +144,10 @@ init_ccapi(krb5_context context)
     }
 
     init_func = (cc_initialize_func)dlsym(cc_handle, "cc_initialize");
-    set_target_uid = dlsym(cc_handle, "krb5_ipc_client_set_target_uid");
-    clear_target = dlsym(cc_handle, "krb5_ipc_client_clear_target");
+    set_target_uid = (void (KRB5_CALLCONV *)(uid_t))
+       dlsym(cc_handle, "krb5_ipc_client_set_target_uid");
+    clear_target = (void (KRB5_CALLCONV *)(void))
+       dlsym(cc_handle, "krb5_ipc_client_clear_target");
     HEIMDAL_MUTEX_unlock(&acc_mutex);
     if (init_func == NULL) {
        if (context)
@@ -157,14 +172,16 @@ void
 _heim_krb5_ipc_client_set_target_uid(uid_t uid)
 {
     init_ccapi(NULL);
-    (*set_target_uid)(uid);
+    if (set_target_uid != NULL)
+        (*set_target_uid)(uid);
 }
 
 void
 _heim_krb5_ipc_client_clear_target(void)
 {
     init_ccapi(NULL);
-    (*clear_target)();
+    if (clear_target != NULL)
+        (*clear_target)();
 }
 
 static krb5_error_code
@@ -436,7 +453,7 @@ get_cc_name(krb5_acc *a)
 }
 
 
-static const char*
+static const char* KRB5_CALLCONV
 acc_get_name(krb5_context context,
             krb5_ccache id)
 {
@@ -473,7 +490,7 @@ acc_get_name(krb5_context context,
     return a->cache_name;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_alloc(krb5_context context, krb5_ccache *id)
 {
     krb5_error_code ret;
@@ -503,7 +520,7 @@ acc_alloc(krb5_context context, krb5_ccache *id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_resolve(krb5_context context, krb5_ccache *id, const char *res)
 {
     krb5_error_code ret;
@@ -543,7 +560,7 @@ acc_resolve(krb5_context context, krb5_ccache *id, const char *res)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_gen_new(krb5_context context, krb5_ccache *id)
 {
     krb5_error_code ret;
@@ -561,7 +578,7 @@ acc_gen_new(krb5_context context, krb5_ccache *id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_initialize(krb5_context context,
               krb5_ccache id,
               krb5_principal primary_principal)
@@ -615,7 +632,7 @@ acc_initialize(krb5_context context,
     return translate_cc_error(context, error);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_close(krb5_context context,
          krb5_ccache id)
 {
@@ -637,7 +654,7 @@ acc_close(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_destroy(krb5_context context,
            krb5_ccache id)
 {
@@ -655,7 +672,7 @@ acc_destroy(krb5_context context,
     return translate_cc_error(context, error);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_store_cred(krb5_context context,
               krb5_ccache id,
               krb5_creds *creds)
@@ -690,7 +707,7 @@ acc_store_cred(krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_get_principal(krb5_context context,
                  krb5_ccache id,
                  krb5_principal *principal)
@@ -718,7 +735,7 @@ acc_get_principal(krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_get_first (krb5_context context,
               krb5_ccache id,
               krb5_cc_cursor *cursor)
@@ -743,7 +760,7 @@ acc_get_first (krb5_context context,
 }
 
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_get_next (krb5_context context,
              krb5_ccache id,
              krb5_cc_cursor *cursor,
@@ -770,7 +787,7 @@ acc_get_next (krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_end_get (krb5_context context,
             krb5_ccache id,
             krb5_cc_cursor *cursor)
@@ -780,7 +797,7 @@ acc_end_get (krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_remove_cred(krb5_context context,
                krb5_ccache id,
                krb5_flags which,
@@ -856,7 +873,7 @@ acc_remove_cred(krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_set_flags(krb5_context context,
              krb5_ccache id,
              krb5_flags flags)
@@ -864,7 +881,7 @@ acc_set_flags(krb5_context context,
     return 0;
 }
 
-static int
+static int KRB5_CALLCONV
 acc_get_version(krb5_context context,
                krb5_ccache id)
 {
@@ -876,7 +893,7 @@ struct cache_iter {
     cc_ccache_iterator_t iter;
 };
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
 {
     struct cache_iter *iter;
@@ -910,7 +927,7 @@ acc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
 {
     struct cache_iter *iter = cursor;
@@ -948,7 +965,7 @@ acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
 {
     struct cache_iter *iter = cursor;
@@ -961,7 +978,7 @@ acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
 {
     krb5_acc *afrom = ACACHE(from);
@@ -993,7 +1010,7 @@ acc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
     return translate_cc_error(context, error);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_get_default_name(krb5_context context, char **str)
 {
     krb5_error_code ret;
@@ -1015,18 +1032,18 @@ acc_get_default_name(krb5_context context, char **str)
        return translate_cc_error(context, error);
     }
        
-    asprintf(str, "API:%s", name->data);
+    error = asprintf(str, "API:%s", name->data);
     (*name->func->release)(name);
     (*cc->func->release)(cc);
 
-    if (*str == NULL) {
+    if (error < 0 || *str == NULL) {
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
        return ENOMEM;
     }
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_set_default(krb5_context context, krb5_ccache id)
 {
     krb5_acc *a = ACACHE(id);
@@ -1045,7 +1062,7 @@ acc_set_default(krb5_context context, krb5_ccache id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 acc_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime)
 {
     krb5_acc *a = ACACHE(id);
index ce8040d07ca487541804a909cc13dc5bbe375400..32a131b07c5115fe65359344471a40e3dc96a03b 100644 (file)
@@ -83,7 +83,7 @@ main (int argc, char **argv)
     while((ret = krb5_cc_next_cred(context, id, &cursor, &creds)) == 0){
         char *principal;
 
-       krb5_unparse_name_short(context, creds.server, &principal);
+       krb5_unparse_name(context, creds.server, &principal);
        printf("principal: %s\\n", principal);
        free(principal);
        krb5_free_cred_contents (context, &creds);
@@ -206,8 +206,10 @@ allocate_ccache (krb5_context context,
     }
 
     ret = (*id)->ops->resolve(context, id, residual);
-    if(ret)
+    if(ret) {
        free(*id);
+        *id = NULL;
+    }
 
 #ifdef KRB5_USE_PATH_TOKENS
     if (exp_residual)
@@ -217,6 +219,25 @@ allocate_ccache (krb5_context context,
     return ret;
 }
 
+static int
+is_possible_path_name(const char * name)
+{
+    const char * colon;
+
+    if ((colon = strchr(name, ':')) == NULL)
+        return TRUE;
+
+#ifdef _WIN32
+    /* <drive letter>:\path\to\cache ? */
+
+    if (colon == name + 1 &&
+        strchr(colon + 1, ':') == NULL)
+        return TRUE;
+#endif
+
+    return FALSE;
+}
+
 /**
  * Find and allocate a ccache in `id' from the specification in `residual'.
  * If the ccache name doesn't contain any colon, interpret it as a file name.
@@ -251,7 +272,7 @@ krb5_cc_resolve(krb5_context context,
                                    id);
        }
     }
-    if (strchr (name, ':') == NULL)
+    if (is_possible_path_name(name))
        return allocate_ccache (context, &krb5_fcc_ops, name, id);
     else {
        krb5_set_error_message(context, KRB5_CC_UNKNOWN_TYPE,
@@ -389,84 +410,7 @@ krb5_cc_get_ops(krb5_context context, krb5_ccache id)
 krb5_error_code
 _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res)
 {
-#ifndef KRB5_USE_PATH_TOKENS
-    size_t tlen, len = 0;
-    char *tmp, *tmp2, *append;
-
-    *res = NULL;
-
-    while (str && *str) {
-       tmp = strstr(str, "%{");
-       if (tmp && tmp != str) {
-           append = malloc((tmp - str) + 1);
-           if (append) {
-               memcpy(append, str, tmp - str);
-               append[tmp - str] = '\0';
-           }
-           str = tmp;
-       } else if (tmp) {
-           tmp2 = strchr(tmp, '}');
-           if (tmp2 == NULL) {
-               if (*res)
-                   free(*res);
-               *res = NULL;
-               krb5_set_error_message(context, KRB5_CONFIG_BADFORMAT,
-                                      "variable missing }");
-               return KRB5_CONFIG_BADFORMAT;
-           }
-           if (strncasecmp(tmp, "%{uid}", 6) == 0)
-               asprintf(&append, "%u", (unsigned)getuid());
-           else if (strncasecmp(tmp, "%{null}", 7) == 0)
-               append = strdup("");
-           else {
-               if (*res)
-                   free(*res);
-               *res = NULL;
-               krb5_set_error_message(context,
-                                      KRB5_CONFIG_BADFORMAT,
-                                      "expand default cache unknown "
-                                      "variable \"%.*s\"",
-                                      (int)(tmp2 - tmp) - 2, tmp + 2);
-               return KRB5_CONFIG_BADFORMAT;
-           }
-           str = tmp2 + 1;
-       } else {
-           append = strdup(str);
-           str = NULL;
-       }
-       if (append == NULL) {
-           if (*res)
-               free(*res);
-           *res = NULL;
-           krb5_set_error_message(context, ENOMEM,
-                                  N_("malloc: out of memory", ""));
-           return ENOMEM;
-       }
-       
-       tlen = strlen(append);
-       tmp = realloc(*res, len + tlen + 1);
-       if (tmp == NULL) {
-           free(append);
-           if (*res)
-               free(*res);
-           *res = NULL;
-           krb5_set_error_message(context, ENOMEM,
-                                  N_("malloc: out of memory", ""));
-           return ENOMEM;
-       }
-       *res = tmp;
-       memcpy(*res + len, append, tlen + 1);
-       len = len + tlen;
-       free(append);
-    }
-    return 0;
-#else  /* _WIN32 */
-    /* On Windows, we use the more generic _krb5_expand_path_tokens()
-       function which also handles path tokens in addition to %{uid}
-       and %{null} */
-
     return _krb5_expand_path_tokens(context, str, res);
-#endif
 }
 
 /*
@@ -554,7 +498,7 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 krb5_cc_set_default_name(krb5_context context, const char *name)
 {
     krb5_error_code ret = 0;
-    char *p;
+    char *p = NULL, *exp_p = NULL;
 
     if (name == NULL) {
        const char *e = NULL;
@@ -606,26 +550,17 @@ krb5_cc_set_default_name(krb5_context context, const char *name)
        return ENOMEM;
     }
 
-#ifdef KRB5_USE_PATH_TOKENS
-    {
-       char * exp_p = NULL;
-
-       if (_krb5_expand_path_tokens(context, p, &exp_p) == 0) {
-           free (p);
-           p = exp_p;
-       } else {
-           free (p);
-           return EINVAL;
-       }
-    }
-#endif
+    ret = _krb5_expand_path_tokens(context, p, &exp_p);
+    free(p);
+    if (ret)
+       return ret;
 
     if (context->default_cc_name)
        free(context->default_cc_name);
 
-    context->default_cc_name = p;
+    context->default_cc_name = exp_p;
 
-    return ret;
+    return 0;
 }
 
 /**
@@ -1499,7 +1434,7 @@ krb5_cccol_cursor_next(krb5_context context, krb5_cccol_cursor cursor,
        cursor->cursor = NULL;
        if (ret != KRB5_CC_END)
            break;
-       
+
        cursor->idx++;
     }
     if (cursor->idx >= context->num_cc_ops) {
diff --git a/source4/heimdal/lib/krb5/ccache_plugin.h b/source4/heimdal/lib/krb5/ccache_plugin.h
new file mode 100644 (file)
index 0000000..f6871d6
--- /dev/null
@@ -0,0 +1,39 @@
+/***********************************************************************
+ * Copyright (c) 2010, Secure Endpoints Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **********************************************************************/
+
+#ifndef HEIMDAL_KRB5_CCACHE_PLUGIN_H
+#define HEIMDAL_KRB5_CCACHE_PLUGIN_H 1
+
+#include <krb5.h>
+
+#define KRB5_PLUGIN_CCACHE "ccache_ops"
+
+#endif /* HEIMDAL_KRB5_CCACHE_PLUGIN_H */
index 4eb4e12fad385ab3136f23f52ceba8a2086a4018..22d0b90bd8d4fae0fda3944f734ed1e246083897 100644 (file)
@@ -239,7 +239,12 @@ parse_binding(struct fileptr *f, unsigned *lineno, char *p,
     return ret;
 }
 
-#ifdef __APPLE__
+#if defined(__APPLE__)
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
+#define HAVE_CFPROPERTYLISTCREATEWITHSTREAM 1
+#endif
+
 static char *
 cfstring2cstring(CFStringRef string)
 {
@@ -293,7 +298,6 @@ parse_plist_config(krb5_context context, const char *path, krb5_config_section *
 {
     CFReadStreamRef s;
     CFDictionaryRef d;
-    CFErrorRef e;
     CFURLRef url;
     
     url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)path, strlen(path), FALSE);
@@ -315,7 +319,11 @@ parse_plist_config(krb5_context context, const char *path, krb5_config_section *
        return ENOENT;
     }
 
-    d = (CFDictionaryRef)CFPropertyListCreateWithStream (kCFAllocatorDefault, s, 0, kCFPropertyListImmutable, NULL, &e);
+#ifdef HAVE_CFPROPERTYLISTCREATEWITHSTREAM
+    d = (CFDictionaryRef)CFPropertyListCreateWithStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL);
+#else 
+    d = (CFDictionaryRef)CFPropertyListCreateFromStream(NULL, s, 0, kCFPropertyListImmutable, NULL, NULL);
+#endif
     CFRelease(s);
     if (d == NULL) {
        krb5_clear_error_message(context);
@@ -447,8 +455,9 @@ krb5_config_parse_file_multi (krb5_context context,
            fname = newfname;
        }
 #else  /* KRB5_USE_PATH_TOKENS */
-       asprintf(&newfname, "%%{USERCONFIG}/%s", &fname[1]);
-       if (newfname == NULL) {
+       if (asprintf(&newfname, "%%{USERCONFIG}%s", &fname[1]) < 0 || 
+           newfname == NULL)
+       {
            krb5_set_error_message(context, ENOMEM,
                                   N_("malloc: out of memory", ""));
            return ENOMEM;
index adcbb703ee104a14faf798a8e1721d7b3463da22..0897c5e7a09640fd376cdc14fe33855ee4edca53 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2010 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
  * All rights reserved.
  *
@@ -215,6 +215,14 @@ init_context_from_config_file(krb5_context context)
        krb5_config_free_strings(s);
     }
 
+    tmp = krb5_config_get_string(context, NULL, "libdefaults",
+                                "check-rd-req-server", NULL);
+    if (tmp == NULL && !issuid())
+       tmp = getenv("KRB5_CHECK_RD_REQ_SERVER");
+    if(tmp) {
+       if (strcasecmp(tmp, "ignore") == 0)
+           context->flags |= KRB5_CTX_F_RD_REQ_IGNORE;
+    }
 
     return 0;
 }
@@ -239,6 +247,7 @@ cc_ops_register(krb5_context context)
 #endif
     krb5_cc_register(context, &krb5_kcm_ops, TRUE);
 #endif
+    _krb5_load_ccache_plugins(context);
     return 0;
 }
 
@@ -380,6 +389,13 @@ out:
 
 #ifndef HEIMDAL_SMALLER
 
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_get_permitted_enctypes(krb5_context context,
+                           krb5_enctype **etypes)
+{
+    return krb5_get_default_in_tkt_etypes(context, etypes);
+}
+
 /*
  *
  */
index eda5e634d19704048b6ef6400bce5ff07bda8bc9..47f910260e36a0f734cd5268a63db1b1e7e5ac2b 100644 (file)
@@ -96,11 +96,11 @@ struct checksum_type {
     size_t blocksize;
     size_t checksumsize;
     unsigned flags;
-    krb5_enctype (*checksum)(krb5_context context,
-                            struct key_data *key,
-                            const void *buf, size_t len,
-                            unsigned usage,
-                            Checksum *csum);
+    krb5_error_code (*checksum)(krb5_context context,
+                               struct key_data *key,
+                               const void *buf, size_t len,
+                               unsigned usage,
+                               Checksum *csum);
     krb5_error_code (*verify)(krb5_context context,
                              struct key_data *key,
                              const void *buf, size_t len,
@@ -4004,7 +4004,7 @@ krb5_generate_random_block(void *buf, size_t len)
        rng_initialized = 1;
     }
     HEIMDAL_MUTEX_unlock(&crypto_mutex);
-    if (RAND_bytes(buf, len) != 1)
+    if (RAND_bytes(buf, len) <= 0)
        krb5_abortx(NULL, "Failed to generate random block");
 }
 
index 838135ffad9c3445d43a0ffb76b3f2523d2519df..c4c202be5db92fe7ddc294bc44675e974f00f08c 100644 (file)
@@ -87,7 +87,7 @@ krb5_free_data(krb5_context context,
 /**
  * Allocate data of and krb5_data.
  *
- * @param p krb5_data to free.
+ * @param p krb5_data to allocate.
  * @param len size to allocate.
  *
  * @return Returns 0 to indicate success. Otherwise an kerberos et
index adab6f5e84c64c132ad67aa2de957d9570e01bc7..237d346f4dcda072da7673130604066bbea7956b 100644 (file)
@@ -96,11 +96,17 @@ krb5_vset_error_message (krb5_context context, krb5_error_code ret,
                         const char *fmt, va_list args)
     __attribute__ ((format (printf, 3, 0)))
 {
+    int r;
 
-    krb5_clear_error_message(context);
     HEIMDAL_MUTEX_lock(context->mutex);
+    if (context->error_string) {
+       free(context->error_string);
+       context->error_string = NULL;
+    }
     context->error_code = ret;
-    vasprintf(&context->error_string, fmt, args);
+    r = vasprintf(&context->error_string, fmt, args);
+    if (r < 0)
+       context->error_string = NULL;
     HEIMDAL_MUTEX_unlock(context->mutex);
 }
 
@@ -144,19 +150,22 @@ krb5_vprepend_error_message(krb5_context context, krb5_error_code ret,
                            const char *fmt, va_list args)
     __attribute__ ((format (printf, 3, 0)))
 {
-    char *str, *str2;
+    char *str = NULL, *str2 = NULL;
     HEIMDAL_MUTEX_lock(context->mutex);
     if (context->error_code != ret) {
        HEIMDAL_MUTEX_unlock(context->mutex);
        return;
     }
-    vasprintf(&str, fmt, args);
+    if (vasprintf(&str, fmt, args) < 0 || str == NULL) {
+       HEIMDAL_MUTEX_unlock(context->mutex);
+       return;
+    }
     if (context->error_string) {
        int e;
 
        e = asprintf(&str2, "%s: %s", str, context->error_string);
        free(context->error_string);
-       if (e < 0)
+       if (e < 0 || str2 == NULL)
            context->error_string = NULL;
        else
            context->error_string = str2;
@@ -241,7 +250,7 @@ krb5_get_error_message(krb5_context context, krb5_error_code code)
            return strdup(msg);
     }
 
-    if (asprintf(&str, "<unknown error: %d>", (int)code) == -1)
+    if (asprintf(&str, "<unknown error: %d>", (int)code) == -1 || str == NULL)
        return NULL;
 
     return str;
diff --git a/source4/heimdal/lib/krb5/expand_path.c b/source4/heimdal/lib/krb5/expand_path.c
new file mode 100644 (file)
index 0000000..70096e1
--- /dev/null
@@ -0,0 +1,500 @@
+
+/***********************************************************************
+ * Copyright (c) 2009, Secure Endpoints Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ **********************************************************************/
+
+#include "krb5_locl.h"
+
+typedef int PTYPE;
+
+#ifdef _WIN32
+#include <shlobj.h>
+#include <sddl.h>
+
+/*
+ * Expand a %{TEMP} token
+ *
+ * The %{TEMP} token expands to the temporary path for the current
+ * user as returned by GetTempPath().
+ *
+ * @note: Since the GetTempPath() function relies on the TMP or TEMP
+ * environment variables, this function will failover to the system
+ * temporary directory until the user profile is loaded.  In addition,
+ * the returned path may or may not exist.
+ */
+static int
+_expand_temp_folder(krb5_context context, PTYPE param, const char *postfix, char **ret)
+{
+    TCHAR tpath[MAX_PATH];
+    size_t len;
+
+    if (!GetTempPath(sizeof(tpath)/sizeof(tpath[0]), tpath)) {
+       if (context)
+           krb5_set_error_message(context, EINVAL,
+                                  "Failed to get temporary path (GLE=%d)",
+                                  GetLastError());
+       return EINVAL;
+    }
+
+    len = strlen(tpath);
+
+    if (len > 0 && tpath[len - 1] == '\\')
+       tpath[len - 1] = '\0';
+
+    *ret = strdup(tpath);
+
+    if (*ret == NULL) {
+       if (context)
+           krb5_set_error_message(context, ENOMEM, "strdup - Out of memory");
+       return ENOMEM;
+    }
+
+    return 0;
+}
+
+extern HINSTANCE _krb5_hInstance;
+
+/*
+ * Expand a %{BINDIR} token
+ *
+ * This is also used to expand a few other tokens on Windows, since
+ * most of the executable binaries end up in the same directory.  The
+ * "bin" directory is considered to be the directory in which the
+ * krb5.dll is located.
+ */
+static int
+_expand_bin_dir(krb5_context context, PTYPE param, const char *postfix, char **ret)
+{
+    TCHAR path[MAX_PATH];
+    TCHAR *lastSlash;
+    DWORD nc;
+
+    nc = GetModuleFileName(_krb5_hInstance, path, sizeof(path)/sizeof(path[0]));
+    if (nc == 0 ||
+       nc == sizeof(path)/sizeof(path[0])) {
+       return EINVAL;
+    }
+
+    lastSlash = strrchr(path, '\\');
+    if (lastSlash != NULL) {
+       TCHAR *fslash = strrchr(lastSlash, '/');
+
+       if (fslash != NULL)
+           lastSlash = fslash;
+
+       *lastSlash = '\0';
+    }
+
+    if (postfix) {
+       if (strlcat(path, postfix, sizeof(path)/sizeof(path[0])) >= sizeof(path)/sizeof(path[0]))
+           return EINVAL;
+    }
+
+    *ret = strdup(path);
+    if (*ret == NULL)
+       return ENOMEM;
+
+    return 0;
+}
+
+/*
+ *  Expand a %{USERID} token
+ *
+ *  The %{USERID} token expands to the string representation of the
+ *  user's SID.  The user account that will be used is the account
+ *  corresponding to the current thread's security token.  This means
+ *  that:
+ *
+ *  - If the current thread token has the anonymous impersonation
+ *    level, the call will fail.
+ *
+ *  - If the current thread is impersonating a token at
+ *    SecurityIdentification level the call will fail.
+ *
+ */
+static int
+_expand_userid(krb5_context context, PTYPE param, const char *postfix, char **ret)
+{
+    int rv = EINVAL;
+    HANDLE hThread = NULL;
+    HANDLE hToken = NULL;
+    PTOKEN_OWNER pOwner = NULL;
+    DWORD len = 0;
+    LPTSTR strSid = NULL;
+
+    hThread = GetCurrentThread();
+
+    if (!OpenThreadToken(hThread, TOKEN_QUERY,
+                        FALSE, /* Open the thread token as the
+                                  current thread user. */
+                        &hToken)) {
+
+       DWORD le = GetLastError();
+
+       if (le == ERROR_NO_TOKEN) {
+           HANDLE hProcess = GetCurrentProcess();
+
+           le = 0;
+           if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
+               le = GetLastError();
+       }
+
+       if (le != 0) {
+           if (context)
+               krb5_set_error_message(context, rv, 
+                                      "Can't open thread token (GLE=%d)", le);
+           goto _exit;
+       }
+    }
+
+    if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &len)) {
+       if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+           if (context)
+               krb5_set_error_message(context, rv,
+                                      "Unexpected error reading token information (GLE=%d)",
+                                      GetLastError());
+           goto _exit;
+       }
+
+       if (len == 0) {
+           if (context)
+               krb5_set_error_message(context, rv,
+                                     "GetTokenInformation() returned truncated buffer");
+           goto _exit;
+       }
+
+       pOwner = malloc(len);
+       if (pOwner == NULL) {
+           if (context)
+               krb5_set_error_message(context, rv, "Out of memory");
+           goto _exit;
+       }
+    } else {
+       if (context)
+           krb5_set_error_message(context, rv, "GetTokenInformation() returned truncated buffer");
+       goto _exit;
+    }
+
+    if (!GetTokenInformation(hToken, TokenOwner, pOwner, len, &len)) {
+       if (context)
+           krb5_set_error_message(context, rv, "GetTokenInformation() failed. GLE=%d", GetLastError());
+       goto _exit;
+    }
+
+    if (!ConvertSidToStringSid(pOwner->Owner, &strSid)) {
+       if (context)
+           krb5_set_error_message(context, rv, "Can't convert SID to string. GLE=%d", GetLastError());
+       goto _exit;
+    }
+
+    *ret = strdup(strSid);
+    if (*ret == NULL && context)
+       krb5_set_error_message(context, rv, "Out of memory");
+
+    rv = 0;
+
+ _exit:
+    if (hToken != NULL)
+       CloseHandle(hToken);
+
+    if (pOwner != NULL)
+       free (pOwner);
+
+    if (strSid != NULL)
+       LocalFree(strSid);
+
+    return rv;
+}
+
+/*
+ * Expand a folder identified by a CSIDL
+ */
+
+static int
+_expand_csidl(krb5_context context, PTYPE folder, const char *postfix, char **ret)
+{
+    TCHAR path[MAX_PATH];
+    size_t len;
+
+    if (SHGetFolderPath(NULL, folder, NULL, SHGFP_TYPE_CURRENT, path) != S_OK) {
+       if (context)
+           krb5_set_error_message(context, EINVAL, "Unable to determine folder path");
+       return EINVAL;
+    } 
+
+    len = strlen(path);
+
+    if (len > 0 && path[len - 1] == '\\')
+       path[len - 1] = '\0';
+
+    if (postfix &&
+       strlcat(path, postfix, sizeof(path)/sizeof(path[0])) >= sizeof(path)/sizeof(path[0])) {
+       return ENOMEM;
+    }
+
+    *ret = strdup(path);
+    if (*ret == NULL) {
+       if (context)
+           krb5_set_error_message(context, ENOMEM, "Out of memory");
+       return ENOMEM;
+    }
+    return 0;
+}
+
+#else
+
+static int
+_expand_path(krb5_context context, PTYPE param, const char *postfix, char **ret)
+{
+    *ret = strdup(postfix);
+    if (*ret == NULL) {
+       krb5_set_error_message(context, ENOMEM, "malloc - out of memory");
+       return ENOMEM;
+    }
+    return 0;
+}
+
+static int
+_expand_temp_folder(krb5_context context, PTYPE param, const char *postfix, char **ret)
+{
+    const char *p = NULL;
+
+    if (issuid())
+       p = getenv("TEMP");
+    if (p)
+       *ret = strdup(p);
+    else
+       *ret = strdup("/tmp");
+    if (*ret == NULL)
+       return ENOMEM;
+    return 0;
+}
+
+static int
+_expand_userid(krb5_context context, PTYPE param, const char *postfix, char **str)
+{
+    int ret = asprintf(str, "%ld", (unsigned long)getuid());
+    if (ret < 0 || *str == NULL)
+       return ENOMEM;
+    return 0;
+}
+
+
+#endif /* _WIN32 */
+
+/**
+ * Expand a %{null} token
+ *
+ * The expansion of a %{null} token is always the empty string.
+ */
+
+static int
+_expand_null(krb5_context context, PTYPE param, const char *postfix, char **ret)
+{
+    *ret = strdup("");
+    if (*ret == NULL) {
+       if (context)
+           krb5_set_error_message(context, ENOMEM, "Out of memory");
+       return ENOMEM;
+    }
+    return 0;
+}
+
+
+static const struct token {
+    const char * tok;
+    int ftype;
+#define FTYPE_CSIDL 0
+#define FTYPE_SPECIAL 1
+
+    PTYPE param;
+    const char * postfix;
+
+    int (*exp_func)(krb5_context, PTYPE, const char *, char **);
+
+#define SPECIALP(f, P) FTYPE_SPECIAL, 0, P, f
+#define SPECIAL(f) SPECIALP(f, NULL)
+
+} tokens[] = {
+#ifdef _WIN32
+#define CSIDLP(C,P) FTYPE_CSIDL, C, P, _expand_csidl
+#define CSIDL(C) CSIDLP(C, NULL)
+
+    {"APPDATA", CSIDL(CSIDL_APPDATA)}, /* Roaming application data (for current user) */
+    {"COMMON_APPDATA", CSIDL(CSIDL_COMMON_APPDATA)}, /* Application data (all users) */
+    {"LOCAL_APPDATA", CSIDL(CSIDL_LOCAL_APPDATA)}, /* Local application data (for current user) */
+    {"SYSTEM", CSIDL(CSIDL_SYSTEM)}, /* Windows System folder (e.g. %WINDIR%\System32) */
+    {"WINDOWS", CSIDL(CSIDL_WINDOWS)}, /* Windows folder */
+    {"USERCONFIG", CSIDLP(CSIDL_APPDATA, "\\" PACKAGE)}, /* Per user Heimdal configuration file path */
+    {"COMMONCONFIG", CSIDLP(CSIDL_COMMON_APPDATA, "\\" PACKAGE)}, /* Common Heimdal configuration file path */
+    {"LIBDIR", SPECIAL(_expand_bin_dir)},
+    {"BINDIR", SPECIAL(_expand_bin_dir)},
+    {"LIBEXEC", SPECIAL(_expand_bin_dir)},
+    {"SBINDIR", SPECIAL(_expand_bin_dir)},
+#else
+    {"LIBDIR", FTYPE_SPECIAL, 0, LIBDIR, _expand_path},
+    {"BINDIR", FTYPE_SPECIAL, 0, BINDIR, _expand_path},
+    {"LIBEXEC", FTYPE_SPECIAL, 0, LIBEXECDIR, _expand_path},
+    {"SBINDIR", FTYPE_SPECIAL, 0, SBINDIR, _expand_path},
+#endif
+    {"TEMP", SPECIAL(_expand_temp_folder)},
+    {"USERID", SPECIAL(_expand_userid)},
+    {"uid", SPECIAL(_expand_userid)},
+    {"null", SPECIAL(_expand_null)}
+};
+
+static int
+_expand_token(krb5_context context,
+             const char *token,
+             const char *token_end,
+             char **ret)
+{
+    size_t i;
+
+    *ret = NULL;
+
+    if (token[0] != '%' || token[1] != '{' || token_end[0] != '}' ||
+       token_end - token <= 2) {
+       if (context)
+           krb5_set_error_message(context, EINVAL,"Invalid token.");
+       return EINVAL;
+    }
+
+    for (i = 0; i < sizeof(tokens)/sizeof(tokens[0]); i++) {
+       if (!strncmp(token+2, tokens[i].tok, (token_end - token) - 2))
+           return tokens[i].exp_func(context, tokens[i].param,
+                                     tokens[i].postfix, ret);
+    }
+
+    if (context)
+       krb5_set_error_message(context, EINVAL, "Invalid token.");
+    return EINVAL;
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+_krb5_expand_path_tokens(krb5_context context,
+                        const char *path_in,
+                        char **ppath_out)
+{
+    char *tok_begin, *tok_end, *append;
+    const char *path_left;
+    size_t len = 0;
+
+    if (path_in == NULL || *path_in == '\0') {
+        *ppath_out = strdup("");
+        return 0;
+    }
+
+    *ppath_out = NULL;
+
+    for (path_left = path_in; path_left && *path_left; ) {
+
+       tok_begin = strstr(path_left, "%{");
+
+       if (tok_begin && tok_begin != path_left) {
+
+           append = malloc((tok_begin - path_left) + 1);
+           if (append) {
+               memcpy(append, path_left, tok_begin - path_left);
+               append[tok_begin - path_left] = '\0';
+           }
+           path_left = tok_begin;
+
+       } else if (tok_begin) {
+
+           tok_end = strchr(tok_begin, '}');
+           if (tok_end == NULL) {
+               if (*ppath_out)
+                   free(*ppath_out);
+               *ppath_out = NULL;
+               if (context)
+                   krb5_set_error_message(context, EINVAL, "variable missing }");
+               return EINVAL;
+           }
+
+           if (_expand_token(context, tok_begin, tok_end, &append)) {
+               if (*ppath_out)
+                   free(*ppath_out);
+               *ppath_out = NULL;
+               return EINVAL;
+           }
+
+           path_left = tok_end + 1;
+       } else {
+
+           append = strdup(path_left);
+           path_left = NULL;
+
+       }
+
+       if (append == NULL) {
+
+           if (*ppath_out)
+               free(*ppath_out);
+           *ppath_out = NULL;
+           if (context)
+               krb5_set_error_message(context, ENOMEM, "malloc - out of memory");
+           return ENOMEM;
+
+       }
+       
+       {
+           size_t append_len = strlen(append);
+           char * new_str = realloc(*ppath_out, len + append_len + 1);
+
+           if (new_str == NULL) {
+               free(append);
+               if (*ppath_out)
+                   free(*ppath_out);
+               *ppath_out = NULL;
+               if (context)
+                   krb5_set_error_message(context, ENOMEM, "malloc - out of memory");
+               return ENOMEM;
+           }
+
+           *ppath_out = new_str;
+           memcpy(*ppath_out + len, append, append_len + 1);
+           len = len + append_len;
+           free(append);
+       }
+    }
+
+#ifdef _WIN32
+    /* Also deal with slashes */
+    if (*ppath_out) {
+       char * c;
+       for (c = *ppath_out; *c; c++)
+           if (*c == '/')
+               *c = '\\';
+    }
+#endif
+
+    return 0;
+}
index 67c4c744449b80f0f5effef682ca4b2d271bd07b..218bd2cdbfed27fdd3017df49c087c170fa7086b 100644 (file)
@@ -58,7 +58,7 @@ struct fcc_cursor {
 
 #define FCC_CURSOR(C) ((struct fcc_cursor*)(C))
 
-static const char*
+static const char* KRB5_CALLCONV
 fcc_get_name(krb5_context context,
             krb5_ccache id)
 {
@@ -167,20 +167,20 @@ write_storage(krb5_context context, krb5_storage *sp, int fd)
 }
 
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_lock(krb5_context context, krb5_ccache id,
         int fd, krb5_boolean exclusive)
 {
     return _krb5_xlock(context, fd, exclusive, fcc_get_name(context, id));
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_unlock(krb5_context context, int fd)
 {
     return _krb5_xunlock(context, fd);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
 {
     krb5_fcache *f;
@@ -304,12 +304,13 @@ _krb5_erase_file(krb5_context context, const char *filename)
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_gen_new(krb5_context context, krb5_ccache *id)
 {
+    char *file = NULL, *exp_file = NULL;
+    krb5_error_code ret;
     krb5_fcache *f;
     int fd;
-    char *file;
 
     f = malloc(sizeof(*f));
     if(f == NULL) {
@@ -317,39 +318,30 @@ fcc_gen_new(krb5_context context, krb5_ccache *id)
                               N_("malloc: out of memory", ""));
        return KRB5_CC_NOMEM;
     }
-    asprintf (&file, "%sXXXXXX", KRB5_DEFAULT_CCFILE_ROOT);
-    if(file == NULL) {
+    ret = asprintf (&file, "%sXXXXXX", KRB5_DEFAULT_CCFILE_ROOT);
+    if(ret < 0 || file == NULL) {
        free(f);
        krb5_set_error_message(context, KRB5_CC_NOMEM,
                               N_("malloc: out of memory", ""));
        return KRB5_CC_NOMEM;
     }
-#ifdef KRB5_USE_PATH_TOKENS
-    {
-       char * exp_file = NULL;
-       krb5_error_code ec;
+    ret = _krb5_expand_path_tokens(context, file, &exp_file);
+    free(file);
+    if (ret)
+       return ret;
 
-       ec = _krb5_expand_path_tokens(context, file, &exp_file);
+    file = exp_file;
 
-       if (ec == 0) {
-           free(file);
-           file = exp_file;
-       } else {
-           free(file);
-           return ec;
-       }
-    }
-#endif
-    fd = mkstemp(file);
+    fd = mkstemp(exp_file);
     if(fd < 0) {
        int ret = errno;
-       krb5_set_error_message(context, ret, N_("mkstemp %s failed", ""), file);
+       krb5_set_error_message(context, ret, N_("mkstemp %s failed", ""), exp_file);
        free(f);
-       free(file);
+       free(exp_file);
        return ret;
     }
     close(fd);
-    f->filename = file;
+    f->filename = exp_file;
     f->version = 0;
     (*id)->data.data = f;
     (*id)->data.length = sizeof(*f);
@@ -381,7 +373,7 @@ storage_set_flags(krb5_context context, krb5_storage *sp, int vno)
     krb5_storage_set_flags(sp, flags);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_open(krb5_context context,
         krb5_ccache id,
         int *fd_ret,
@@ -412,7 +404,7 @@ fcc_open(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_initialize(krb5_context context,
               krb5_ccache id,
               krb5_principal primary_principal)
@@ -468,7 +460,7 @@ fcc_initialize(krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_close(krb5_context context,
          krb5_ccache id)
 {
@@ -477,7 +469,7 @@ fcc_close(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_destroy(krb5_context context,
            krb5_ccache id)
 {
@@ -485,7 +477,7 @@ fcc_destroy(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_store_cred(krb5_context context,
               krb5_ccache id,
               krb5_creds *creds)
@@ -675,7 +667,7 @@ init_fcc (krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_get_principal(krb5_context context,
                  krb5_ccache id,
                  krb5_principal *principal)
@@ -696,12 +688,12 @@ fcc_get_principal(krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_end_get (krb5_context context,
             krb5_ccache id,
             krb5_cc_cursor *cursor);
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_get_first (krb5_context context,
               krb5_ccache id,
               krb5_cc_cursor *cursor)
@@ -734,7 +726,7 @@ fcc_get_first (krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_get_next (krb5_context context,
              krb5_ccache id,
              krb5_cc_cursor *cursor,
@@ -752,7 +744,7 @@ fcc_get_next (krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_end_get (krb5_context context,
             krb5_ccache id,
             krb5_cc_cursor *cursor)
@@ -764,7 +756,7 @@ fcc_end_get (krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_remove_cred(krb5_context context,
                 krb5_ccache id,
                 krb5_flags which,
@@ -772,7 +764,7 @@ fcc_remove_cred(krb5_context context,
 {
     krb5_error_code ret;
     krb5_ccache copy, newfile;
-    char *newname;
+    char *newname = NULL;
     int fd;
 
     ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &copy);
@@ -791,10 +783,10 @@ fcc_remove_cred(krb5_context context,
        return ret;
     }
 
-    asprintf(&newname, "FILE:%s.XXXXXX", FILENAME(id));
-    if (newname == NULL) {
+    ret = asprintf(&newname, "FILE:%s.XXXXXX", FILENAME(id));
+    if (ret < 0 || newname == NULL) {
        krb5_cc_destroy(context, copy);
-       return ret;
+       return ENOMEM;
     }
 
     fd = mkstemp(&newname[5]);
@@ -821,7 +813,7 @@ fcc_remove_cred(krb5_context context,
        return ret;
     }
 
-    ret = rename(&newname[5], FILENAME(id));
+    ret = rk_rename(&newname[5], FILENAME(id));
     if (ret)
        ret = errno;
     free(newname);
@@ -830,7 +822,7 @@ fcc_remove_cred(krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_set_flags(krb5_context context,
              krb5_ccache id,
              krb5_flags flags)
@@ -838,7 +830,7 @@ fcc_set_flags(krb5_context context,
     return 0; /* XXX */
 }
 
-static int
+static int KRB5_CALLCONV
 fcc_get_version(krb5_context context,
                krb5_ccache id)
 {
@@ -849,7 +841,7 @@ struct fcache_iter {
     int first;
 };
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
 {
     struct fcache_iter *iter;
@@ -864,7 +856,7 @@ fcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
 {
     struct fcache_iter *iter = cursor;
@@ -904,7 +896,7 @@ fcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
 {
     struct fcache_iter *iter = cursor;
@@ -912,20 +904,12 @@ fcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
 {
     krb5_error_code ret = 0;
 
-    ret = rename(FILENAME(from), FILENAME(to));
-#ifdef RENAME_DOES_NOT_UNLINK
-    if (ret && (errno == EEXIST || errno == EACCES)) {
-       ret = unlink(FILENAME(to));
-       if (ret == 0) {
-           ret = rename(FILENAME(from), FILENAME(to));
-       }
-    }
-#endif
+    ret = rk_rename(FILENAME(from), FILENAME(to));
 
     if (ret && errno != EXDEV) {
        char buf[128];
@@ -990,11 +974,12 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
     {
        krb5_storage *sp;
        int fd;
-       ret = init_fcc (context, to, &sp, &fd, NULL);
-       if (sp)
-           krb5_storage_free(sp);
-       fcc_unlock(context, fd);
-       close(fd);
+       if ((ret = init_fcc (context, to, &sp, &fd, NULL)) == 0) {
+           if (sp)
+               krb5_storage_free(sp);
+           fcc_unlock(context, fd);
+           close(fd);
+       }
     }
 
     fcc_close(context, from);
@@ -1002,7 +987,7 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_get_default_name(krb5_context context, char **str)
 {
     return _krb5_expand_default_cc_name(context,
@@ -1010,7 +995,7 @@ fcc_get_default_name(krb5_context context, char **str)
                                        str);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime)
 {
     krb5_error_code ret;
@@ -1031,17 +1016,17 @@ fcc_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_set_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat kdc_offset)
 {
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fcc_get_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat *kdc_offset)
 {
     krb5_error_code ret;
-    krb5_storage *sp;
+    krb5_storage *sp = NULL;
     int fd;
     ret = init_fcc(context, id, &sp, &fd, kdc_offset);
     if (sp)
index 575f842d8b8d7dd7042da0e947b63e0fa7225767..6001d6926138e1337f96e13164af29a3f5ccac25 100644 (file)
@@ -38,7 +38,7 @@ krb5_generate_seq_number(krb5_context context,
                         const krb5_keyblock *key,
                         uint32_t *seqno)
 {
-    if (RAND_bytes((void *)seqno, sizeof(*seqno)) != 1)
+    if (RAND_bytes((void *)seqno, sizeof(*seqno)) <= 0)
        krb5_abortx(context, "Failed to generate random block");
     /* MIT used signed numbers, lets not stomp into that space directly */
     *seqno &= 0x3fffffff;
index 75e44f0cd41aa6980dc48d8d5e738c46d4008d9c..8f9d46219023b500607782cd93f8ba3b39b0cd75 100644 (file)
@@ -314,7 +314,7 @@ _krb5_get_krbtgt(krb5_context context,
 }
 
 /* DCE compatible decrypt proc */
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 decrypt_tkt_with_subkey (krb5_context context,
                         krb5_keyblock *key,
                         krb5_key_usage usage,
@@ -939,9 +939,9 @@ get_cred_kdc_referral(krb5_context context,
            ret = EINVAL;
 
        if (ret) {
-           ret = get_cred_kdc_address (context, ccache, flags, NULL,
-                                       &referral, &tgt, impersonate_principal,
-                                       second_ticket, &ticket);
+           ret = get_cred_kdc_address(context, ccache, flags, NULL,
+                                      &referral, &tgt, impersonate_principal,
+                                      second_ticket, &ticket);
            if (ret)
                goto out;
        }
@@ -956,8 +956,8 @@ get_cred_kdc_referral(krb5_context context,
            krb5_set_error_message(context, KRB5KRB_AP_ERR_NOT_US,
                                   N_("Got back an non krbtgt "
                                      "ticket referrals", ""));
-           krb5_free_cred_contents(context, &ticket);
-           return KRB5KRB_AP_ERR_NOT_US;
+           ret = KRB5KRB_AP_ERR_NOT_US;
+           goto out;
        }
 
        referral_realm = ticket.server->name.name_string.val[1];
@@ -979,8 +979,8 @@ get_cred_kdc_referral(krb5_context context,
                                          "loops back to realm %s", ""),
                                       tgt.server->realm,
                                       referral_realm);
-               krb5_free_cred_contents(context, &ticket);
-               return KRB5_GET_IN_TKT_LOOP;
+               ret = KRB5_GET_IN_TKT_LOOP;
+                goto out;
            }
            tickets++;
        }       
@@ -996,10 +996,8 @@ get_cred_kdc_referral(krb5_context context,
        }
 
        ret = add_cred(context, &ticket, ret_tgts);
-       if (ret) {
-           krb5_free_cred_contents(context, &ticket);
+       if (ret)
            goto out;
-       }
 
        /* try realm in the referral */
        ret = krb5_principal_set_realm(context,
@@ -1017,6 +1015,7 @@ get_cred_kdc_referral(krb5_context context,
 out:
     krb5_free_principal(context, referral.server);
     krb5_free_cred_contents(context, &tgt);
+    krb5_free_cred_contents(context, &ticket);
     return ret;
 }
 
index 539dedfa47ee571f7b20e12ad349af8e410e5841..ba4301ce297a0304bbbd5f96b5207eb3ef4b8fb1 100644 (file)
@@ -104,8 +104,6 @@ krb5_error_code
 _krb5_get_default_principal_local(krb5_context context,
                                  krb5_principal *princ)
 {
-    krb5_error_code ret = 0;
-
     /* See if we can get the principal first.  We only expect this to
        work if logged into a domain. */
     {
index f4437880757b9e30f0d9e448a6029ff8675d735b..869687aa63b5a6e40d77103fcdb4bfc2ee82beb0 100644 (file)
@@ -94,7 +94,7 @@ free_paid(krb5_context context, struct pa_info_data *ppaid)
        krb5_free_data(context, ppaid->s2kparams);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 default_s2k_func(krb5_context context, krb5_enctype type,
                 krb5_const_pointer keyseed,
                 krb5_salt salt, krb5_data *s2kparms,
@@ -234,11 +234,12 @@ report_expiration (krb5_context context,
                   const char *str,
                   time_t now)
 {
-    char *p;
+    char *p = NULL;
 
-    asprintf (&p, "%s%s", str, ctime(&now));
-    (*prompter) (context, data, NULL, p, 0, NULL);
-    free (p);
+    if (asprintf(&p, "%s%s", str, ctime(&now)) < 0 || p == NULL)
+       return;
+    (*prompter)(context, data, NULL, p, 0, NULL);
+    free(p);
 }
 
 /*
@@ -562,10 +563,14 @@ change_password (krb5_context context,
                             &result_string);
     if (ret)
        goto out;
-    asprintf (&p, "%s: %.*s\n",
-             result_code ? "Error" : "Success",
-             (int)result_string.length,
-             result_string.length > 0 ? (char*)result_string.data : "");
+    if (asprintf(&p, "%s: %.*s\n",
+                result_code ? "Error" : "Success",
+                (int)result_string.length,
+                result_string.length > 0 ? (char*)result_string.data : "") < 0)
+    {
+       ret = ENOMEM;
+       goto out;
+    }
 
     /* return the result */
     (*prompter) (context, data, NULL, p, 0, NULL);
@@ -1454,7 +1459,7 @@ krb5_init_creds_set_password(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 keytab_key_proc(krb5_context context, krb5_enctype enctype,
                krb5_const_pointer keyseed,
                krb5_salt salt, krb5_data *s2kparms,
@@ -1581,7 +1586,7 @@ krb5_init_creds_set_keytab(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 keyblock_key_proc(krb5_context context, krb5_enctype enctype,
                  krb5_const_pointer keyseed,
                  krb5_salt salt, krb5_data *s2kparms,
@@ -1613,7 +1618,8 @@ krb5_init_creds_set_keyblock(krb5_context context,
  * @param in input data from KDC, first round it should be reset by krb5_data_zer().
  * @param out reply to KDC.
  * @param hostinfo KDC address info, first round it can be NULL.
- * @param flags status of the round, if 1 is set, continue one more round.
+ * @param flags status of the round, if
+ *        KRB5_INIT_CREDS_STEP_FLAG_CONTINUE is set, continue one more round.
  *
  * @return 0 for success, or an Kerberos 5 error code, see
  *     krb5_get_error_message().
@@ -1816,7 +1822,7 @@ krb5_init_creds_step(krb5_context context,
     out->data = ctx->req_buffer.data;
     out->length = ctx->req_buffer.length;
 
-    *flags = 1;
+    *flags = KRB5_INIT_CREDS_STEP_FLAG_CONTINUE;
 
     return 0;
  out:
index 01ea184773eedcb6e588f38a57309418b484ec8e..80a72ecbf7ccd9de630441ab1659352ddcd57d2f 100644 (file)
@@ -1202,94 +1202,6 @@ _krb5_kcm_noop(krb5_context context,
 }
 
 
-/*
- * Request:
- *      NameZ
- *      Mode
- *
- * Response:
- *
- */
-krb5_error_code
-_krb5_kcm_chmod(krb5_context context,
-               krb5_ccache id,
-               uint16_t mode)
-{
-    krb5_error_code ret;
-    krb5_kcmcache *k = KCMCACHE(id);
-    krb5_storage *request;
-
-    ret = krb5_kcm_storage_request(context, KCM_OP_CHMOD, &request);
-    if (ret)
-       return ret;
-
-    ret = krb5_store_stringz(request, k->name);
-    if (ret) {
-       krb5_storage_free(request);
-       return ret;
-    }
-
-    ret = krb5_store_int16(request, mode);
-    if (ret) {
-       krb5_storage_free(request);
-       return ret;
-    }
-
-    ret = krb5_kcm_call(context, request, NULL, NULL);
-
-    krb5_storage_free(request);
-    return ret;
-}
-
-
-/*
- * Request:
- *      NameZ
- *      UID
- *      GID
- *
- * Response:
- *
- */
-krb5_error_code
-_krb5_kcm_chown(krb5_context context,
-               krb5_ccache id,
-               uint32_t uid,
-               uint32_t gid)
-{
-    krb5_error_code ret;
-    krb5_kcmcache *k = KCMCACHE(id);
-    krb5_storage *request;
-
-    ret = krb5_kcm_storage_request(context, KCM_OP_CHOWN, &request);
-    if (ret)
-       return ret;
-
-    ret = krb5_store_stringz(request, k->name);
-    if (ret) {
-       krb5_storage_free(request);
-       return ret;
-    }
-
-    ret = krb5_store_int32(request, uid);
-    if (ret) {
-       krb5_storage_free(request);
-       return ret;
-    }
-
-    ret = krb5_store_int32(request, gid);
-    if (ret) {
-       krb5_storage_free(request);
-       return ret;
-    }
-
-    ret = krb5_kcm_call(context, request, NULL, NULL);
-
-    krb5_storage_free(request);
-    return ret;
-}
-
-
 /*
  * Request:
  *      NameZ
index 79b079a0563d78003c5e198b4ee713d869415a9b..d1ffd5773800dc07cb00649a9b5c927e1d7bd0e9 100644 (file)
  *   store the keytab in a AFS keyfile (usually /usr/afs/etc/KeyFile ),
  *   the type's name is AFSKEYFILE. The residual part is a filename.
  *
- * - krb4
- *   the keytab is a Kerberos 4 srvtab that is on-the-fly converted to
- *   a keytab. The type's name is krb4 The residual part is a
- *   filename.
- *
  * - memory
  *   The keytab is stored in a memory segment. This allows sensitive
  *   and/or temporary data not to be stored on disk. The type's name
@@ -113,7 +108,7 @@ main (int argc, char **argv)
     if (ret)
        krb5_err(context, 1, ret, "krb5_kt_start_seq_get");
     while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
-       krb5_unparse_name_short(context, entry.principal, &principal);
+       krb5_unparse_name(context, entry.principal, &principal);
        printf("principal: %s\n", principal);
        free(principal);
        krb5_kt_free_entry(context, &entry);
index 02de8c8028cd40b3f62ac4942bc8f87f72615807..d05696476921cabaebf1d1446a81af2324d59c1a 100644 (file)
@@ -53,7 +53,7 @@ free_list (krb5_context context, struct any_data *a)
     }
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 any_resolve(krb5_context context, const char *name, krb5_keytab id)
 {
     struct any_data *a, *a0 = NULL, *prev = NULL;
@@ -95,7 +95,7 @@ any_resolve(krb5_context context, const char *name, krb5_keytab id)
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 any_get_name (krb5_context context,
              krb5_keytab id,
              char *name,
@@ -106,7 +106,7 @@ any_get_name (krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 any_close (krb5_context context,
           krb5_keytab id)
 {
@@ -121,7 +121,7 @@ struct any_cursor_extra_data {
     krb5_kt_cursor cursor;
 };
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 any_start_seq_get(krb5_context context,
                  krb5_keytab id,
                  krb5_kt_cursor *c)
@@ -150,7 +150,7 @@ any_start_seq_get(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 any_next_entry (krb5_context context,
                krb5_keytab id,
                krb5_keytab_entry *entry,
@@ -182,7 +182,7 @@ any_next_entry (krb5_context context,
     } while (1);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 any_end_seq_get(krb5_context context,
                krb5_keytab id,
                krb5_kt_cursor *cursor)
@@ -198,7 +198,7 @@ any_end_seq_get(krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 any_add_entry(krb5_context context,
              krb5_keytab id,
              krb5_keytab_entry *entry)
@@ -218,7 +218,7 @@ any_add_entry(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 any_remove_entry(krb5_context context,
                 krb5_keytab id,
                 krb5_keytab_entry *entry)
index 9a21db0cbb297dfc6fe7325ed531cf7b5545cd5b..2b9ea7f11de8b03f4147272bf3f850a7026c12a3 100644 (file)
@@ -286,7 +286,7 @@ krb5_kt_store_principal(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_resolve(krb5_context context, const char *name, krb5_keytab id)
 {
     struct fkt_data *d;
@@ -307,7 +307,7 @@ fkt_resolve(krb5_context context, const char *name, krb5_keytab id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_resolve_java14(krb5_context context, const char *name, krb5_keytab id)
 {
     krb5_error_code ret;
@@ -320,7 +320,7 @@ fkt_resolve_java14(krb5_context context, const char *name, krb5_keytab id)
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_close(krb5_context context, krb5_keytab id)
 {
     struct fkt_data *d = id->data;
@@ -329,7 +329,7 @@ fkt_close(krb5_context context, krb5_keytab id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_destroy(krb5_context context, krb5_keytab id)
 {
     struct fkt_data *d = id->data;
@@ -337,7 +337,7 @@ fkt_destroy(krb5_context context, krb5_keytab id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_get_name(krb5_context context,
             krb5_keytab id,
             char *name,
@@ -430,7 +430,7 @@ fkt_start_seq_get_int(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_start_seq_get(krb5_context context,
                  krb5_keytab id,
                  krb5_kt_cursor *c)
@@ -503,7 +503,7 @@ loop:
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_next_entry(krb5_context context,
               krb5_keytab id,
               krb5_keytab_entry *entry,
@@ -512,7 +512,7 @@ fkt_next_entry(krb5_context context,
     return fkt_next_entry_int(context, id, entry, cursor, NULL, NULL);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_end_seq_get(krb5_context context,
                krb5_keytab id,
                krb5_kt_cursor *cursor)
@@ -523,7 +523,7 @@ fkt_end_seq_get(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_setup_keytab(krb5_context context,
                 krb5_keytab id,
                 krb5_storage *sp)
@@ -537,7 +537,7 @@ fkt_setup_keytab(krb5_context context,
     return krb5_store_int8 (sp, id->version);
 }
                
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_add_entry(krb5_context context,
              krb5_keytab id,
              krb5_keytab_entry *entry)
@@ -723,7 +723,7 @@ fkt_add_entry(krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 fkt_remove_entry(krb5_context context,
                 krb5_keytab id,
                 krb5_keytab_entry *entry)
index 54666c7d447dbe0e9e4802654bf534435340297f..28bbaeee8c364418c53bd5abdcf6378a4eff49b6 100644 (file)
@@ -128,7 +128,7 @@ get_cell_and_realm (krb5_context context, struct akf_data *d)
  * init and get filename
  */
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 akf_resolve(krb5_context context, const char *name, krb5_keytab id)
 {
     int ret;
@@ -164,7 +164,7 @@ akf_resolve(krb5_context context, const char *name, krb5_keytab id)
  * cleanup
  */
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 akf_close(krb5_context context, krb5_keytab id)
 {
     struct akf_data *d = id->data;
@@ -179,7 +179,7 @@ akf_close(krb5_context context, krb5_keytab id)
  * Return filename
  */
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 akf_get_name(krb5_context context,
             krb5_keytab id,
             char *name,
@@ -195,7 +195,7 @@ akf_get_name(krb5_context context,
  * Init
  */
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 akf_start_seq_get(krb5_context context,
                  krb5_keytab id,
                  krb5_kt_cursor *c)
@@ -226,7 +226,7 @@ akf_start_seq_get(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 akf_next_entry(krb5_context context,
               krb5_keytab id,
               krb5_keytab_entry *entry,
@@ -281,7 +281,7 @@ akf_next_entry(krb5_context context,
     return ret;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 akf_end_seq_get(krb5_context context,
                krb5_keytab id,
                krb5_kt_cursor *cursor)
@@ -291,7 +291,7 @@ akf_end_seq_get(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 akf_add_entry(krb5_context context,
              krb5_keytab id,
              krb5_keytab_entry *entry)
index 73ffa1c67d7fa3353db83d578397319fe5b4892f..0ee684d363824aec0e4d84f3e2ed2cd82be38544 100644 (file)
@@ -50,7 +50,7 @@ static HEIMDAL_MUTEX mkt_mutex = HEIMDAL_MUTEX_INITIALIZER;
 static struct mkt_data *mkt_head;
 
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mkt_resolve(krb5_context context, const char *name, krb5_keytab id)
 {
     struct mkt_data *d;
@@ -95,7 +95,7 @@ mkt_resolve(krb5_context context, const char *name, krb5_keytab id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mkt_close(krb5_context context, krb5_keytab id)
 {
     struct mkt_data *d = id->data, **dp;
@@ -126,7 +126,7 @@ mkt_close(krb5_context context, krb5_keytab id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mkt_get_name(krb5_context context,
             krb5_keytab id,
             char *name,
@@ -137,7 +137,7 @@ mkt_get_name(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mkt_start_seq_get(krb5_context context,
                  krb5_keytab id,
                  krb5_kt_cursor *c)
@@ -147,7 +147,7 @@ mkt_start_seq_get(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mkt_next_entry(krb5_context context,
               krb5_keytab id,
               krb5_keytab_entry *entry,
@@ -159,7 +159,7 @@ mkt_next_entry(krb5_context context,
     return krb5_kt_copy_entry_contents(context, &d->entries[c->fd++], entry);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mkt_end_seq_get(krb5_context context,
                krb5_keytab id,
                krb5_kt_cursor *cursor)
@@ -167,7 +167,7 @@ mkt_end_seq_get(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mkt_add_entry(krb5_context context,
              krb5_keytab id,
              krb5_keytab_entry *entry)
@@ -185,7 +185,7 @@ mkt_add_entry(krb5_context context,
                                       &d->entries[d->num_entries++]);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mkt_remove_entry(krb5_context context,
                 krb5_keytab id,
                 krb5_keytab_entry *entry)
index c810b8bc749d8a29f88c9e90a8f76994f30599ca..8f4210e19b01e90bbf3b3bc269d42cedfc11ca58 100644 (file)
 #endif
 #endif
 
+#ifdef _WIN32
+#define KRB5_CALLCONV __stdcall
+#else
+#define KRB5_CALLCONV
+#endif
+
 /* simple constants */
 
 #ifndef TRUE
@@ -404,6 +410,10 @@ typedef union {
 #define KRB5_TC_MATCH_2ND_TKT          (1 << 23)
 #define KRB5_TC_MATCH_IS_SKEY          (1 << 22)
 
+/* constants for get_flags and set_flags */
+#define KRB5_TC_OPENCLOSE 0x00000001
+#define KRB5_TC_NOTICKET  0x00000002
+
 typedef AuthorizationData krb5_authdata;
 
 typedef KRB_ERROR krb5_error;
@@ -427,33 +437,34 @@ typedef struct krb5_cc_cache_cursor_data *krb5_cc_cache_cursor;
 typedef struct krb5_cc_ops {
     int version;
     const char *prefix;
-    const char* (*get_name)(krb5_context, krb5_ccache);
-    krb5_error_code (*resolve)(krb5_context, krb5_ccache *, const char *);
-    krb5_error_code (*gen_new)(krb5_context, krb5_ccache *);
-    krb5_error_code (*init)(krb5_context, krb5_ccache, krb5_principal);
-    krb5_error_code (*destroy)(krb5_context, krb5_ccache);
-    krb5_error_code (*close)(krb5_context, krb5_ccache);
-    krb5_error_code (*store)(krb5_context, krb5_ccache, krb5_creds*);
-    krb5_error_code (*retrieve)(krb5_context, krb5_ccache,
-                               krb5_flags, const krb5_creds*, krb5_creds *);
-    krb5_error_code (*get_princ)(krb5_context, krb5_ccache, krb5_principal*);
-    krb5_error_code (*get_first)(krb5_context, krb5_ccache, krb5_cc_cursor *);
-    krb5_error_code (*get_next)(krb5_context, krb5_ccache,
-                               krb5_cc_cursor*, krb5_creds*);
-    krb5_error_code (*end_get)(krb5_context, krb5_ccache, krb5_cc_cursor*);
-    krb5_error_code (*remove_cred)(krb5_context, krb5_ccache,
-                                  krb5_flags, krb5_creds*);
-    krb5_error_code (*set_flags)(krb5_context, krb5_ccache, krb5_flags);
-    int (*get_version)(krb5_context, krb5_ccache);
-    krb5_error_code (*get_cache_first)(krb5_context, krb5_cc_cursor *);
-    krb5_error_code (*get_cache_next)(krb5_context, krb5_cc_cursor, krb5_ccache *);
-    krb5_error_code (*end_cache_get)(krb5_context, krb5_cc_cursor);
-    krb5_error_code (*move)(krb5_context, krb5_ccache, krb5_ccache);
-    krb5_error_code (*get_default_name)(krb5_context, char **);
-    krb5_error_code (*set_default)(krb5_context, krb5_ccache);
-    krb5_error_code (*lastchange)(krb5_context, krb5_ccache, krb5_timestamp *);
-    krb5_error_code (*set_kdc_offset)(krb5_context, krb5_ccache, krb5_deltat);
-    krb5_error_code (*get_kdc_offset)(krb5_context, krb5_ccache, krb5_deltat *);
+    const char* (KRB5_CALLCONV * get_name)(krb5_context, krb5_ccache);
+    krb5_error_code (KRB5_CALLCONV * resolve)(krb5_context, krb5_ccache *, const char *);
+    krb5_error_code (KRB5_CALLCONV * gen_new)(krb5_context, krb5_ccache *);
+    krb5_error_code (KRB5_CALLCONV * init)(krb5_context, krb5_ccache, krb5_principal);
+    krb5_error_code (KRB5_CALLCONV * destroy)(krb5_context, krb5_ccache);
+    krb5_error_code (KRB5_CALLCONV * close)(krb5_context, krb5_ccache);
+    krb5_error_code (KRB5_CALLCONV * store)(krb5_context, krb5_ccache, krb5_creds*);
+    krb5_error_code (KRB5_CALLCONV * retrieve)(krb5_context, krb5_ccache,
+                                              krb5_flags, const krb5_creds*, krb5_creds *);
+    krb5_error_code (KRB5_CALLCONV * get_princ)(krb5_context, krb5_ccache, krb5_principal*);
+    krb5_error_code (KRB5_CALLCONV * get_first)(krb5_context, krb5_ccache, krb5_cc_cursor *);
+    krb5_error_code (KRB5_CALLCONV * get_next)(krb5_context, krb5_ccache,
+                                              krb5_cc_cursor*, krb5_creds*);
+    krb5_error_code (KRB5_CALLCONV * end_get)(krb5_context, krb5_ccache, krb5_cc_cursor*);
+    krb5_error_code (KRB5_CALLCONV * remove_cred)(krb5_context, krb5_ccache,
+                                                 krb5_flags, krb5_creds*);
+    krb5_error_code (KRB5_CALLCONV * set_flags)(krb5_context, krb5_ccache, krb5_flags);
+    int (KRB5_CALLCONV * get_version)(krb5_context, krb5_ccache);
+    krb5_error_code (KRB5_CALLCONV * get_cache_first)(krb5_context, krb5_cc_cursor *);
+    krb5_error_code (KRB5_CALLCONV * get_cache_next)(krb5_context, krb5_cc_cursor,
+                                                    krb5_ccache *);
+    krb5_error_code (KRB5_CALLCONV * end_cache_get)(krb5_context, krb5_cc_cursor);
+    krb5_error_code (KRB5_CALLCONV * move)(krb5_context, krb5_ccache, krb5_ccache);
+    krb5_error_code (KRB5_CALLCONV * get_default_name)(krb5_context, char **);
+    krb5_error_code (KRB5_CALLCONV * set_default)(krb5_context, krb5_ccache);
+    krb5_error_code (KRB5_CALLCONV * lastchange)(krb5_context, krb5_ccache, krb5_timestamp *);
+    krb5_error_code (KRB5_CALLCONV * set_kdc_offset)(krb5_context, krb5_ccache, krb5_deltat);
+    krb5_error_code (KRB5_CALLCONV * get_kdc_offset)(krb5_context, krb5_ccache, krb5_deltat *);
 } krb5_cc_ops;
 
 struct krb5_log_facility;
@@ -523,18 +534,18 @@ typedef struct krb5_keytab_data *krb5_keytab;
 
 struct krb5_keytab_data {
     const char *prefix;
-    krb5_error_code (*resolve)(krb5_context, const char*, krb5_keytab);
-    krb5_error_code (*get_name)(krb5_context, krb5_keytab, char*, size_t);
-    krb5_error_code (*close)(krb5_context, krb5_keytab);
-    krb5_error_code (*destroy)(krb5_context, krb5_keytab);
-    krb5_error_code (*get)(krb5_context, krb5_keytab, krb5_const_principal,
-                          krb5_kvno, krb5_enctype, krb5_keytab_entry*);
-    krb5_error_code (*start_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*);
-    krb5_error_code (*next_entry)(krb5_context, krb5_keytab,
-                                 krb5_keytab_entry*, krb5_kt_cursor*);
-    krb5_error_code (*end_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*);
-    krb5_error_code (*add)(krb5_context, krb5_keytab, krb5_keytab_entry*);
-    krb5_error_code (*remove)(krb5_context, krb5_keytab, krb5_keytab_entry*);
+    krb5_error_code (KRB5_CALLCONV * resolve)(krb5_context, const char*, krb5_keytab);
+    krb5_error_code (KRB5_CALLCONV * get_name)(krb5_context, krb5_keytab, char*, size_t);
+    krb5_error_code (KRB5_CALLCONV * close)(krb5_context, krb5_keytab);
+    krb5_error_code (KRB5_CALLCONV * destroy)(krb5_context, krb5_keytab);
+    krb5_error_code (KRB5_CALLCONV * get)(krb5_context, krb5_keytab, krb5_const_principal,
+                                         krb5_kvno, krb5_enctype, krb5_keytab_entry*);
+    krb5_error_code (KRB5_CALLCONV * start_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*);
+    krb5_error_code (KRB5_CALLCONV * next_entry)(krb5_context, krb5_keytab,
+                                                krb5_keytab_entry*, krb5_kt_cursor*);
+    krb5_error_code (KRB5_CALLCONV * end_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*);
+    krb5_error_code (KRB5_CALLCONV * add)(krb5_context, krb5_keytab, krb5_keytab_entry*);
+    krb5_error_code (KRB5_CALLCONV * remove)(krb5_context, krb5_keytab, krb5_keytab_entry*);
     void *data;
     int32_t version;
 };
@@ -606,8 +617,8 @@ typedef struct {
 
 extern const char *heimdal_version, *heimdal_long_version;
 
-typedef void (*krb5_log_log_func_t)(const char*, const char*, void*);
-typedef void (*krb5_log_close_func_t)(void*);
+typedef void (KRB5_CALLCONV * krb5_log_log_func_t)(const char*, const char*, void*);
+typedef void (KRB5_CALLCONV * krb5_log_close_func_t)(void*);
 
 typedef struct krb5_log_facility {
     char *program;
@@ -642,28 +653,28 @@ typedef struct _krb5_prompt {
     krb5_prompt_type type;
 } krb5_prompt;
 
-typedef int (*krb5_prompter_fct)(krb5_context /*context*/,
-                                void * /*data*/,
-                                const char * /*name*/,
-                                const char * /*banner*/,
-                                int /*num_prompts*/,
-                                krb5_prompt /*prompts*/[]);
-typedef krb5_error_code (*krb5_key_proc)(krb5_context /*context*/,
-                                        krb5_enctype /*type*/,
-                                        krb5_salt /*salt*/,
-                                        krb5_const_pointer /*keyseed*/,
-                                        krb5_keyblock ** /*key*/);
-typedef krb5_error_code (*krb5_decrypt_proc)(krb5_context /*context*/,
-                                            krb5_keyblock * /*key*/,
-                                            krb5_key_usage /*usage*/,
-                                            krb5_const_pointer /*decrypt_arg*/,
-                                            krb5_kdc_rep * /*dec_rep*/);
-typedef krb5_error_code (*krb5_s2k_proc)(krb5_context /*context*/,
-                                        krb5_enctype /*type*/,
-                                        krb5_const_pointer /*keyseed*/,
-                                        krb5_salt /*salt*/,
-                                        krb5_data * /*s2kparms*/,
-                                        krb5_keyblock ** /*key*/);
+typedef int (KRB5_CALLCONV * krb5_prompter_fct)(krb5_context /*context*/,
+                                               void * /*data*/,
+                                               const char * /*name*/,
+                                               const char * /*banner*/,
+                                               int /*num_prompts*/,
+                                               krb5_prompt /*prompts*/[]);
+typedef krb5_error_code (KRB5_CALLCONV * krb5_key_proc)(krb5_context /*context*/,
+                                                       krb5_enctype /*type*/,
+                                                       krb5_salt /*salt*/,
+                                                       krb5_const_pointer /*keyseed*/,
+                                                       krb5_keyblock ** /*key*/);
+typedef krb5_error_code (KRB5_CALLCONV * krb5_decrypt_proc)(krb5_context /*context*/,
+                                                           krb5_keyblock * /*key*/,
+                                                           krb5_key_usage /*usage*/,
+                                                           krb5_const_pointer /*decrypt_arg*/,
+                                                           krb5_kdc_rep * /*dec_rep*/);
+typedef krb5_error_code (KRB5_CALLCONV * krb5_s2k_proc)(krb5_context /*context*/,
+                                                       krb5_enctype /*type*/,
+                                                       krb5_const_pointer /*keyseed*/,
+                                                       krb5_salt /*salt*/,
+                                                       krb5_data * /*s2kparms*/,
+                                                       krb5_keyblock ** /*key*/);
 
 struct _krb5_get_init_creds_opt_private;
 
@@ -698,6 +709,9 @@ typedef struct _krb5_get_init_creds_opt krb5_get_init_creds_opt;
 #define KRB5_GET_INIT_CREDS_OPT_ANONYMOUS      0x0100
 #define KRB5_GET_INIT_CREDS_OPT_DISABLE_TRANSITED_CHECK        0x0200
 
+/* krb5_init_creds_step flags argument */
+#define KRB5_INIT_CREDS_STEP_FLAG_CONTINUE     0x0001
+
 typedef struct _krb5_verify_init_creds_opt {
     krb5_flags flags;
     int ap_req_nofail;
@@ -757,12 +771,9 @@ enum {
     KRB5_KRBHST_FLAGS_LARGE_MSG          = 2
 };
 
-typedef krb5_error_code (*krb5_send_to_kdc_func)(krb5_context,
-                                                void *,
-                                                krb5_krbhst_info *,
-                                                time_t,
-                                                const krb5_data *,
-                                                krb5_data *);
+typedef krb5_error_code
+(KRB5_CALLCONV * krb5_send_to_kdc_func)(krb5_context, void *, krb5_krbhst_info *, time_t,
+                                       const krb5_data *, krb5_data *);
 
 /** flags for krb5_parse_name_flags */
 enum {
@@ -784,7 +795,9 @@ typedef struct krb5_sendto_ctx_data *krb5_sendto_ctx;
 #define KRB5_SENDTO_RESTART    1
 #define KRB5_SENDTO_CONTINUE   2
 
-typedef krb5_error_code (*krb5_sendto_ctx_func)(krb5_context, krb5_sendto_ctx, void *, const krb5_data *, int *);
+typedef krb5_error_code
+(KRB5_CALLCONV * krb5_sendto_ctx_func)(krb5_context, krb5_sendto_ctx, void *,
+                                      const krb5_data *, int *);
 
 struct krb5_plugin;
 enum krb5_plugin_type {
@@ -828,7 +841,7 @@ typedef struct {
 } krb5_last_req_entry;
 
 typedef krb5_error_code
-(*krb5_gic_process_last_req)(krb5_context, krb5_last_req_entry **, void *);
+(KRB5_CALLCONV * krb5_gic_process_last_req)(krb5_context, krb5_last_req_entry **, void *);
 
 /*
  *
@@ -854,8 +867,6 @@ extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_wrfkt_ops;
 extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_javakt_ops;
 extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_mkt_ops;
 extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_akf_ops;
-extern KRB5_LIB_VARIABLE const krb5_kt_ops krb4_fkt_ops;
-extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_srvtab_fkt_ops;
 extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_any_ops;
 
 extern KRB5_LIB_VARIABLE const char *krb5_cc_type_api;
index 6acaa2c66befcf5b274bab9c0e0392d052ed2f81..2fdb76d757b0e3633f601bbd30b45f589344d718 100644 (file)
@@ -274,6 +274,7 @@ typedef struct krb5_context_data {
 #define KRB5_CTX_F_CHECK_PAC                   2
 #define KRB5_CTX_F_HOMEDIR_ACCESS              4
 #define KRB5_CTX_F_SOCKETS_INITIALIZED          8
+#define KRB5_CTX_F_RD_REQ_IGNORE               16
     struct send_to_kdc *send_to_kdc;
 #ifdef PKINIT
     hx509_context hx509ctx;
index ec0c8b738e68fd03627aa8cbb2ae97335e19c37b..d8646f0537a8faa6194547ffbc2b3d1e920c31c8 100644 (file)
@@ -481,7 +481,7 @@ static krb5_error_code
 fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
                   const char *serv_string, int port, int proto)
 {
-    char *host;
+    char *host = NULL;
     int ret;
     struct addrinfo *ai;
     struct addrinfo hints;
@@ -500,12 +500,12 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
     }
 
     if(kd->fallback_count == 0)
-       asprintf(&host, "%s.%s.", serv_string, kd->realm);
+       ret = asprintf(&host, "%s.%s.", serv_string, kd->realm);
     else
-       asprintf(&host, "%s-%d.%s.",
-                serv_string, kd->fallback_count, kd->realm);   
+       ret = asprintf(&host, "%s-%d.%s.",
+                      serv_string, kd->fallback_count, kd->realm);     
 
-    if (host == NULL)
+    if (ret < 0 || host == NULL)
        return ENOMEM;
 
     make_hints(&hints, proto);
index 55c70fc96a96bf3d4980eb129df7a8f2222a62c5..ca0756fdb9a3df65f9461a1837a93c52c515d882 100644 (file)
@@ -165,7 +165,7 @@ struct _heimdal_syslog_data{
     int priority;
 };
 
-static void
+static void KRB5_CALLCONV
 log_syslog(const char *timestr,
           const char *msg,
           void *data)
@@ -175,7 +175,7 @@ log_syslog(const char *timestr,
     syslog(s->priority, "%s", msg);
 }
 
-static void
+static void KRB5_CALLCONV
 close_syslog(void *data)
 {
     free(data);
@@ -215,7 +215,7 @@ struct file_data{
     int keep_open;
 };
 
-static void
+static void KRB5_CALLCONV
 log_file(const char *timestr,
         const char *msg,
         void *data)
@@ -241,7 +241,7 @@ log_file(const char *timestr,
     }
 }
 
-static void
+static void KRB5_CALLCONV
 close_file(void *data)
 {
     struct file_data *f = data;
@@ -428,8 +428,8 @@ krb5_vlog_msg(krb5_context context,
                krb5_format_time(context, t, buf, sizeof(buf), TRUE);
            }
            if(actual == NULL) {
-               vasprintf(&msg, fmt, ap);
-               if(msg == NULL)
+               int ret = vasprintf(&msg, fmt, ap);
+               if(ret < 0 || msg == NULL)
                    actual = fmt;
                else
                    actual = msg;
index cdafc67bae6a097972fe4306ca1a2d0219666cc2..19e6b2345ee73770c12a18964b8e25a6c280e7e6 100644 (file)
@@ -56,26 +56,27 @@ static struct krb5_mcache *mcc_head;
 
 #define MISDEAD(X)     ((X)->dead)
 
-static const char*
+static const char* KRB5_CALLCONV
 mcc_get_name(krb5_context context,
             krb5_ccache id)
 {
     return MCACHE(id)->name;
 }
 
-static krb5_mcache *
+static krb5_mcache * KRB5_CALLCONV
 mcc_alloc(const char *name)
 {
     krb5_mcache *m, *m_c;
+    int ret = 0;
 
     ALLOC(m, 1);
     if(m == NULL)
        return NULL;
     if(name == NULL)
-       asprintf(&m->name, "%p", m);
+       ret = asprintf(&m->name, "%p", m);
     else
        m->name = strdup(name);
-    if(m->name == NULL) {
+    if(ret < 0 || m->name == NULL) {
        free(m);
        return NULL;
     }
@@ -103,7 +104,7 @@ mcc_alloc(const char *name)
     return m;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
 {
     krb5_mcache *m;
@@ -135,7 +136,7 @@ mcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
 }
 
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_gen_new(krb5_context context, krb5_ccache *id)
 {
     krb5_mcache *m;
@@ -154,7 +155,7 @@ mcc_gen_new(krb5_context context, krb5_ccache *id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_initialize(krb5_context context,
               krb5_ccache id,
               krb5_principal primary_principal)
@@ -180,7 +181,7 @@ mcc_close_internal(krb5_mcache *m)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_close(krb5_context context,
          krb5_ccache id)
 {
@@ -189,7 +190,7 @@ mcc_close(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_destroy(krb5_context context,
            krb5_ccache id)
 {
@@ -230,7 +231,7 @@ mcc_destroy(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_store_cred(krb5_context context,
               krb5_ccache id,
               krb5_creds *creds)
@@ -261,7 +262,7 @@ mcc_store_cred(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_get_principal(krb5_context context,
                  krb5_ccache id,
                  krb5_principal *principal)
@@ -275,7 +276,7 @@ mcc_get_principal(krb5_context context,
                                principal);
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_get_first (krb5_context context,
               krb5_ccache id,
               krb5_cc_cursor *cursor)
@@ -289,7 +290,7 @@ mcc_get_first (krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_get_next (krb5_context context,
              krb5_ccache id,
              krb5_cc_cursor *cursor,
@@ -311,7 +312,7 @@ mcc_get_next (krb5_context context,
        return KRB5_CC_END;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_end_get (krb5_context context,
             krb5_ccache id,
             krb5_cc_cursor *cursor)
@@ -319,7 +320,7 @@ mcc_end_get (krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_remove_cred(krb5_context context,
                 krb5_ccache id,
                 krb5_flags which,
@@ -339,7 +340,7 @@ mcc_remove_cred(krb5_context context,
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_set_flags(krb5_context context,
              krb5_ccache id,
              krb5_flags flags)
@@ -351,7 +352,7 @@ struct mcache_iter {
     krb5_mcache *cache;
 };
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
 {
     struct mcache_iter *iter;
@@ -373,7 +374,7 @@ mcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
 {
     struct mcache_iter *iter = cursor;
@@ -400,7 +401,7 @@ mcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
 {
     struct mcache_iter *iter = cursor;
@@ -412,7 +413,7 @@ mcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
 {
     krb5_mcache *mfrom = MCACHE(from), *mto = MCACHE(to);
@@ -447,7 +448,7 @@ mcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_default_name(krb5_context context, char **str)
 {
     *str = strdup("MEMORY:");
@@ -459,14 +460,14 @@ mcc_default_name(krb5_context context, char **str)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_lastchange(krb5_context context, krb5_ccache id, krb5_timestamp *mtime)
 {
     *mtime = MCACHE(id)->mtime;
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_set_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat kdc_offset)
 {
     krb5_mcache *m = MCACHE(id);
@@ -474,7 +475,7 @@ mcc_set_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat kdc_offset)
     return 0;
 }
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 mcc_get_kdc_offset(krb5_context context, krb5_ccache id, krb5_deltat *kdc_offset)
 {
     krb5_mcache *m = MCACHE(id);
index 0ff3d7f3c615f8155e7670f1b33fe15ff3217478..7ed91b0768ca270aaa7237fbf738193d29717158 100644 (file)
@@ -378,6 +378,12 @@ krb5_c_prf(krb5_context context,
     return ret;
 }
 
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_c_random_make_octets(krb5_context context, krb5_data * data)
+{
+    return krb5_generate_random_keyblock(context, data->length, data->data);
+}
+
 /**
  * MIT compat glue
  *
@@ -392,4 +398,38 @@ krb5_cc_copy_creds(krb5_context context,
     return krb5_cc_copy_cache(context, from, to);
 }
 
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_auth_con_getsendsubkey(krb5_context context, krb5_auth_context auth_context,
+                            krb5_keyblock **keyblock)
+{
+    return krb5_auth_con_getlocalsubkey(context, auth_context, keyblock);
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_auth_con_getrecvsubkey(krb5_context context, krb5_auth_context auth_context,
+                            krb5_keyblock **keyblock)
+{
+    return krb5_auth_con_getremotesubkey(context, auth_context, keyblock);
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_auth_con_setsendsubkey(krb5_context context, krb5_auth_context auth_context,
+                            krb5_keyblock *keyblock)
+{
+    return krb5_auth_con_setlocalsubkey(context, auth_context, keyblock);
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_auth_con_setrecvsubkey(krb5_context context, krb5_auth_context auth_context,
+                            krb5_keyblock *keyblock)
+{
+    return krb5_auth_con_setremotesubkey(context, auth_context, keyblock);
+}
+
+KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
+krb5_free_default_realm(krb5_context context, krb5_realm realm)
+{
+    return krb5_xfree(realm);
+}
+
 #endif /* HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/pcache.c b/source4/heimdal/lib/krb5/pcache.c
new file mode 100644 (file)
index 0000000..e7f7a61
--- /dev/null
@@ -0,0 +1,66 @@
+/***********************************************************************
+ * Copyright (c) 2010, Secure Endpoints Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **********************************************************************/
+
+#include "krb5_locl.h"
+#include "ccache_plugin.h"
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+#include <assert.h>
+
+krb5_error_code
+_krb5_load_ccache_plugins(krb5_context context)
+{
+    struct krb5_plugin * plist = NULL;
+    struct krb5_plugin *p;
+    krb5_error_code code;
+
+    code = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, KRB5_PLUGIN_CCACHE,
+                             &plist);
+    if (code)
+        return code;
+
+    for (p = plist; p != NULL; p = _krb5_plugin_get_next(p)) {
+        krb5_cc_ops * ccops;
+        krb5_error_code c_load;
+
+        ccops = _krb5_plugin_get_symbol(p);
+        if (ccops != NULL && ccops->version == KRB5_CC_OPS_VERSION) {
+            c_load = krb5_cc_register(context, ccops, FALSE);
+            if (c_load != 0)
+                code = c_load;
+        }
+    }
+
+    _krb5_plugin_free(plist);
+
+    return code;
+}
index 6711c7702f2216e98665fbb925caafc15f1023f2..92c1200f0645da99debf64d9d682bd6c09b99cda 100644 (file)
@@ -1416,10 +1416,7 @@ pk_rd_pa_reply_dh(krb5_context context,
        }
 
 
-       dh_gen_keylen = DH_size(ctx->u.dh);
-       size = BN_num_bytes(ctx->u.dh->p);
-       if (size < dh_gen_keylen)
-           size = dh_gen_keylen;
+       size = DH_size(ctx->u.dh);
 
        dh_gen_key = malloc(size);
        if (dh_gen_key == NULL) {
@@ -1427,10 +1424,8 @@ pk_rd_pa_reply_dh(krb5_context context,
            krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
            goto out;
        }
-       memset(dh_gen_key, 0, size - dh_gen_keylen);
        
-       dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),
-                                      kdc_dh_pubkey, ctx->u.dh);
+       dh_gen_keylen = DH_compute_key(dh_gen_key, kdc_dh_pubkey, ctx->u.dh);
        if (dh_gen_keylen == -1) {
            ret = KRB5KRB_ERR_GENERIC;
            dh_gen_keylen = 0;
@@ -1438,6 +1433,12 @@ pk_rd_pa_reply_dh(krb5_context context,
                                   N_("PKINIT: Can't compute Diffie-Hellman key", ""));
            goto out;
        }
+       if (dh_gen_keylen < size) {
+           size -= dh_gen_keylen;
+           memmove(dh_gen_key + size, dh_gen_key, dh_gen_keylen);
+           memset(dh_gen_key, 0, size);
+       }
+
     } else {
 #ifdef HAVE_OPENSSL
        const EC_GROUP *group;
index aa71e29b39b5858d6193b359c01c28547c809995..e19ba4a27cc3baedea591b7fcf48b9212fbdb29a 100644 (file)
@@ -201,8 +201,19 @@ load_plugins(krb5_context context)
        dirs = rk_UNCONST(sysplugin_dirs);
 
     for (di = dirs; *di != NULL; di++) {
+#ifdef KRB5_USE_PATH_TOKENS
+       {
+           char * dir = NULL;
 
+           if (_krb5_expand_path_tokens(context, *di, &dir))
+               continue;
+           d = opendir(dir);
+
+           free(dir);
+       }
+#else
        d = opendir(*di);
+#endif
        if (d == NULL)
            continue;
        rk_cloexec_dir(d);
@@ -215,17 +226,18 @@ load_plugins(krb5_context context)
                continue;
 
            path = NULL;
+           ret = 0;
 #ifdef __APPLE__
            { /* support loading bundles on MacOS */
                size_t len = strlen(n);
                if (len > 7 && strcmp(&n[len - 7],  ".bundle") == 0)
-                   asprintf(&path, "%s/%s/Contents/MacOS/%.*s", *di, n, (int)(len - 7), n);
+                   ret = asprintf(&path, "%s/%s/Contents/MacOS/%.*s", *di, n, (int)(len - 7), n);
            }
 #endif
-           if (path == NULL)
-               asprintf(&path, "%s/%s", *di, n);
+           if (ret < 0 || path == NULL)
+               ret = asprintf(&path, "%s/%s", *di, n);
 
-           if (path == NULL) {
+           if (ret < 0 || path == NULL) {
                ret = ENOMEM;
                krb5_set_error_message(context, ret, "malloc: out of memory");
                return ret;
index 875fd99c40340789268de3b3e5310882c173dcf2..1bf748c51231d698f378fbef02ec435c34b3cc44 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5_locl.h"
 
-KRB5_LIB_FUNCTION int
+KRB5_LIB_FUNCTION int KRB5_CALLCONV
 krb5_prompter_posix (krb5_context context,
                     void *data,
                     const char *name,
index 6b2ffbdaac48ac132a6d851954f41733d1c5fbdc..8ce6570de281291c2d355e1ef309b5c37c6688b5 100644 (file)
@@ -926,7 +926,7 @@ krb5_rd_req_ctx(krb5_context context,
                                  &o->keyblock);
        if (ret) {
            /* If caller specified a server, fail. */
-           if (service == NULL)
+           if (service == NULL && (context->flags & KRB5_CTX_F_RD_REQ_IGNORE) == 0)
                goto out;
            /* Otherwise, fall back to iterating over the keytab. This
             * have serious performace issues for larger keytab.
index f4eb9032d76a404035c1ebb7e76f5003ea98ef03..375a4aaba6b27ac1130cf5629295de3d7bcd8efb 100644 (file)
@@ -308,12 +308,12 @@ krb5_get_server_rcache(krb5_context context,
     }
     strvisx(tmp, piece->data, piece->length, VIS_WHITE | VIS_OCTAL);
 #ifdef HAVE_GETEUID
-    asprintf(&name, "FILE:rc_%s_%u", tmp, (unsigned)geteuid());
+    ret = asprintf(&name, "FILE:rc_%s_%u", tmp, (unsigned)geteuid());
 #else
-    asprintf(&name, "FILE:rc_%s", tmp);
+    ret = asprintf(&name, "FILE:rc_%s", tmp);
 #endif
     free(tmp);
-    if(name == NULL) {
+    if(ret < 0 || name == NULL) {
        krb5_set_error_message(context, ENOMEM,
                               N_("malloc: out of memory", ""));
        return ENOMEM;
index 9ff52fa545fa57918ed0ae53203757450975f2a4..2ae8153c8d7b1dd78c1997409d96488b87f4cde7 100644 (file)
@@ -183,16 +183,16 @@ send_and_recv_http(krb5_socket_t fd,
                   const krb5_data *req,
                   krb5_data *rep)
 {
-    char *request;
+    char *request = NULL;
     char *str;
     int ret;
     int len = base64_encode(req->data, req->length, &str);
 
     if(len < 0)
        return -1;
-    asprintf(&request, "GET %s%s HTTP/1.0\r\n\r\n", prefix, str);
+    ret = asprintf(&request, "GET %s%s HTTP/1.0\r\n\r\n", prefix, str);
     free(str);
-    if (request == NULL)
+    if (ret < 0 || request == NULL)
        return -1;
     ret = net_write (fd, request, strlen(request));
     free (request);
@@ -261,7 +261,7 @@ send_via_proxy (krb5_context context,
 {
     char *proxy2 = strdup(context->http_proxy);
     char *proxy  = proxy2;
-    char *prefix;
+    char *prefix = NULL;
     char *colon;
     struct addrinfo hints;
     struct addrinfo *ai, *a;
@@ -304,8 +304,8 @@ send_via_proxy (krb5_context context,
     }
     freeaddrinfo (ai);
 
-    asprintf(&prefix, "http://%s/", hi->hostname);
-    if(prefix == NULL) {
+    ret = asprintf(&prefix, "http://%s/", hi->hostname);
+    if(ret < 0 || prefix == NULL) {
        close(s);
        return 1;
     }
@@ -648,7 +648,7 @@ krb5_sendto_context(krb5_context context,
     return ret;
 }
 
-krb5_error_code
+krb5_error_code KRB5_CALLCONV
 _krb5_kdc_retry(krb5_context context, krb5_sendto_ctx ctx, void *data,
                const krb5_data *reply, int *action)
 {
index e7d4d9532d5c3642c3c0889e3bc14a1d1703a997..45c97284bfb88be4c7d0ece2fa2cb90782e5cff7 100644 (file)
@@ -602,7 +602,7 @@ noreferral:
 }
 
 
-static krb5_error_code
+static krb5_error_code KRB5_CALLCONV
 decrypt_tkt (krb5_context context,
             krb5_keyblock *key,
             krb5_key_usage usage,
index 01cf323d37bfe7ef816c20aa57d88ad05ad01630..d47a1288ed1012bad197924c5c17c49938f424a1 100644 (file)
@@ -120,7 +120,7 @@ get_krb4_cc_name(const char *tkfile, char **cc)
        }
 #ifdef HAVE_GETUID
        if(*cc == NULL)
-           if (asprintf(cc, "%s%u", TKT_ROOT, (unsigned)getuid()) < 0)
+           if (asprintf(cc, "%s%u", TKT_ROOT, (unsigned)getuid()) < 0 || *cc == NULL)
                return errno;
 #elif defined(KRB5_USE_PATH_TOKENS)
        if(*cc == NULL)
index a4c633936fb6ca896192ed6d818520da23b4e9eb..63994dfca71452631f9450e706f0e6182608db3c 100644 (file)
@@ -46,6 +46,7 @@ _warnerr(krb5_context context, int do_errtext,
     const char *args[2], **arg;
     char *msg = NULL;
     const char *err_str = NULL;
+    krb5_error_code ret;
 
     args[0] = args[1] = NULL;
     arg = args;
@@ -53,8 +54,8 @@ _warnerr(krb5_context context, int do_errtext,
        strlcat(xfmt, "%s", sizeof(xfmt));
        if(do_errtext)
            strlcat(xfmt, ": ", sizeof(xfmt));
-       vasprintf(&msg, fmt, ap);
-       if(msg == NULL)
+       ret = vasprintf(&msg, fmt, ap);
+       if(ret < 0 || msg == NULL)
            return ENOMEM;
        *arg++ = msg;
     }
index 71f96bfce299752f2a7575fde3c047fccd4f2137..8390d79acc3c4e47bf408619e08a0b3189df93c2 100644 (file)
@@ -222,8 +222,6 @@ ret_string(krb5_storage *sp, int ucs2, struct sec_buffer *desc, char **s)
     ret = 0;
 out:
     return ret;
-
-    return 0;
 }
 
 static krb5_error_code
@@ -485,6 +483,10 @@ heim_ntlm_encode_type1(const struct ntlm_type1 *type1, struct ntlm_buf *data)
        domain.offset = base;
        domain.length = len_string(0, type1->domain);
        domain.allocated = domain.length;
+    } else {
+       domain.offset = 0;
+       domain.length = 0;
+       domain.allocated = 0;
     }
     if (type1->hostname) {
        hostname.offset = domain.allocated + domain.offset;
index 4c06bd2d1f6d25b17315fc2cbba19a86e2cdb65f..394e9841c78dd2a94f3967480f0c1923c5239039 100644 (file)
@@ -93,7 +93,7 @@ base64_encode(const void *data, int size, char **str)
     }
     *p = 0;
     *str = s;
-    return strlen(s);
+    return (int) strlen(s);
 }
 
 #define DECODE_ERROR 0xffffffff
index d182f0019eaa7b2eca6d415aa99ef1336ce08979..e7dc74b7bc64b2efd720e1430f77669febe17336 100644 (file)
@@ -223,7 +223,7 @@ arg_printusage_i18n (struct getargs *args,
                     const char *usage,
                     const char *progname,
                     const char *extra_string,
-                    char *(i18n)(const char *))
+                    char *(*i18n)(const char *))
 {
     size_t i, max_len = 0;
     char buf[128];
@@ -475,9 +475,6 @@ arg_match_long(struct getargs *args, size_t num_args,
        abort ();
        UNREACHABLE(return 0);
     }
-
-    /* not reached */
-    return ARG_ERR_NO_MATCH;
 }
 
 static int
index 79573a0ea4153ff54a916758a38b6ee7a44b36b7..1065c7c661af5c94d7f29d157f2854c068b14069 100644 (file)
@@ -104,7 +104,7 @@ arg_printusage_i18n (struct getargs *args,
                     const char *usage,
                     const char *progname,
                     const char *extra_string,
-                    char *(i18n)(const char *));
+                    char *(*i18n)(const char *));
 
 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
 free_getarg_strings (getarg_strings *);
index 0c72b27fc6c5e73895ce1bbd29a574ff3522ecc5..b3c327cc3e58add57faf26060e2cfb7170ca4fd1 100644 (file)
@@ -83,6 +83,7 @@ inet_ntop_v6 (const void *src, char *dst, size_t size)
     const struct in6_addr *addr = (struct in6_addr *)src;
     const u_char *ptr = addr->s6_addr;
     const char *orig_dst = dst;
+    int compressed = 0;
 
     if (size < INET6_ADDRSTRLEN) {
        errno = ENOSPC;
@@ -91,6 +92,26 @@ inet_ntop_v6 (const void *src, char *dst, size_t size)
     for (i = 0; i < 8; ++i) {
        int non_zerop = 0;
 
+        if (compressed == 0 &&
+            ptr[0] == 0 && ptr[1] == 0 &&
+            i <= 5 &&
+            ptr[2] == 0 && ptr[3] == 0 &&
+            ptr[4] == 0 && ptr[5] == 0) {
+
+            compressed = 1;
+
+            if (i == 0)
+                *dst++ = ':';
+            *dst++ = ':';
+
+            for (ptr += 6, i += 3;
+                 i < 8 && ptr[0] == 0 && ptr[1] == 0;
+                 ++i, ptr += 2);
+
+            if (i >= 8)
+                break;
+        }
+
        if (non_zerop || (ptr[0] >> 4)) {
            *dst++ = xdigits[ptr[0] >> 4];
            non_zerop = 1;
index 3db1f49f226e2a278de9fef869307b82b3d2fd96..e44fb1925ad97813bb7ef7b980ca14e0a08760a5 100644 (file)
 #ifdef HAVE_WINSOCK
 
 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
-inet_pton(int af, const char *src, void *dst)
+inet_pton(int af, const char *csrc, void *dst)
 {
+    char * src;
+
+    if (csrc == NULL || (src = strdup(csrc)) == NULL) {
+       _set_errno( ENOMEM );
+       return 0;
+    }
+
     switch (af) {
     case AF_INET:
        {
@@ -49,6 +56,8 @@ inet_pton(int af, const char *src, void *dst)
 
            si4.sin_family = AF_INET;
            r = WSAStringToAddress(src, AF_INET, NULL, (LPSOCKADDR) &si4, &s);
+           free(src);
+           src = NULL;
 
            if (r == 0) {
                memcpy(dst, &si4.sin_addr, sizeof(si4.sin_addr));
@@ -65,6 +74,8 @@ inet_pton(int af, const char *src, void *dst)
 
            si6.sin6_family = AF_INET6;
            r = WSAStringToAddress(src, AF_INET6, NULL, (LPSOCKADDR) &si6, &s);
+           free(src);
+           src = NULL;
 
            if (r == 0) {
                memcpy(dst, &si6.sin6_addr, sizeof(si6.sin6_addr));
index b57dda3ddae6dd03f325b5a2a5726df92e59f047..df1ac53def10c3dfc64212e5be988d5bb8dd3fe5 100644 (file)
@@ -73,8 +73,28 @@ net_read(rk_socket_t sock, void *buf, size_t nbytes)
     ssize_t count;
     size_t rem = nbytes;
 
+#ifdef SOCKET_IS_NOT_AN_FD
+    int use_read = 0;
+#endif
+
     while (rem > 0) {
+#ifdef SOCKET_IS_NOT_AN_FD
+       if (use_read)
+           count = _read (sock, cbuf, rem);
+       else
+           count = recv (sock, cbuf, rem, 0);
+
+       if (use_read == 0 &&
+           rk_IS_SOCKET_ERROR(count) &&
+            (rk_SOCK_ERRNO == WSANOTINITIALISED ||
+             rk_SOCK_ERRNO == WSAENOTSOCK)) {
+           use_read = 1;
+
+           count = _read (sock, cbuf, rem);
+       }
+#else
        count = recv (sock, cbuf, rem, 0);
+#endif
        if (count < 0) {
 
            /* With WinSock, the error EINTR (WSAEINTR), is used to
index 94c9df1c38ab6a7b3ede713b62fc67e3c416a5a9..e1cfa99074ee29365391feafc3b52bcdb9bf0029 100644 (file)
@@ -70,9 +70,28 @@ net_write(rk_socket_t sock, const void *buf, size_t nbytes)
     const char *cbuf = (const char *)buf;
     ssize_t count;
     size_t rem = nbytes;
+#ifdef SOCKET_IS_NOT_AN_FD
+    int use_write = 0;
+#endif
 
     while (rem > 0) {
+#ifdef SOCKET_IS_NOT_AN_FD
+       if (use_write)
+           count = _write (sock, cbuf, rem);
+       else
+           count = send (sock, cbuf, rem, 0);
+
+       if (use_write == 0 &&
+           rk_IS_SOCKET_ERROR(count) &&
+           (rk_SOCK_ERRNO == WSANOTINITIALISED ||
+             rk_SOCK_ERRNO == WSAENOTSOCK)) {
+           use_write = 1;
+
+           count = _write (sock, cbuf, rem);
+       }
+#else
        count = send (sock, cbuf, rem, 0);
+#endif
        if (count < 0) {
            if (errno == EINTR)
                continue;
index e112274a6821cb24b74003be8071f5df5e4a71c3..97edda471b58c860e08c0634301907bb2968de20 100644 (file)
@@ -98,7 +98,7 @@ rk_dns_type_to_string(int type)
     return NULL;
 }
 
-#if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)
+#if ((defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)) || defined(HAVE_WINDNS)
 
 static void
 dns_free_rr(struct rk_resource_record *rr)
@@ -124,6 +124,8 @@ rk_dns_free_data(struct rk_dns_reply *r)
     free (r);
 }
 
+#ifndef HAVE_WINDNS
+
 static int
 parse_record(const unsigned char *data, const unsigned char *end_data,
             const unsigned char **pp, struct rk_resource_record **ret_rr)
@@ -605,6 +607,8 @@ rk_dns_lookup(const char *domain, const char *type_name)
     return dns_lookup_int(domain, rk_ns_c_in, type);
 }
 
+#endif /* !HAVE_WINDNS */
+
 static int
 compare_srv(const void *a, const void *b)
 {
@@ -708,6 +712,218 @@ rk_dns_srv_order(struct rk_dns_reply *r)
     return;
 }
 
+#ifdef HAVE_WINDNS
+
+#include <WinDNS.h>
+
+static struct rk_resource_record *
+parse_dns_record(PDNS_RECORD pRec)
+{
+    struct rk_resource_record * rr;
+
+    if (pRec == NULL)
+       return NULL;
+
+    rr = calloc(1, sizeof(*rr));
+
+    rr->domain = strdup(pRec->pName);
+    rr->type = pRec->wType;
+    rr->class = 0;
+    rr->ttl = pRec->dwTtl;
+    rr->size = 0;
+
+    switch (rr->type) {
+    case rk_ns_t_ns:
+    case rk_ns_t_cname:
+    case rk_ns_t_ptr:
+       rr->u.txt = strdup(pRec->Data.NS.pNameHost);
+       if(rr->u.txt == NULL) {
+           dns_free_rr(rr);
+           return NULL;
+       }
+       break;
+
+    case rk_ns_t_mx:
+    case rk_ns_t_afsdb:{
+       size_t hostlen = strnlen(pRec->Data.MX.pNameExchange, DNS_MAX_NAME_LENGTH);
+
+       rr->u.mx = (struct mx_record *)malloc(sizeof(struct mx_record) +
+                                             hostlen);
+       if (rr->u.mx == NULL) {
+           dns_free_rr(rr);
+           return NULL;
+       }
+
+       strcpy_s(rr->u.mx->domain, hostlen + 1, pRec->Data.MX.pNameExchange);
+       rr->u.mx->preference = pRec->Data.MX.wPreference;
+       break;
+    }
+
+    case rk_ns_t_srv:{
+       size_t hostlen = strnlen(pRec->Data.SRV.pNameTarget, DNS_MAX_NAME_LENGTH);
+
+       rr->u.srv =
+           (struct srv_record*)malloc(sizeof(struct srv_record) +
+                                      hostlen);
+       if(rr->u.srv == NULL) {
+           dns_free_rr(rr);
+           return NULL;
+       }
+
+       rr->u.srv->priority = pRec->Data.SRV.wPriority;
+       rr->u.srv->weight = pRec->Data.SRV.wWeight;
+       rr->u.srv->port = pRec->Data.SRV.wPort;
+       strcpy_s(rr->u.srv->target, hostlen + 1, pRec->Data.SRV.pNameTarget);
+
+       break;
+    }
+
+    case rk_ns_t_txt:{
+       size_t len;
+
+       if (pRec->Data.TXT.dwStringCount == 0) {
+           rr->u.txt = strdup("");
+           break;
+       }
+
+       len = strnlen(pRec->Data.TXT.pStringArray[0], DNS_MAX_TEXT_STRING_LENGTH);
+
+       rr->u.txt = (char *)malloc(len + 1);
+       strcpy_s(rr->u.txt, len + 1, pRec->Data.TXT.pStringArray[0]);
+
+       break;
+    }
+
+    case rk_ns_t_key : {
+       size_t key_len;
+
+       if (pRec->wDataLength < 4) {
+           dns_free_rr(rr);
+           return NULL;
+       }
+
+       key_len = pRec->wDataLength - 4;
+       rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1);
+       if (rr->u.key == NULL) {
+           dns_free_rr(rr);
+           return NULL;
+       }
+
+       rr->u.key->flags     = pRec->Data.KEY.wFlags;
+       rr->u.key->protocol  = pRec->Data.KEY.chProtocol;
+       rr->u.key->algorithm = pRec->Data.KEY.chAlgorithm;
+       rr->u.key->key_len   = key_len;
+       memcpy_s (rr->u.key->key_data, key_len,
+                 pRec->Data.KEY.Key, key_len);
+       break;
+    }
+
+    case rk_ns_t_sig : {
+       size_t sig_len, hostlen;
+
+       if(pRec->wDataLength <= 18) {
+           dns_free_rr(rr);
+           return NULL;
+       }
+
+       sig_len = pRec->wDataLength;
+
+       hostlen = strnlen(pRec->Data.SIG.pNameSigner, DNS_MAX_NAME_LENGTH);
+
+       rr->u.sig = malloc(sizeof(*rr->u.sig)
+                             + hostlen + sig_len);
+       if (rr->u.sig == NULL) {
+           dns_free_rr(rr);
+           return NULL;
+       }
+       rr->u.sig->type           = pRec->Data.SIG.wTypeCovered;
+       rr->u.sig->algorithm      = pRec->Data.SIG.chAlgorithm;
+       rr->u.sig->labels         = pRec->Data.SIG.chLabelCount;
+       rr->u.sig->orig_ttl       = pRec->Data.SIG.dwOriginalTtl;
+       rr->u.sig->sig_expiration = pRec->Data.SIG.dwExpiration;
+       rr->u.sig->sig_inception  = pRec->Data.SIG.dwTimeSigned;
+       rr->u.sig->key_tag        = pRec->Data.SIG.wKeyTag;
+       rr->u.sig->sig_len        = sig_len;
+       memcpy_s (rr->u.sig->sig_data, sig_len,
+                 pRec->Data.SIG.Signature, sig_len);
+       rr->u.sig->signer         = &rr->u.sig->sig_data[sig_len];
+       strcpy_s(rr->u.sig->signer, hostlen + 1, pRec->Data.SIG.pNameSigner);
+       break;
+    }
+
+#ifdef DNS_TYPE_DS
+    case rk_ns_t_ds: {
+       rr->u.ds = malloc (sizeof(*rr->u.ds) + pRec->Data.DS.wDigestLength - 1);
+       if (rr->u.ds == NULL) {
+           dns_free_rr(rr);
+           return NULL;
+       }
+
+       rr->u.ds->key_tag     = pRec->Data.DS.wKeyTag;
+       rr->u.ds->algorithm   = pRec->Data.DS.chAlgorithm;
+       rr->u.ds->digest_type = pRec->Data.DS.chDigestType;
+       rr->u.ds->digest_len  = pRec->Data.DS.wDigestLength;
+       memcpy_s (rr->u.ds->digest_data, pRec->Data.DS.wDigestLength,
+                 pRec->Data.DS.Digest, pRec->Data.DS.wDigestLength);
+       break;
+    }
+#endif
+
+    default:
+       dns_free_rr(rr);
+       return NULL;
+    }
+
+    rr->next = parse_dns_record(pRec->pNext);
+    return rr;
+}
+
+ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL
+rk_dns_lookup(const char *domain, const char *type_name)
+{
+    DNS_STATUS status;
+    int type;
+    PDNS_RECORD pRec = NULL;
+    struct rk_dns_reply * r = NULL;
+
+    __try {
+
+       type = rk_dns_string_to_type(type_name);
+       if(type == -1) {
+           if(_resolve_debug)
+               fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n",
+                       type_name);
+           return NULL;
+       }
+
+       status = DnsQuery_UTF8(domain, type, DNS_QUERY_STANDARD, NULL,
+                              &pRec, NULL);
+       if (status != ERROR_SUCCESS)
+           return NULL;
+
+       r = calloc(1, sizeof(*r));
+       r->q.domain = strdup(domain);
+       r->q.type = type;
+       r->q.class = 0;
+
+       r->head = parse_dns_record(pRec);
+
+       if (r->head == NULL) {
+           rk_dns_free_data(r);
+           return NULL;
+       } else {
+           return r;
+       }
+
+    } __finally {
+
+       if (pRec)
+           DnsRecordListFree(pRec, DnsFreeRecordList);
+
+    }
+}
+#endif /* HAVE_WINDNS */
+
 #else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
 
 ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL
index adec8084b8763ebc5614818ae1c5022b7b26d65b..fc1e97fc63b5c54b66bdb6cf943696a7998d1603 100644 (file)
@@ -153,7 +153,7 @@ struct rk_sig_record {
     unsigned sig_inception;
     unsigned key_tag;
     char     *signer;
-    unsigned sig_len;
+    size_t   sig_len;
     char     sig_data[1];      /* also includes signer */
 };
 
@@ -176,7 +176,7 @@ struct rk_ds_record {
     unsigned key_tag;
     unsigned algorithm;
     unsigned digest_type;
-    unsigned digest_len;
+    size_t digest_len;
     u_char digest_data[1];
 };
 
index 76b083c7973fcf98d9289e6d7863c517e7c09a0d..d6e9024bd08d16e1206d5f5eb2b54f083dfd267f 100644 (file)
@@ -68,7 +68,8 @@ typedef SOCKET rk_socket_t;
 #define rk_IS_BAD_SOCKET(s) ((s) == INVALID_SOCKET)
 #define rk_IS_SOCKET_ERROR(rv) ((rv) == SOCKET_ERROR)
 #define rk_SOCK_ERRNO WSAGetLastError()
-#define rk_SOCK_IOCTL(s,c,a) ioctlsocket((s),(c),(a))
+
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL rk_SOCK_IOCTL(SOCKET s, long cmd, int * argp);
 
 #define ETIMEDOUT               WSAETIMEDOUT
 #define EWOULDBLOCK             WSAEWOULDBLOCK
@@ -124,6 +125,32 @@ typedef uint64_t           u_int64_t;
 #define UNREACHABLE(x) x
 #define UNUSED_ARGUMENT(x) ((void) x)
 
+#define RETSIGTYPE void
+
+#define VOID_RETSIGTYPE 1
+
+#ifdef VOID_RETSIGTYPE
+#define SIGRETURN(x) return
+#else
+#define SIGRETURN(x) return (RETSIGTYPE)(x)
+#endif
+
+#ifndef CPP_ONLY
+
+typedef int pid_t;
+
+typedef unsigned int gid_t;
+
+typedef unsigned int uid_t;
+
+typedef unsigned short mode_t;
+
+#endif
+
+#ifndef __cplusplus
+#define inline __inline
+#endif
+
 #else
 
 #define UNREACHABLE(x)
@@ -315,6 +342,32 @@ rk_vsnprintf (char *str, size_t sz, const char *format, va_list args);
 
 #endif  /* _MSC_VER */
 
+#ifdef HAVE_WINSOCK
+
+/* While we are at it, define WinSock specific scatter gather socket
+   I/O. */
+
+#define iovec    _WSABUF
+#define iov_base buf
+#define iov_len  len
+
+struct msghdr {
+    void           *msg_name;
+    socklen_t       msg_namelen;
+    struct iovec   *msg_iov;
+    size_t          msg_iovlen;
+    void           *msg_control;
+    socklen_t       msg_controllen;
+    int             msg_flags;
+};
+
+#define sendmsg sendmsg_w32
+
+ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL
+sendmsg_w32(rk_socket_t s, const struct msghdr * msg, int flags);
+
+#endif /* HAVE_WINSOCK */
+
 #ifndef HAVE_PUTENV
 #define putenv rk_putenv
 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL putenv(const char *);
@@ -563,6 +616,12 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL initgroups(const char *, gid_t);
 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL fchown(int, uid_t, gid_t);
 #endif
 
+#ifdef RENAME_DOES_NOT_UNLINK
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL rk_rename(const char *, const char *);
+#else
+#define rk_rename(__rk_rn_from,__rk_rn_to) rename(__rk_rn_from,__rk_rn_to)
+#endif
+
 #if !defined(HAVE_DAEMON) || defined(NEED_DAEMON_PROTO)
 #ifndef HAVE_DAEMON
 #define daemon rk_daemon
@@ -824,32 +883,6 @@ ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL
 gai_strerror(int);
 #endif
 
-#ifdef HAVE_WINSOCK
-
-/* While we are at it, define WinSock specific scatter gather socket
-   I/O. */
-
-#define iovec    _WSABUF
-#define iov_base buf
-#define iov_len  len
-
-struct msghdr {
-    void           *msg_name;
-    socklen_t       msg_namelen;
-    struct iovec   *msg_iov;
-    size_t          msg_iovlen;
-    void           *msg_control;
-    socklen_t       msg_controllen;
-    int             msg_flags;
-};
-
-#define sendmsg sendmsg_w32
-
-ROKEN_LIB_FUNCTION ssize_t ROKEN_LIB_CALL
-sendmsg_w32(rk_socket_t s, const struct msghdr * msg, int flags);
-
-#endif
-
 #ifdef NO_SLEEP
 
 ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL
@@ -1039,7 +1072,7 @@ void
 rk_qsort(void *, size_t, size_t, int (*)(const void *, const void *));
 #endif
 
-#if defined(__linux__) && SOCK_CLOEXEC && !defined(SOCKET_WRAPPER_REPLACE) 
+#if defined(__linux__) && defined(SOCK_CLOEXEC) && !defined(SOCKET_WRAPPER_REPLACE) 
 #undef socket
 #define socket(_fam,_type,_prot) rk_socket(_fam,_type,_prot)
 int ROKEN_LIB_FUNCTION rk_socket(int, int, int);
index c99596c536f07237156db7cbf5936445c540b4a5..1d6c8ffe8af10de876058451a42741853f5072e5 100644 (file)
@@ -66,11 +66,13 @@ setup_int(const char *proxy_host, short proxy_port,
     memset(&dns_addr, 0, sizeof(dns_addr));
     if(dns_req)
        free(dns_req);
+    dns_req = NULL;
     if(proxy_host) {
        if(make_address(proxy_host, &dns_addr.sin_addr) != 0)
            return -1;
        dns_addr.sin_port = htons(proxy_port);
-       asprintf(&dns_req, "http://%s:%d%s", dns_host, dns_port, dns_path);
+       if (asprintf(&dns_req, "http://%s:%d%s", dns_host, dns_port, dns_path) < 0)
+           return -1;
     } else {
        if(make_address(dns_host, &dns_addr.sin_addr) != 0)
            return -1;
@@ -135,7 +137,7 @@ roken_gethostby(const char *hostname)
 {
     int s;
     struct sockaddr_in addr;
-    char *request;
+    char *request = NULL;
     char buf[1024];
     int offset = 0;
     int n;
@@ -144,7 +146,8 @@ roken_gethostby(const char *hostname)
     if(dns_addr.sin_family == 0)
        return NULL; /* no configured host */
     addr = dns_addr;
-    asprintf(&request, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req, hostname);
+    if (asprintf(&request, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req, hostname) < 0)
+       return NULL;
     if(request == NULL)
        return NULL;
     s  = socket(AF_INET, SOCK_STREAM, 0);
index bd800ac5a1c0a64cb10698e0c631b04f7f2b6e81..ef594ffd0df5ac08aa0214ae302b7a90513e5a87 100644 (file)
@@ -316,6 +316,19 @@ socket_to_fd(rk_socket_t sock, int flags)
 #endif
 }
 
+#ifdef HAVE_WINSOCK
+ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
+rk_SOCK_IOCTL(SOCKET s, long cmd, int * argp) {
+    u_long ul = (argp)? *argp : 0;
+    int rv;
+
+    rv = ioctlsocket(s, cmd, &ul);
+    if (argp)
+       *argp = (int) ul;
+    return rv;
+}
+#endif
+
 #ifndef HEIMDAL_SMALLER
 #undef socket
 
index 5155c28cb56030ba827cd8c643f3680ab6966ba0..85271ecaf5c9ed5c77047c214fc8a10e07e20c97 100644 (file)
@@ -72,7 +72,7 @@ rk_strerror_r(int eno, char *strerrbuf, size_t buflen)
     return 0;
 #else
     int ret;
-    ret = strlcpy(strerrbuf, buflen, strerror(eno));
+    ret = strlcpy(strerrbuf, strerror(eno), buflen);
     if (ret > buflen)
        return ERANGE;
     return 0;
index b2e2210493b2cb69a9b4d172be808ee3d7302ef6..c2907832a2761eaf5041f2c6fe6ddd0ca747f185 100644 (file)
@@ -49,7 +49,7 @@ error_entry_cmp(const void *a, const void *b)
 }
 
 int
-_wind_stringprep_error(uint32_t cp, wind_profile_flags flags)
+_wind_stringprep_error(const uint32_t cp, wind_profile_flags flags)
 {
     struct error_entry ee = {cp};
     const struct error_entry *s;
index 102c577e66455c993c5753024e4c24faadd2e4e2..3c68ea866007a174d4eb2e93d48f271c84f30e1d 100644 (file)
@@ -164,13 +164,32 @@ compat_decomp(const uint32_t *in, size_t in_len,
     return 0;
 }
 
-static int
-cc_cmp(const void *a, const void *b)
+static void
+swap_char(uint32_t * a, uint32_t * b)
+{
+    uint32_t t;
+    t = *a;
+    *a = *b;
+    *b = t;
+}
+
+/* Unicode 5.2.0 D109 Canonical Ordering for a sequence of code points
+ * that all have Canonical_Combining_Class > 0 */
+static void
+canonical_reorder_sequence(uint32_t * a, size_t len)
 {
-    const uint32_t *ua = (const uint32_t *)a;
-    const uint32_t *ub = (const uint32_t *)b;
+    size_t i, j;
 
-    return _wind_combining_class(*ua) - _wind_combining_class(*ub);
+    if (len <= 1)
+       return;
+
+    for (i = 1; i < len; i++) {
+       for (j = i;
+            j > 0 &&
+                _wind_combining_class(a[j]) < _wind_combining_class(a[j-1]);
+            j--)
+           swap_char(&a[j], &a[j-1]);
+    }
 }
 
 static void
@@ -186,7 +205,7 @@ canonical_reorder(uint32_t *tmp, size_t tmp_len)
                 j < tmp_len && _wind_combining_class(tmp[j]);
                 ++j)
                ;
-           qsort(&tmp[i], j - i, sizeof(tmp[0]), cc_cmp);
+           canonical_reorder_sequence(&tmp[i], j - i);
            i = j;
        }
     }
index d64686a252dcf0d512b61cc5d18a1e2e2cdb6fdc..249b1dc2a1ca7ab75dc5fec353f3df36045ddbf2 100644 (file)
@@ -46,7 +46,8 @@ ldap_error = ['A.1', 'C.3', 'C.4', 'C.5', 'C.8', 'rfc4518-error' ]
 sasl_error = ['C.1.2', 'C.2.1', 'C.2.2', 'C.3', 'C.4', 'C.5', 'C.6', 'C.7', 'C.8', 'C.9']
 
 name_map = ['B.1', 'B.2']
-ldap_map = ['rfc4518-map', 'B.2']
+ldap_map = ['rfc4518-map']
+ldap_case_map = ['rfc4518-map', 'B.2']
 sasl_map = ['C.1.2', 'B.1']
 
 def symbols(tabledict, tables):
@@ -69,6 +70,7 @@ def get_maplist():
     d = dict()
     _merge_table(d, dict(map(lambda x: [x, ['name']], name_map)))
     _merge_table(d, dict(map(lambda x: [x, ['ldap']], ldap_map)))
+    _merge_table(d, dict(map(lambda x: [x, ['ldap_case']], ldap_case_map)))
     _merge_table(d, dict(map(lambda x: [x, ['sasl']], sasl_map)))
     return d
 
index e890bebeee71d130c9738dcea55106a08b99ce83..dd55ea35db5d71faccc796149c8a2e67296cfc4f 100644 (file)
@@ -46,6 +46,7 @@ typedef unsigned int wind_profile_flags;
 #define WIND_PROFILE_NAME                      0x00000001
 #define WIND_PROFILE_SASL                      0x00000002
 #define WIND_PROFILE_LDAP                      0x00000004
+#define WIND_PROFILE_LDAP_CASE                 0x00000008
 
 #define WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE 0x00010000
 #define WIND_PROFILE_LDAP_CASE_EXACT_ASSERTION 0x00020000