summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/hcrypto
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal/lib/hcrypto')
-rw-r--r--source4/heimdal/lib/hcrypto/aes.c23
-rw-r--r--source4/heimdal/lib/hcrypto/aes.h4
-rw-r--r--source4/heimdal/lib/hcrypto/camellia.h2
-rw-r--r--source4/heimdal/lib/hcrypto/common.c69
-rw-r--r--source4/heimdal/lib/hcrypto/common.h45
-rw-r--r--source4/heimdal/lib/hcrypto/dh-imath.c9
-rw-r--r--source4/heimdal/lib/hcrypto/dh-ltm.c249
-rw-r--r--source4/heimdal/lib/hcrypto/dh.c63
-rw-r--r--source4/heimdal/lib/hcrypto/dh.h7
-rw-r--r--source4/heimdal/lib/hcrypto/engine.c104
-rw-r--r--source4/heimdal/lib/hcrypto/engine.h15
-rw-r--r--source4/heimdal/lib/hcrypto/evp-cc.c856
-rw-r--r--source4/heimdal/lib/hcrypto/evp-cc.h7
-rw-r--r--source4/heimdal/lib/hcrypto/evp-hcrypto.c93
-rw-r--r--source4/heimdal/lib/hcrypto/evp-hcrypto.h7
-rw-r--r--source4/heimdal/lib/hcrypto/evp.c74
-rw-r--r--source4/heimdal/lib/hcrypto/evp.h11
-rw-r--r--source4/heimdal/lib/hcrypto/hash.h3
-rw-r--r--source4/heimdal/lib/hcrypto/imath/imath.c2
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/LICENSE4
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn.ilg6
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn.ind82
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_error.c47
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_fast_mp_invmod.c148
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c172
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c107
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c98
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c114
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_2expt.c48
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_abs.c43
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_add.c53
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_add_d.c112
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_addmod.c41
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_and.c57
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_clamp.c44
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_clear.c44
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_clear_multi.c34
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp.c43
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp_d.c44
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp_mag.c55
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c53
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_copy.c68
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_count_bits.c45
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_div.c292
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_2.c68
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_2d.c97
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_3.c79
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c115
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c43
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_reduce.c94
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_setup.c32
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_exch.c34
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_expt_d.c57
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_exptmod.c112
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_exptmod_fast.c321
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_exteuclid.c82
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_find_prime.c26
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_fread.c67
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_fwrite.c52
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_gcd.c105
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_get_int.c45
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_grow.c57
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_init.c46
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_copy.c32
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_multi.c59
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_set.c32
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_set_int.c31
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_size.c48
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_invmod.c43
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_invmod_slow.c175
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_is_square.c109
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_isprime.c75
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_jacobi.c105
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c167
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_karatsuba_sqr.c121
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_lcm.c60
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_lshd.c67
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod.c48
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod_2d.c55
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod_d.c27
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c59
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c118
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c59
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul.c66
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2.c82
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2d.c85
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_d.c79
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_mulmod.c40
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_n_root.c132
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_neg.c40
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_or.c50
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_fermat.c62
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c50
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c83
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c103
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c170
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c52
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_random_ex.c125
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_radix_size.c78
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_radix_smap.c24
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_rand.c55
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_radix.c85
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_signed_bin.c41
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c55
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce.c100
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k.c61
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c62
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c47
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c44
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c52
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c44
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_setup.c34
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_rshd.c72
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_set.c29
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_set_int.c48
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_shrink.c35
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_signed_bin_size.c27
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqr.c58
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqrmod.c41
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqrt.c81
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_sub.c59
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_sub_d.c93
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_submod.c42
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_signed_bin.c33
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c31
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c48
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c31
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_toom_mul.c284
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_toom_sqr.c226
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_toradix.c75
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_toradix_n.c88
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c28
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_xor.c51
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_zero.c36
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_mp_zero_multi.c35
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_prime_tab.c61
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_reverse.c39
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_add.c109
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_exptmod.c252
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c90
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c81
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_sqr.c84
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_sub.c89
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/bncore.c36
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/booker.pl265
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/callgraph.txt11913
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/libtommath.dsp572
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/mtest/logtab.h24
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-config.h90
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-types.h20
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.c3985
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.h231
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/mtest/mtest.c308
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/pics/design_process.sxdbin0 -> 6950 bytes
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/pics/design_process.tifbin0 -> 79042 bytes
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.sxdbin0 -> 6869 bytes
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.tifbin0 -> 87542 bytes
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/pics/makefile35
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/pics/primality.tifbin0 -> 85514 bytes
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/pics/radix.sxdbin0 -> 6181 bytes
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.sxdbin0 -> 6787 bytes
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.tifbin0 -> 53880 bytes
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/pretty.build66
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/tombc/grammar.txt35
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/tommath.h592
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/tommath_class.h1000
-rw-r--r--source4/heimdal/lib/hcrypto/libtommath/tommath_superclass.h76
-rw-r--r--source4/heimdal/lib/hcrypto/md4.c6
-rw-r--r--source4/heimdal/lib/hcrypto/md5.c6
-rw-r--r--source4/heimdal/lib/hcrypto/rand-fortuna.c44
-rw-r--r--source4/heimdal/lib/hcrypto/rand-unix.c2
-rw-r--r--source4/heimdal/lib/hcrypto/rand.c24
-rw-r--r--source4/heimdal/lib/hcrypto/rand.h2
-rw-r--r--source4/heimdal/lib/hcrypto/randi.h2
-rw-r--r--source4/heimdal/lib/hcrypto/rijndael-alg-fst.c51
-rw-r--r--source4/heimdal/lib/hcrypto/rsa-imath.c9
-rw-r--r--source4/heimdal/lib/hcrypto/rsa-ltm.c630
-rw-r--r--source4/heimdal/lib/hcrypto/rsa.c221
-rw-r--r--source4/heimdal/lib/hcrypto/rsa.h6
-rw-r--r--source4/heimdal/lib/hcrypto/sha.c10
-rw-r--r--source4/heimdal/lib/hcrypto/sha256.c6
-rw-r--r--source4/heimdal/lib/hcrypto/ui.c2
-rw-r--r--source4/heimdal/lib/hcrypto/validate.c308
183 files changed, 31330 insertions, 123 deletions
diff --git a/source4/heimdal/lib/hcrypto/aes.c b/source4/heimdal/lib/hcrypto/aes.c
index b3049c165a..77847e460e 100644
--- a/source4/heimdal/lib/hcrypto/aes.c
+++ b/source4/heimdal/lib/hcrypto/aes.c
@@ -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);
+ }
+}
diff --git a/source4/heimdal/lib/hcrypto/aes.h b/source4/heimdal/lib/hcrypto/aes.h
index 273f1dd569..4ba4516519 100644
--- a/source4/heimdal/lib/hcrypto/aes.h
+++ b/source4/heimdal/lib/hcrypto/aes.h
@@ -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
}
diff --git a/source4/heimdal/lib/hcrypto/camellia.h b/source4/heimdal/lib/hcrypto/camellia.h
index feabae1aa3..6661f3bf07 100644
--- a/source4/heimdal/lib/hcrypto/camellia.h
+++ b/source4/heimdal/lib/hcrypto/camellia.h
@@ -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
index 0000000000..136bf1db10
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/common.c
@@ -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
index 0000000000..f78f544401
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/common.h
@@ -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 */
diff --git a/source4/heimdal/lib/hcrypto/dh-imath.c b/source4/heimdal/lib/hcrypto/dh-imath.c
index 822d5a328b..c2e86fa2fa 100644
--- a/source4/heimdal/lib/hcrypto/dh-imath.c
+++ b/source4/heimdal/lib/hcrypto/dh-imath.c
@@ -31,14 +31,14 @@
* 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
index 0000000000..6166100b08
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/dh-ltm.c
@@ -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;
+}
diff --git a/source4/heimdal/lib/hcrypto/dh.c b/source4/heimdal/lib/hcrypto/dh.c
index d42ac34fd2..3ad37f87a7 100644
--- a/source4/heimdal/lib/hcrypto/dh.c
+++ b/source4/heimdal/lib/hcrypto/dh.c
@@ -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;
+}
diff --git a/source4/heimdal/lib/hcrypto/dh.h b/source4/heimdal/lib/hcrypto/dh.h
index 2522bfe39f..3a24f9dfdf 100644
--- a/source4/heimdal/lib/hcrypto/dh.h
+++ b/source4/heimdal/lib/hcrypto/dh.h
@@ -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 */
diff --git a/source4/heimdal/lib/hcrypto/engine.c b/source4/heimdal/lib/hcrypto/engine.c
index 8066d59cf8..6e3e5e3939 100644
--- a/source4/heimdal/lib/hcrypto/engine.c
+++ b/source4/heimdal/lib/hcrypto/engine.c
@@ -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 *
diff --git a/source4/heimdal/lib/hcrypto/engine.h b/source4/heimdal/lib/hcrypto/engine.h
index d3a1479ce2..7fd8f3e1e5 100644
--- a/source4/heimdal/lib/hcrypto/engine.h
+++ b/source4/heimdal/lib/hcrypto/engine.h
@@ -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
@@ -66,6 +68,16 @@
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
index 0000000000..bd084a25e2
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/evp-cc.c
@@ -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__ */
+
diff --git a/source4/heimdal/lib/hcrypto/evp-cc.h b/source4/heimdal/lib/hcrypto/evp-cc.h
index 0febd21e98..9249bb226e 100644
--- a/source4/heimdal/lib/hcrypto/evp-cc.h
+++ b/source4/heimdal/lib/hcrypto/evp-cc.h
@@ -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);
diff --git a/source4/heimdal/lib/hcrypto/evp-hcrypto.c b/source4/heimdal/lib/hcrypto/evp-hcrypto.c
index 699fc667b0..9e063545e1 100644
--- a/source4/heimdal/lib/hcrypto/evp-hcrypto.c
+++ b/source4/heimdal/lib/hcrypto/evp-hcrypto.c
@@ -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;
}
@@ -176,6 +179,94 @@ EVP_hcrypto_aes_256_cbc(void)
}
/**
+ * 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
*
* @return the message digest type.
diff --git a/source4/heimdal/lib/hcrypto/evp-hcrypto.h b/source4/heimdal/lib/hcrypto/evp-hcrypto.h
index c0fb89af71..7915046bdc 100644
--- a/source4/heimdal/lib/hcrypto/evp-hcrypto.h
+++ b/source4/heimdal/lib/hcrypto/evp-hcrypto.h
@@ -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);
diff --git a/source4/heimdal/lib/hcrypto/evp.c b/source4/heimdal/lib/hcrypto/evp.c
index 72787e185f..da1a8940be 100644
--- a/source4/heimdal/lib/hcrypto/evp.c
+++ b/source4/heimdal/lib/hcrypto/evp.c
@@ -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,10 +1141,56 @@ 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
*
* @return the Camellia-128 EVP_CIPHER pointer.
@@ -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;
diff --git a/source4/heimdal/lib/hcrypto/evp.h b/source4/heimdal/lib/hcrypto/evp.h
index ae92ab4899..03ec175d59 100644
--- a/source4/heimdal/lib/hcrypto/evp.h
+++ b/source4/heimdal/lib/hcrypto/evp.h
@@ -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
@@ -101,6 +104,7 @@
#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 */
diff --git a/source4/heimdal/lib/hcrypto/hash.h b/source4/heimdal/lib/hcrypto/hash.h
index 78a795f2a7..cfec9cf3f3 100644
--- a/source4/heimdal/lib/hcrypto/hash.h
+++ b/source4/heimdal/lib/hcrypto/hash.h
@@ -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
diff --git a/source4/heimdal/lib/hcrypto/imath/imath.c b/source4/heimdal/lib/hcrypto/imath/imath.c
index 4e47a76ce2..0079bafd02 100644
--- a/source4/heimdal/lib/hcrypto/imath/imath.c
+++ b/source4/heimdal/lib/hcrypto/imath/imath.c
@@ -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
index 0000000000..5baa792a65
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/LICENSE
@@ -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
index 0000000000..3c859f0346
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn.ilg
@@ -0,0 +1,6 @@
+This is makeindex, version 2.14 [02-Oct-2002] (kpathsea + Thai support).
+Scanning input file bn.idx....done (79 entries accepted, 0 rejected).
+Sorting entries....done (511 comparisons).
+Generating output file bn.ind....done (82 lines written, 0 warnings).
+Output written in bn.ind.
+Transcript written in bn.ilg.
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn.ind b/source4/heimdal/lib/hcrypto/libtommath/bn.ind
new file mode 100644
index 0000000000..c099b521d1
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn.ind
@@ -0,0 +1,82 @@
+\begin{theindex}
+
+ \item mp\_add, \hyperpage{31}
+ \item mp\_add\_d, \hyperpage{56}
+ \item mp\_and, \hyperpage{31}
+ \item mp\_clear, \hyperpage{12}
+ \item mp\_clear\_multi, \hyperpage{13}
+ \item mp\_cmp, \hyperpage{25}
+ \item mp\_cmp\_d, \hyperpage{26}
+ \item mp\_cmp\_mag, \hyperpage{23}
+ \item mp\_div, \hyperpage{32}
+ \item mp\_div\_2, \hyperpage{28}
+ \item mp\_div\_2d, \hyperpage{30}
+ \item mp\_div\_d, \hyperpage{56}
+ \item mp\_dr\_reduce, \hyperpage{45}
+ \item mp\_dr\_setup, \hyperpage{45}
+ \item MP\_EQ, \hyperpage{23}
+ \item mp\_error\_to\_string, \hyperpage{9}
+ \item mp\_expt\_d, \hyperpage{47}
+ \item mp\_exptmod, \hyperpage{47}
+ \item mp\_exteuclid, \hyperpage{55}
+ \item mp\_gcd, \hyperpage{55}
+ \item mp\_get\_int, \hyperpage{20}
+ \item mp\_grow, \hyperpage{17}
+ \item MP\_GT, \hyperpage{23}
+ \item mp\_init, \hyperpage{11}
+ \item mp\_init\_copy, \hyperpage{14}
+ \item mp\_init\_multi, \hyperpage{13}
+ \item mp\_init\_set, \hyperpage{21}
+ \item mp\_init\_set\_int, \hyperpage{21}
+ \item mp\_init\_size, \hyperpage{15}
+ \item mp\_int, \hyperpage{10}
+ \item mp\_invmod, \hyperpage{56}
+ \item mp\_jacobi, \hyperpage{56}
+ \item mp\_lcm, \hyperpage{56}
+ \item mp\_lshd, \hyperpage{30}
+ \item MP\_LT, \hyperpage{23}
+ \item MP\_MEM, \hyperpage{9}
+ \item mp\_mod, \hyperpage{39}
+ \item mp\_mod\_d, \hyperpage{56}
+ \item mp\_montgomery\_calc\_normalization, \hyperpage{42}
+ \item mp\_montgomery\_reduce, \hyperpage{42}
+ \item mp\_montgomery\_setup, \hyperpage{42}
+ \item mp\_mul, \hyperpage{33}
+ \item mp\_mul\_2, \hyperpage{28}
+ \item mp\_mul\_2d, \hyperpage{29}
+ \item mp\_mul\_d, \hyperpage{56}
+ \item mp\_n\_root, \hyperpage{48}
+ \item mp\_neg, \hyperpage{31, 32}
+ \item MP\_NO, \hyperpage{9}
+ \item MP\_OKAY, \hyperpage{9}
+ \item mp\_or, \hyperpage{31}
+ \item mp\_prime\_fermat, \hyperpage{49}
+ \item mp\_prime\_is\_divisible, \hyperpage{49}
+ \item mp\_prime\_is\_prime, \hyperpage{51}
+ \item mp\_prime\_miller\_rabin, \hyperpage{50}
+ \item mp\_prime\_next\_prime, \hyperpage{51}
+ \item mp\_prime\_rabin\_miller\_trials, \hyperpage{50}
+ \item mp\_prime\_random, \hyperpage{51}
+ \item mp\_prime\_random\_ex, \hyperpage{52}
+ \item mp\_radix\_size, \hyperpage{53}
+ \item mp\_read\_radix, \hyperpage{53}
+ \item mp\_read\_unsigned\_bin, \hyperpage{54}
+ \item mp\_reduce, \hyperpage{40}
+ \item mp\_reduce\_2k, \hyperpage{46}
+ \item mp\_reduce\_2k\_setup, \hyperpage{46}
+ \item mp\_reduce\_setup, \hyperpage{40}
+ \item mp\_rshd, \hyperpage{30}
+ \item mp\_set, \hyperpage{19}
+ \item mp\_set\_int, \hyperpage{20}
+ \item mp\_shrink, \hyperpage{16}
+ \item mp\_sqr, \hyperpage{35}
+ \item mp\_sub, \hyperpage{31}
+ \item mp\_sub\_d, \hyperpage{56}
+ \item mp\_to\_unsigned\_bin, \hyperpage{54}
+ \item mp\_toradix, \hyperpage{53}
+ \item mp\_unsigned\_bin\_size, \hyperpage{54}
+ \item MP\_VAL, \hyperpage{9}
+ \item mp\_xor, \hyperpage{31}
+ \item MP\_YES, \hyperpage{9}
+
+\end{theindex}
diff --git a/source4/heimdal/lib/hcrypto/libtommath/bn_error.c b/source4/heimdal/lib/hcrypto/libtommath/bn_error.c
new file mode 100644
index 0000000000..b1b7177e61
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_error.c
@@ -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
index 0000000000..ff03dfffe3
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_fast_mp_invmod.c
@@ -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
index 0000000000..b6c0694bd2
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_fast_mp_montgomery_reduce.c
@@ -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
index 0000000000..91e10d670f
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_mul_digs.c
@@ -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
index 0000000000..5b114d717a
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_mul_high_digs.c
@@ -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
index 0000000000..19e92ef180
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_fast_s_mp_sqr.c
@@ -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
index 0000000000..f422ffc994
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_2expt.c
@@ -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
index 0000000000..09dd7229eb
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_abs.c
@@ -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
index 0000000000..be20644770
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_add.c
@@ -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
index 0000000000..8ca36c1124
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_add_d.c
@@ -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
index 0000000000..6d8afe18c9
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_addmod.c
@@ -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
index 0000000000..8ea22878f9
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_and.c
@@ -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
index 0000000000..359c2ff24d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_clamp.c
@@ -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
index 0000000000..a65f0a36c4
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_clear.c
@@ -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
index 0000000000..daaea79a3b
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_clear_multi.c
@@ -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
index 0000000000..533f36bf93
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp.c
@@ -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
index 0000000000..724c1c3634
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp_d.c
@@ -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
index 0000000000..693eb7cc72
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cmp_mag.c
@@ -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
index 0000000000..66d1a74714
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_cnt_lsb.c
@@ -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
index 0000000000..b0de16d8ab
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_copy.c
@@ -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
index 0000000000..8bc5657a33
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_count_bits.c
@@ -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
index 0000000000..aee9c94324
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div.c
@@ -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
index 0000000000..7ee3e5b70f
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_2.c
@@ -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
index 0000000000..4f7fa59e3f
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_2d.c
@@ -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
index 0000000000..3c60269ece
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_3.c
@@ -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
index 0000000000..6a26d4f0cf
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_div_d.c
@@ -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
index 0000000000..52373440d8
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_is_modulus.c
@@ -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
index 0000000000..e60b5784f1
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_reduce.c
@@ -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
index 0000000000..1d7d856ef0
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_dr_setup.c
@@ -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
index 0000000000..38574e0a5e
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exch.c
@@ -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
index 0000000000..4bdc2d13a6
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_expt_d.c
@@ -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
index 0000000000..023191657a
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exptmod.c
@@ -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
index 0000000000..2a3b3c9e81
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exptmod_fast.c
@@ -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
index 0000000000..e6c4ce2b85
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_exteuclid.c
@@ -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
index 0000000000..0458744fc7
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_find_prime.c
@@ -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
index 0000000000..b344b6f05d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_fread.c
@@ -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
index 0000000000..a0b4c6b6d1
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_fwrite.c
@@ -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
index 0000000000..b39ba9041d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_gcd.c
@@ -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
index 0000000000..17162e2bf1
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_get_int.c
@@ -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
index 0000000000..cf2b949b24
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_grow.c
@@ -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
index 0000000000..8be27f5696
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init.c
@@ -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
index 0000000000..0160811aff
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_copy.c
@@ -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
index 0000000000..59dc3a9ea7
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_multi.c
@@ -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
index 0000000000..34edad92ff
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_set.c
@@ -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
index 0000000000..5c55993152
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_set_int.c
@@ -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
index 0000000000..8e014183a3
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_init_size.c
@@ -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
index 0000000000..154651468f
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_invmod.c
@@ -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
index 0000000000..eedd47dcf1
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_invmod_slow.c
@@ -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
index 0000000000..50c524444e
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_is_square.c
@@ -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
index 0000000000..07ce86f296
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_isprime.c
@@ -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
index 0000000000..91cfeeade4
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_jacobi.c
@@ -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
index 0000000000..8ea2c2792a
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_karatsuba_mul.c
@@ -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
index 0000000000..a5e198be12
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_karatsuba_sqr.c
@@ -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
index 0000000000..781eef5659
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_lcm.c
@@ -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
index 0000000000..f118cf1ae5
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_lshd.c
@@ -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
index 0000000000..f5cf8d09f2
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod.c
@@ -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
index 0000000000..e194a06870
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod_2d.c
@@ -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
index 0000000000..9ca37e6732
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mod_d.c
@@ -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
index 0000000000..c669fe0ec3
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_calc_normalization.c
@@ -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
index 0000000000..b76509051b
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_reduce.c
@@ -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
index 0000000000..f08274936e
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_montgomery_setup.c
@@ -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
index 0000000000..8b1117a63b
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul.c
@@ -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
index 0000000000..02455fc35d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2.c
@@ -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
index 0000000000..efeff2e751
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_2d.c
@@ -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
index 0000000000..00f9a899ef
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mul_d.c
@@ -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
index 0000000000..003ceb9b97
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_mulmod.c
@@ -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
index 0000000000..0e7bedca72
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_n_root.c
@@ -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
index 0000000000..a7d035ab6d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_neg.c
@@ -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
index 0000000000..bff4995489
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_or.c
@@ -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
index 0000000000..c23d77f6de
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_fermat.c
@@ -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
index 0000000000..8e7871c2c6
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_is_divisible.c
@@ -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
index 0000000000..c316d62109
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_is_prime.c
@@ -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
index 0000000000..ddf03582ac
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_miller_rabin.c
@@ -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
index 0000000000..daf2ec7c64
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_next_prime.c
@@ -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
index 0000000000..248c2fd2e6
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_rabin_miller_trials.c
@@ -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
index 0000000000..07aae4b072
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_prime_random_ex.c
@@ -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
index 0000000000..1b61e3a1be
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_radix_size.c
@@ -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
index 0000000000..7d72feb84e
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_radix_smap.c
@@ -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
index 0000000000..af66a67eea
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_rand.c
@@ -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
index 0000000000..91c46c22f7
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_radix.c
@@ -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
index 0000000000..8da651ce30
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_signed_bin.c
@@ -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
index 0000000000..1ebba13a02
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_read_unsigned_bin.c
@@ -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
index 0000000000..21d0730905
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce.c
@@ -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
index 0000000000..d9620c221c
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k.c
@@ -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
index 0000000000..f06103d6a6
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_l.c
@@ -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
index 0000000000..a80e7a22f2
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup.c
@@ -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
index 0000000000..7cf002e888
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_2k_setup_l.c
@@ -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
index 0000000000..7308be73e2
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_is_2k.c
@@ -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
index 0000000000..14a4d21846
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_is_2k_l.c
@@ -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
index 0000000000..370f20bb17
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_reduce_setup.c
@@ -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
index 0000000000..2a693c5a5b
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_rshd.c
@@ -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
index 0000000000..174adcbc6d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_set.c
@@ -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
index 0000000000..cf10ea1a44
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_set_int.c
@@ -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
index 0000000000..4b8c5ef11a
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_shrink.c
@@ -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
index 0000000000..6739d19e2b
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_signed_bin_size.c
@@ -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
index 0000000000..868ccbbaef
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqr.c
@@ -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
index 0000000000..161cbbb30d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqrmod.c
@@ -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
index 0000000000..8fd057ceed
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sqrt.c
@@ -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
index 0000000000..f5015cce45
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sub.c
@@ -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
index 0000000000..06cdca636d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_sub_d.c
@@ -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
index 0000000000..869e23cded
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_submod.c
@@ -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
index 0000000000..9df83ca526
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_signed_bin.c
@@ -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
index 0000000000..677f827d4f
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_signed_bin_n.c
@@ -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
index 0000000000..c137f104ac
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin.c
@@ -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
index 0000000000..0dc00c623d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_to_unsigned_bin_n.c
@@ -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
index 0000000000..ad5d9e9b64
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toom_mul.c
@@ -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
index 0000000000..48880d0350
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toom_sqr.c
@@ -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
index 0000000000..0adc28d2fd
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toradix.c
@@ -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
index 0000000000..796ed55c65
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_toradix_n.c
@@ -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
index 0000000000..6dc3bd5fc1
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_unsigned_bin_size.c
@@ -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
index 0000000000..59ff2e1832
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_xor.c
@@ -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
index 0000000000..b0977d4431
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_zero.c
@@ -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
index 0000000000..339a75fbf8
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_mp_zero_multi.c
@@ -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
index 0000000000..bd252477ec
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_prime_tab.c
@@ -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
index 0000000000..ddfa827a09
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_reverse.c
@@ -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
index 0000000000..f034ae62aa
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_add.c
@@ -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
index 0000000000..097d894702
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_exptmod.c
@@ -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
index 0000000000..f5bbf39ce2
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_digs.c
@@ -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
index 0000000000..2b718f23cc
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_mul_high_digs.c
@@ -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
index 0000000000..d2531c2925
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_sqr.c
@@ -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
index 0000000000..6a60c3932c
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bn_s_mp_sub.c
@@ -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
index 0000000000..8fb1824c6f
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/bncore.c
@@ -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
index 0000000000..49f1889d1b
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/booker.pl
@@ -0,0 +1,265 @@
+#!/bin/perl
+#
+#Used to prepare the book "tommath.src" for LaTeX by pre-processing it into a .tex file
+#
+#Essentially you write the "tommath.src" as normal LaTex except where you want code snippets you put
+#
+#EXAM,file
+#
+#This preprocessor will then open "file" and insert it as a verbatim copy.
+#
+#Tom St Denis
+
+#get graphics type
+if (shift =~ /PDF/) {
+ $graph = "";
+} else {
+ $graph = ".ps";
+}
+
+open(IN,"<tommath.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
index 0000000000..2efcf245ba
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/callgraph.txt
@@ -0,0 +1,11913 @@
+BN_PRIME_TAB_C
+
+
+BN_MP_SQRT_C
++--->BN_MP_N_ROOT_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_EXPT_D_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
++--->BN_MP_DIV_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_SET_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CMP_D_C
+
+
+BN_MP_EXCH_C
+
+
+BN_MP_IS_SQUARE_C
++--->BN_MP_MOD_D_C
+| +--->BN_MP_DIV_D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SET_INT_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_SET_INT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_GET_INT_C
++--->BN_MP_SQRT_C
+| +--->BN_MP_N_ROOT_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_EXPT_D_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_ABS_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_SUB_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_NEG_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
+
+
+BN_MP_EXPTMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_INVMOD_C
+| +--->BN_FAST_MP_INVMOD_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_ABS_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_CMP_D_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INVMOD_SLOW_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_ABS_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_CMP_D_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_ABS_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_MULTI_C
++--->BN_MP_REDUCE_IS_2K_L_C
++--->BN_S_MP_EXPTMOD_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_REDUCE_SETUP_C
+| | +--->BN_MP_2EXPT_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_REDUCE_C
+| | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_D_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | +--->BN_MP_2EXPT_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_REDUCE_2K_L_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_SQR_C
+| | +--->BN_MP_TOOM_SQR_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_KARATSUBA_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | +--->BN_FAST_S_MP_SQR_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_DR_IS_MODULUS_C
++--->BN_MP_REDUCE_IS_2K_C
+| +--->BN_MP_REDUCE_2K_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_COUNT_BITS_C
++--->BN_MP_EXPTMOD_FAST_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_MONTGOMERY_SETUP_C
+| +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| +--->BN_MP_MONTGOMERY_REDUCE_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| +--->BN_MP_DR_SETUP_C
+| +--->BN_MP_DR_REDUCE_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| +--->BN_MP_REDUCE_2K_SETUP_C
+| | +--->BN_MP_2EXPT_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_REDUCE_2K_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | +--->BN_MP_2EXPT_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MULMOD_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_SQR_C
+| | +--->BN_MP_TOOM_SQR_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_KARATSUBA_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | +--->BN_FAST_S_MP_SQR_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+
+
+BN_MP_OR_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_ZERO_C
+
+
+BN_MP_GROW_C
+
+
+BN_MP_COUNT_BITS_C
+
+
+BN_MP_PRIME_FERMAT_C
++--->BN_MP_CMP_D_C
++--->BN_MP_INIT_C
++--->BN_MP_EXPTMOD_C
+| +--->BN_MP_INVMOD_C
+| | +--->BN_FAST_MP_INVMOD_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_ABS_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2D_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_INIT_COPY_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INVMOD_SLOW_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_ABS_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2D_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_INIT_COPY_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ABS_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_REDUCE_IS_2K_L_C
+| +--->BN_S_MP_EXPTMOD_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_REDUCE_SETUP_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_L_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DR_IS_MODULUS_C
+| +--->BN_MP_REDUCE_IS_2K_C
+| | +--->BN_MP_REDUCE_2K_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_EXPTMOD_FAST_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_MONTGOMERY_SETUP_C
+| | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_MONTGOMERY_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_DR_SETUP_C
+| | +--->BN_MP_DR_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_REDUCE_2K_SETUP_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MULMOD_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2D_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_INIT_COPY_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_COPY_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_SUBMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+
+
+BN_MP_MOD_2D_C
++--->BN_MP_ZERO_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_TORADIX_N_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_DIV_D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CMP_C
++--->BN_MP_CMP_MAG_C
+
+
+BNCORE_C
+
+
+BN_MP_TORADIX_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_DIV_D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_ADD_D_C
++--->BN_MP_GROW_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_DIV_3_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_FAST_S_MP_MUL_DIGS_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_SQRMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+
+
+BN_MP_INVMOD_C
++--->BN_FAST_MP_INVMOD_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_ABS_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_DIV_2_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_CMP_D_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_INVMOD_SLOW_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_ABS_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_DIV_2_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_CMP_D_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+
+
+BN_MP_AND_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_MUL_D_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_FAST_MP_INVMOD_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_MOD_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_MP_CMP_D_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_FWRITE_C
++--->BN_MP_RADIX_SIZE_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_TORADIX_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_S_MP_SQR_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_N_ROOT_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_EXPT_D_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_SQR_C
+| | +--->BN_MP_TOOM_SQR_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_KARATSUBA_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_FAST_S_MP_SQR_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+
+
+BN_MP_RADIX_SIZE_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_DIV_D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_READ_SIGNED_BIN_C
++--->BN_MP_READ_UNSIGNED_BIN_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_PRIME_RANDOM_EX_C
++--->BN_MP_READ_UNSIGNED_BIN_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_PRIME_IS_PRIME_C
+| +--->BN_MP_CMP_D_C
+| +--->BN_MP_PRIME_IS_DIVISIBLE_C
+| | +--->BN_MP_MOD_D_C
+| | | +--->BN_MP_DIV_D_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_DIV_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_INIT_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_INIT_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_PRIME_MILLER_RABIN_C
+| | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SUB_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CNT_LSB_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXPTMOD_C
+| | | +--->BN_MP_INVMOD_C
+| | | | +--->BN_FAST_MP_INVMOD_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_MOD_C
+| | | | | | +--->BN_MP_DIV_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | | +--->BN_MP_ABS_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_INVMOD_SLOW_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_MOD_C
+| | | | | | +--->BN_MP_DIV_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | | +--->BN_MP_ABS_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_ABS_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_REDUCE_IS_2K_L_C
+| | | +--->BN_S_MP_EXPTMOD_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_REDUCE_SETUP_C
+| | | | | +--->BN_MP_2EXPT_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_REDUCE_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_C
+| | | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | | | | +--->BN_MP_2EXPT_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_REDUCE_2K_L_C
+| | | | | +--->BN_MP_MUL_C
+| | | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_SQR_C
+| | | | | +--->BN_MP_TOOM_SQR_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SQR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_DR_IS_MODULUS_C
+| | | +--->BN_MP_REDUCE_IS_2K_C
+| | | | +--->BN_MP_REDUCE_2K_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_EXPTMOD_FAST_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_MONTGOMERY_SETUP_C
+| | | | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_MONTGOMERY_REDUCE_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_DR_SETUP_C
+| | | | +--->BN_MP_DR_REDUCE_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_REDUCE_2K_SETUP_C
+| | | | | +--->BN_MP_2EXPT_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_REDUCE_2K_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | | | | +--->BN_MP_2EXPT_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MULMOD_C
+| | | | | +--->BN_MP_MUL_C
+| | | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_MOD_C
+| | | | | | +--->BN_MP_DIV_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_C
+| | | | | | | +--->BN_MP_SUB_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_ADD_C
+| | | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_SQR_C
+| | | | | +--->BN_MP_TOOM_SQR_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SQR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_SQRMOD_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_ABS_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_KARATSUBA_SQR_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
++--->BN_S_MP_ADD_C
+| +--->BN_MP_GROW_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
++--->BN_MP_ADD_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_INIT_COPY_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
+
+
+BN_MP_CLAMP_C
+
+
+BN_MP_TOOM_SQR_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_MOD_2D_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_SQR_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_2_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_3_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_MOD_C
++--->BN_MP_INIT_C
++--->BN_MP_DIV_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_SET_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
+
+
+BN_MP_INIT_C
+
+
+BN_MP_TOOM_MUL_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_MOD_2D_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_MUL_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_2_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_3_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_PRIME_IS_PRIME_C
++--->BN_MP_CMP_D_C
++--->BN_MP_PRIME_IS_DIVISIBLE_C
+| +--->BN_MP_MOD_D_C
+| | +--->BN_MP_DIV_D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_INIT_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_PRIME_MILLER_RABIN_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CNT_LSB_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXPTMOD_C
+| | +--->BN_MP_INVMOD_C
+| | | +--->BN_FAST_MP_INVMOD_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | +--->BN_MP_ABS_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INVMOD_SLOW_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | +--->BN_MP_ABS_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_ABS_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_REDUCE_IS_2K_L_C
+| | +--->BN_S_MP_EXPTMOD_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_REDUCE_SETUP_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_L_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DR_IS_MODULUS_C
+| | +--->BN_MP_REDUCE_IS_2K_C
+| | | +--->BN_MP_REDUCE_2K_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_EXPTMOD_FAST_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_MONTGOMERY_SETUP_C
+| | | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_MONTGOMERY_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_DR_SETUP_C
+| | | +--->BN_MP_DR_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_REDUCE_2K_SETUP_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MULMOD_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_SQRMOD_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_ABS_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_COPY_C
++--->BN_MP_GROW_C
+
+
+BN_S_MP_SUB_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_READ_UNSIGNED_BIN_C
++--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_EXPTMOD_FAST_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_INIT_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MONTGOMERY_SETUP_C
++--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
++--->BN_MP_MONTGOMERY_REDUCE_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
++--->BN_MP_DR_SETUP_C
++--->BN_MP_DR_REDUCE_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
++--->BN_MP_REDUCE_2K_SETUP_C
+| +--->BN_MP_2EXPT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_GROW_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_2K_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| +--->BN_MP_2EXPT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_MULMOD_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_ABS_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2D_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_EXCH_C
+
+
+BN_MP_TO_UNSIGNED_BIN_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_SET_INT_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_MOD_D_C
++--->BN_MP_DIV_D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_SQR_C
++--->BN_MP_TOOM_SQR_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_KARATSUBA_SQR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| +--->BN_MP_ADD_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_CLEAR_C
++--->BN_FAST_S_MP_SQR_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_S_MP_SQR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_MULMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+
+
+BN_MP_DIV_2D_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_C
++--->BN_MP_MOD_2D_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
++--->BN_MP_RSHD_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
+
+
+BN_S_MP_ADD_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_FAST_S_MP_SQR_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_S_MP_MUL_DIGS_C
++--->BN_FAST_S_MP_MUL_DIGS_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_XOR_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_RADIX_SMAP_C
+
+
+BN_MP_DR_IS_MODULUS_C
+
+
+BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_2EXPT_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_GROW_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_MUL_2_C
+| +--->BN_MP_GROW_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_SUB_C
++--->BN_S_MP_ADD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_INIT_MULTI_C
++--->BN_MP_INIT_C
++--->BN_MP_CLEAR_C
+
+
+BN_S_MP_MUL_HIGH_DIGS_C
++--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_PRIME_NEXT_PRIME_C
++--->BN_MP_CMP_D_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_D_C
+| +--->BN_MP_DIV_D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_PRIME_MILLER_RABIN_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_CNT_LSB_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXPTMOD_C
+| | +--->BN_MP_INVMOD_C
+| | | +--->BN_FAST_MP_INVMOD_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | +--->BN_MP_ABS_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_INVMOD_SLOW_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | | +--->BN_MP_ABS_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | | +--->BN_MP_CLEAR_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_ABS_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_REDUCE_IS_2K_L_C
+| | +--->BN_S_MP_EXPTMOD_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_REDUCE_SETUP_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_L_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DR_IS_MODULUS_C
+| | +--->BN_MP_REDUCE_IS_2K_C
+| | | +--->BN_MP_REDUCE_2K_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_EXPTMOD_FAST_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_MONTGOMERY_SETUP_C
+| | | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_MONTGOMERY_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_DR_SETUP_C
+| | | +--->BN_MP_DR_REDUCE_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_REDUCE_2K_SETUP_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_REDUCE_2K_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | | | +--->BN_MP_2EXPT_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MULMOD_C
+| | | | +--->BN_MP_MUL_C
+| | | | | +--->BN_MP_TOOM_MUL_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MOD_2D_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | | +--->BN_MP_COPY_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_MUL_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_2_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_DIV_3_C
+| | | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_MOD_C
+| | | | | +--->BN_MP_DIV_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | | +--->BN_MP_MUL_2D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_LSHD_C
+| | | | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_C
+| | | | | | +--->BN_MP_SUB_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_ADD_C
+| | | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | | +--->BN_MP_GROW_C
+| | | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_MUL_D_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SQR_C
+| | | | +--->BN_MP_TOOM_SQR_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_SQR_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SQR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_SQRMOD_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_COUNT_BITS_C
+| | | | +--->BN_MP_ABS_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_SIGNED_BIN_SIZE_C
++--->BN_MP_UNSIGNED_BIN_SIZE_C
+| +--->BN_MP_COUNT_BITS_C
+
+
+BN_MP_INVMOD_SLOW_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_DIV_2_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_MP_CMP_D_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_LCM_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_GCD_C
+| +--->BN_MP_ABS_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_CNT_LSB_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_EXCH_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_DIV_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_SET_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_2K_L_C
++--->BN_MP_INIT_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_S_MP_ADD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_REVERSE_C
+
+
+BN_MP_PRIME_IS_DIVISIBLE_C
++--->BN_MP_MOD_D_C
+| +--->BN_MP_DIV_D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+
+
+BN_MP_SET_C
++--->BN_MP_ZERO_C
+
+
+BN_MP_GCD_C
++--->BN_MP_ABS_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CNT_LSB_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_EXCH_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_2K_SETUP_L_C
++--->BN_MP_INIT_C
++--->BN_MP_2EXPT_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_GROW_C
++--->BN_MP_COUNT_BITS_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_READ_RADIX_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_FAST_S_MP_MUL_HIGH_DIGS_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_FAST_MP_MONTGOMERY_REDUCE_C
++--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+
+
+BN_MP_DIV_D_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_DIV_3_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_2K_SETUP_C
++--->BN_MP_INIT_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_2EXPT_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_GROW_C
++--->BN_MP_CLEAR_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_INIT_SET_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
+
+
+BN_MP_REDUCE_2K_C
++--->BN_MP_INIT_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_S_MP_ADD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_ERROR_C
+
+
+BN_MP_EXPT_D_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+
+
+BN_S_MP_EXPTMOD_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_INIT_C
++--->BN_MP_CLEAR_C
++--->BN_MP_REDUCE_SETUP_C
+| +--->BN_MP_2EXPT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_D_C
+| +--->BN_MP_SET_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| | +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_2K_SETUP_L_C
+| +--->BN_MP_2EXPT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_GROW_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_REDUCE_2K_L_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_C
+| | +--->BN_MP_TOOM_MUL_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_KARATSUBA_MUL_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_MUL_DIGS_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_SQR_C
+| +--->BN_MP_TOOM_SQR_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_KARATSUBA_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| +--->BN_FAST_S_MP_SQR_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SQR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_EXCH_C
+
+
+BN_MP_ABS_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
+
+
+BN_MP_INIT_SET_INT_C
++--->BN_MP_INIT_C
++--->BN_MP_SET_INT_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_SUB_D_C
++--->BN_MP_GROW_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_TO_SIGNED_BIN_C
++--->BN_MP_TO_UNSIGNED_BIN_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_DIV_2_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_REDUCE_IS_2K_C
++--->BN_MP_REDUCE_2K_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_COUNT_BITS_C
+
+
+BN_MP_INIT_SIZE_C
++--->BN_MP_INIT_C
+
+
+BN_MP_DIV_C
++--->BN_MP_CMP_MAG_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ZERO_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_SET_C
++--->BN_MP_COUNT_BITS_C
++--->BN_MP_ABS_C
++--->BN_MP_MUL_2D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_INIT_C
++--->BN_MP_INIT_COPY_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
++--->BN_MP_RSHD_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CLEAR_C
+
+
+BN_MP_MONTGOMERY_REDUCE_C
++--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+
+
+BN_MP_MUL_2_C
++--->BN_MP_GROW_C
+
+
+BN_MP_UNSIGNED_BIN_SIZE_C
++--->BN_MP_COUNT_BITS_C
+
+
+BN_MP_ADDMOD_C
++--->BN_MP_INIT_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+
+
+BN_MP_ADD_C
++--->BN_S_MP_ADD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
+
+
+BN_MP_TO_SIGNED_BIN_N_C
++--->BN_MP_SIGNED_BIN_SIZE_C
+| +--->BN_MP_UNSIGNED_BIN_SIZE_C
+| | +--->BN_MP_COUNT_BITS_C
++--->BN_MP_TO_SIGNED_BIN_C
+| +--->BN_MP_TO_UNSIGNED_BIN_C
+| | +--->BN_MP_INIT_COPY_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_IS_2K_L_C
+
+
+BN_MP_RAND_C
++--->BN_MP_ZERO_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+
+
+BN_MP_CNT_LSB_C
+
+
+BN_MP_2EXPT_C
++--->BN_MP_ZERO_C
++--->BN_MP_GROW_C
+
+
+BN_MP_RSHD_C
++--->BN_MP_ZERO_C
+
+
+BN_MP_SHRINK_C
+
+
+BN_MP_TO_UNSIGNED_BIN_N_C
++--->BN_MP_UNSIGNED_BIN_SIZE_C
+| +--->BN_MP_COUNT_BITS_C
++--->BN_MP_TO_UNSIGNED_BIN_C
+| +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_REDUCE_C
++--->BN_MP_REDUCE_SETUP_C
+| +--->BN_MP_2EXPT_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2D_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_INIT_COPY_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_S_MP_MUL_HIGH_DIGS_C
+| +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_MOD_2D_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_S_MP_MUL_DIGS_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_D_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_MUL_2D_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_GROW_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
++--->BN_MP_CLAMP_C
+
+
+BN_MP_GET_INT_C
+
+
+BN_MP_JACOBI_C
++--->BN_MP_CMP_D_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_CNT_LSB_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_MOD_C
+| +--->BN_MP_DIV_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_SET_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_ABS_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_CLEAR_MULTI_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_MUL_C
++--->BN_MP_TOOM_MUL_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_ZERO_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
+| +--->BN_MP_MUL_2_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_3_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_KARATSUBA_MUL_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CMP_MAG_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| +--->BN_MP_CLEAR_C
++--->BN_FAST_S_MP_MUL_DIGS_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_S_MP_MUL_DIGS_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_EXTEUCLID_C
++--->BN_MP_INIT_MULTI_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_SET_C
+| +--->BN_MP_ZERO_C
++--->BN_MP_COPY_C
+| +--->BN_MP_GROW_C
++--->BN_MP_DIV_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_KARATSUBA_MUL_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
++--->BN_MP_NEG_C
++--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_DR_REDUCE_C
++--->BN_MP_GROW_C
++--->BN_MP_CLAMP_C
++--->BN_MP_CMP_MAG_C
++--->BN_S_MP_SUB_C
+
+
+BN_MP_FREAD_C
++--->BN_MP_ZERO_C
++--->BN_MP_MUL_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_ADD_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_SUB_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CMP_D_C
+
+
+BN_MP_REDUCE_SETUP_C
++--->BN_MP_2EXPT_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_GROW_C
++--->BN_MP_DIV_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_INIT_MULTI_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_SET_C
+| +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_ABS_C
+| +--->BN_MP_MUL_2D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CMP_C
+| +--->BN_MP_SUB_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_ADD_C
+| | +--->BN_S_MP_ADD_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SUB_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| +--->BN_MP_DIV_2D_C
+| | +--->BN_MP_INIT_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_RSHD_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_EXCH_C
+| +--->BN_MP_CLEAR_MULTI_C
+| | +--->BN_MP_CLEAR_C
+| +--->BN_MP_INIT_SIZE_C
+| | +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_C
+| +--->BN_MP_INIT_COPY_C
+| +--->BN_MP_LSHD_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_MUL_D_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+
+
+BN_MP_MONTGOMERY_SETUP_C
+
+
+BN_MP_KARATSUBA_MUL_C
++--->BN_MP_MUL_C
+| +--->BN_MP_TOOM_MUL_C
+| | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_MOD_2D_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MUL_2_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_SUB_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_2_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_2D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MUL_D_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_DIV_3_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_INIT_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_LSHD_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_FAST_S_MP_MUL_DIGS_C
+| | +--->BN_MP_GROW_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_S_MP_MUL_DIGS_C
+| | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_INIT_C
+| | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
+| | +--->BN_MP_CLEAR_C
++--->BN_MP_INIT_SIZE_C
+| +--->BN_MP_INIT_C
++--->BN_MP_CLAMP_C
++--->BN_MP_SUB_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_ADD_C
+| +--->BN_S_MP_ADD_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_CMP_MAG_C
+| +--->BN_S_MP_SUB_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_LSHD_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_RSHD_C
+| | +--->BN_MP_ZERO_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_LSHD_C
++--->BN_MP_GROW_C
++--->BN_MP_RSHD_C
+| +--->BN_MP_ZERO_C
+
+
+BN_MP_PRIME_MILLER_RABIN_C
++--->BN_MP_CMP_D_C
++--->BN_MP_INIT_COPY_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
++--->BN_MP_SUB_D_C
+| +--->BN_MP_GROW_C
+| +--->BN_MP_ADD_D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLAMP_C
++--->BN_MP_CNT_LSB_C
++--->BN_MP_DIV_2D_C
+| +--->BN_MP_COPY_C
+| | +--->BN_MP_GROW_C
+| +--->BN_MP_ZERO_C
+| +--->BN_MP_MOD_2D_C
+| | +--->BN_MP_CLAMP_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_RSHD_C
+| +--->BN_MP_CLAMP_C
+| +--->BN_MP_EXCH_C
++--->BN_MP_EXPTMOD_C
+| +--->BN_MP_INVMOD_C
+| | +--->BN_FAST_MP_INVMOD_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_ABS_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_INVMOD_SLOW_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_COUNT_BITS_C
+| | | | | +--->BN_MP_ABS_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_CLEAR_MULTI_C
+| | | | | | +--->BN_MP_CLEAR_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_CLEAR_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_ABS_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| +--->BN_MP_CLEAR_MULTI_C
+| +--->BN_MP_REDUCE_IS_2K_L_C
+| +--->BN_S_MP_EXPTMOD_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_REDUCE_SETUP_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_S_MP_MUL_HIGH_DIGS_C
+| | | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_FAST_S_MP_MUL_HIGH_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_SETUP_L_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_L_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_EXCH_C
+| +--->BN_MP_DR_IS_MODULUS_C
+| +--->BN_MP_REDUCE_IS_2K_C
+| | +--->BN_MP_REDUCE_2K_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_COUNT_BITS_C
+| +--->BN_MP_EXPTMOD_FAST_C
+| | +--->BN_MP_COUNT_BITS_C
+| | +--->BN_MP_MONTGOMERY_SETUP_C
+| | +--->BN_FAST_MP_MONTGOMERY_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_MONTGOMERY_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_DR_SETUP_C
+| | +--->BN_MP_DR_REDUCE_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | +--->BN_MP_REDUCE_2K_SETUP_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_REDUCE_2K_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+| | | +--->BN_MP_2EXPT_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_SET_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_MULMOD_C
+| | | +--->BN_MP_MUL_C
+| | | | +--->BN_MP_TOOM_MUL_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_MOD_2D_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | | +--->BN_MP_COPY_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_MUL_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_2_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_DIV_3_C
+| | | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CMP_MAG_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_MUL_DIGS_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_MOD_C
+| | | | +--->BN_MP_DIV_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_MP_COPY_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_INIT_MULTI_C
+| | | | | +--->BN_MP_SET_C
+| | | | | +--->BN_MP_MUL_2D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_LSHD_C
+| | | | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_C
+| | | | | +--->BN_MP_SUB_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_ADD_C
+| | | | | | +--->BN_S_MP_ADD_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | | +--->BN_S_MP_SUB_C
+| | | | | | | +--->BN_MP_GROW_C
+| | | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_MUL_D_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_SET_C
+| | | +--->BN_MP_ZERO_C
+| | +--->BN_MP_MOD_C
+| | | +--->BN_MP_DIV_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_COPY_C
+| | | +--->BN_MP_GROW_C
+| | +--->BN_MP_SQR_C
+| | | +--->BN_MP_TOOM_SQR_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | +--->BN_FAST_S_MP_SQR_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_SQR_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_MUL_C
+| | | +--->BN_MP_TOOM_MUL_C
+| | | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_MOD_2D_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_MUL_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_2_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_2D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_MUL_D_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_DIV_3_C
+| | | | | +--->BN_MP_INIT_SIZE_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_KARATSUBA_MUL_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_SUB_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_ADD_C
+| | | | | +--->BN_S_MP_ADD_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CMP_MAG_C
+| | | | | +--->BN_S_MP_SUB_C
+| | | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_FAST_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_S_MP_MUL_DIGS_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_CMP_C
+| +--->BN_MP_CMP_MAG_C
++--->BN_MP_SQRMOD_C
+| +--->BN_MP_SQR_C
+| | +--->BN_MP_TOOM_SQR_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_MOD_2D_C
+| | | | +--->BN_MP_ZERO_C
+| | | | +--->BN_MP_COPY_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_MUL_2_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_2_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_DIV_3_C
+| | | | +--->BN_MP_INIT_SIZE_C
+| | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_MP_EXCH_C
+| | | | +--->BN_MP_CLEAR_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | | +--->BN_MP_CLEAR_C
+| | +--->BN_MP_KARATSUBA_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_MP_CMP_MAG_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLEAR_C
+| | +--->BN_FAST_S_MP_SQR_C
+| | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_S_MP_SQR_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_C
+| +--->BN_MP_CLEAR_C
+| +--->BN_MP_MOD_C
+| | +--->BN_MP_DIV_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_MP_COPY_C
+| | | | +--->BN_MP_GROW_C
+| | | +--->BN_MP_ZERO_C
+| | | +--->BN_MP_INIT_MULTI_C
+| | | +--->BN_MP_SET_C
+| | | +--->BN_MP_COUNT_BITS_C
+| | | +--->BN_MP_ABS_C
+| | | +--->BN_MP_MUL_2D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_LSHD_C
+| | | | | +--->BN_MP_RSHD_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_SUB_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_ADD_C
+| | | | +--->BN_S_MP_ADD_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | | +--->BN_S_MP_SUB_C
+| | | | | +--->BN_MP_GROW_C
+| | | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_EXCH_C
+| | | +--->BN_MP_CLEAR_MULTI_C
+| | | +--->BN_MP_INIT_SIZE_C
+| | | +--->BN_MP_LSHD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_RSHD_C
+| | | +--->BN_MP_MUL_D_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_ADD_C
+| | | +--->BN_S_MP_ADD_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | | +--->BN_MP_CMP_MAG_C
+| | | +--->BN_S_MP_SUB_C
+| | | | +--->BN_MP_GROW_C
+| | | | +--->BN_MP_CLAMP_C
+| | +--->BN_MP_EXCH_C
++--->BN_MP_CLEAR_C
+
+
+BN_MP_DR_SETUP_C
+
+
+BN_MP_CMP_MAG_C
+
+
diff --git a/source4/heimdal/lib/hcrypto/libtommath/libtommath.dsp b/source4/heimdal/lib/hcrypto/libtommath/libtommath.dsp
new file mode 100644
index 0000000000..6b8908f07c
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/libtommath.dsp
@@ -0,0 +1,572 @@
+# Microsoft Developer Studio Project File - Name="libtommath" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=libtommath - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libtommath.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libtommath.mak" CFG="libtommath - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libtommath - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "libtommath - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "libtommath"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libtommath - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Release\tommath.lib"
+
+!ELSEIF "$(CFG)" == "libtommath - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"Debug\tommath.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "libtommath - Win32 Release"
+# Name "libtommath - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\bn_error.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_fast_mp_invmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_fast_mp_montgomery_reduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_fast_s_mp_mul_digs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_fast_s_mp_mul_high_digs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_fast_s_mp_sqr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_2expt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_abs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_add.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_add_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_addmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_and.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_clamp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_clear.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_clear_multi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_cmp.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_cmp_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_cmp_mag.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_cnt_lsb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_copy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_count_bits.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_div.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_div_2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_div_2d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_div_3.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_div_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_dr_is_modulus.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_dr_reduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_dr_setup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_exch.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_expt_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_exptmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_exptmod_fast.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_exteuclid.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_fread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_fwrite.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_gcd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_get_int.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_grow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init_copy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init_multi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init_set.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init_set_int.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_init_size.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_invmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_invmod_slow.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_is_square.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_jacobi.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_karatsuba_mul.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_karatsuba_sqr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_lcm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_lshd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mod_2d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mod_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_montgomery_calc_normalization.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_montgomery_reduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_montgomery_setup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mul.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mul_2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mul_2d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mul_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_mulmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_n_root.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_neg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_or.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_fermat.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_is_divisible.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_is_prime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_miller_rabin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_next_prime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_rabin_miller_trials.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_prime_random_ex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_radix_size.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_radix_smap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_rand.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_read_radix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_read_signed_bin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_read_unsigned_bin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_2k.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_2k_l.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_2k_setup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_2k_setup_l.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_is_2k.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_is_2k_l.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_reduce_setup.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_rshd.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_set.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_set_int.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_shrink.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_signed_bin_size.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_sqr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_sqrmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_sqrt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_sub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_sub_d.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_submod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_to_signed_bin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_to_signed_bin_n.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_to_unsigned_bin.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_to_unsigned_bin_n.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_toom_mul.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_toom_sqr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_toradix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_toradix_n.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_unsigned_bin_size.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_xor.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_mp_zero.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_prime_tab.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_reverse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_add.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_exptmod.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_mul_digs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_mul_high_digs.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_sqr.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bn_s_mp_sub.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bncore.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\tommath.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\tommath_class.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\tommath_superclass.h
+# End Source File
+# End Target
+# End Project
diff --git a/source4/heimdal/lib/hcrypto/libtommath/mtest/logtab.h b/source4/heimdal/lib/hcrypto/libtommath/mtest/logtab.h
new file mode 100644
index 0000000000..bbefaefc04
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/mtest/logtab.h
@@ -0,0 +1,24 @@
+const float s_logv_2[] = {
+ 0.000000000, 0.000000000, 1.000000000, 0.630929754, /* 0 1 2 3 */
+ 0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4 5 6 7 */
+ 0.333333333, 0.315464877, 0.301029996, 0.289064826, /* 8 9 10 11 */
+ 0.278942946, 0.270238154, 0.262649535, 0.255958025, /* 12 13 14 15 */
+ 0.250000000, 0.244650542, 0.239812467, 0.235408913, /* 16 17 18 19 */
+ 0.231378213, 0.227670249, 0.224243824, 0.221064729, /* 20 21 22 23 */
+ 0.218104292, 0.215338279, 0.212746054, 0.210309918, /* 24 25 26 27 */
+ 0.208014598, 0.205846832, 0.203795047, 0.201849087, /* 28 29 30 31 */
+ 0.200000000, 0.198239863, 0.196561632, 0.194959022, /* 32 33 34 35 */
+ 0.193426404, 0.191958720, 0.190551412, 0.189200360, /* 36 37 38 39 */
+ 0.187901825, 0.186652411, 0.185449023, 0.184288833, /* 40 41 42 43 */
+ 0.183169251, 0.182087900, 0.181042597, 0.180031327, /* 44 45 46 47 */
+ 0.179052232, 0.178103594, 0.177183820, 0.176291434, /* 48 49 50 51 */
+ 0.175425064, 0.174583430, 0.173765343, 0.172969690, /* 52 53 54 55 */
+ 0.172195434, 0.171441601, 0.170707280, 0.169991616, /* 56 57 58 59 */
+ 0.169293808, 0.168613099, 0.167948779, 0.167300179, /* 60 61 62 63 */
+ 0.166666667
+};
+
+
+/* $Source: /cvs/libtom/libtommath/mtest/logtab.h,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/05/05 14:38:47 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-config.h b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-config.h
new file mode 100644
index 0000000000..6049c25ba7
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-config.h
@@ -0,0 +1,90 @@
+/* Default configuration for MPI library */
+/* $Id: mpi-config.h,v 1.2 2005/05/05 14:38:47 tom Exp $ */
+
+#ifndef MPI_CONFIG_H_
+#define MPI_CONFIG_H_
+
+/*
+ For boolean options,
+ 0 = no
+ 1 = yes
+
+ Other options are documented individually.
+
+ */
+
+#ifndef MP_IOFUNC
+#define MP_IOFUNC 0 /* include mp_print() ? */
+#endif
+
+#ifndef MP_MODARITH
+#define MP_MODARITH 1 /* include modular arithmetic ? */
+#endif
+
+#ifndef MP_NUMTH
+#define MP_NUMTH 1 /* include number theoretic functions? */
+#endif
+
+#ifndef MP_LOGTAB
+#define MP_LOGTAB 1 /* use table of logs instead of log()? */
+#endif
+
+#ifndef MP_MEMSET
+#define MP_MEMSET 1 /* use memset() to zero buffers? */
+#endif
+
+#ifndef MP_MEMCPY
+#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */
+#endif
+
+#ifndef MP_CRYPTO
+#define MP_CRYPTO 1 /* erase memory on free? */
+#endif
+
+#ifndef MP_ARGCHK
+/*
+ 0 = no parameter checks
+ 1 = runtime checks, continue execution and return an error to caller
+ 2 = assertions; dump core on parameter errors
+ */
+#define MP_ARGCHK 2 /* how to check input arguments */
+#endif
+
+#ifndef MP_DEBUG
+#define MP_DEBUG 0 /* print diagnostic output? */
+#endif
+
+#ifndef MP_DEFPREC
+#define MP_DEFPREC 64 /* default precision, in digits */
+#endif
+
+#ifndef MP_MACRO
+#define MP_MACRO 1 /* use macros for frequent calls? */
+#endif
+
+#ifndef MP_SQUARE
+#define MP_SQUARE 1 /* use separate squaring code? */
+#endif
+
+#ifndef MP_PTAB_SIZE
+/*
+ When building mpprime.c, we build in a table of small prime
+ values to use for primality testing. The more you include,
+ the more space they take up. See primes.c for the possible
+ values (currently 16, 32, 64, 128, 256, and 6542)
+ */
+#define MP_PTAB_SIZE 128 /* how many built-in primes? */
+#endif
+
+#ifndef MP_COMPAT_MACROS
+#define MP_COMPAT_MACROS 1 /* define compatibility macros? */
+#endif
+
+#endif /* ifndef MPI_CONFIG_H_ */
+
+
+/* crc==3287762869, version==2, Sat Feb 02 06:43:53 2002 */
+
+/* $Source: /cvs/libtom/libtommath/mtest/mpi-config.h,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/05/05 14:38:47 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-types.h b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-types.h
new file mode 100644
index 0000000000..026de589dd
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi-types.h
@@ -0,0 +1,20 @@
+/* Type definitions generated by 'types.pl' */
+typedef char mp_sign;
+typedef unsigned short mp_digit; /* 2 byte type */
+typedef unsigned int mp_word; /* 4 byte type */
+typedef unsigned int mp_size;
+typedef int mp_err;
+
+#define MP_DIGIT_BIT (CHAR_BIT*sizeof(mp_digit))
+#define MP_DIGIT_MAX USHRT_MAX
+#define MP_WORD_BIT (CHAR_BIT*sizeof(mp_word))
+#define MP_WORD_MAX UINT_MAX
+
+#define MP_DIGIT_SIZE 2
+#define DIGIT_FMT "%04X"
+#define RADIX (MP_DIGIT_MAX+1)
+
+
+/* $Source: /cvs/libtom/libtommath/mtest/mpi-types.h,v $ */
+/* $Revision: 1.2 $ */
+/* $Date: 2005/05/05 14:38:47 $ */
diff --git a/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.c b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.c
new file mode 100644
index 0000000000..7c712dd62d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.c
@@ -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
index 0000000000..66ae873111
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/mtest/mpi.h
@@ -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
index 0000000000..bdfe6127af
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/mtest/mtest.c
@@ -0,0 +1,308 @@
+/* makes a bignum test harness with NUM tests per operation
+ *
+ * the output is made in the following format [one parameter per line]
+
+operation
+operand1
+operand2
+[... operandN]
+result1
+result2
+[... resultN]
+
+So for example "a * b mod n" would be
+
+mulmod
+a
+b
+n
+a*b mod n
+
+e.g. if a=3, b=4 n=11 then
+
+mulmod
+3
+4
+11
+1
+
+ */
+
+#ifdef MP_8BIT
+#define THE_MASK 127
+#else
+#define THE_MASK 32767
+#endif
+
+#include <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
index 0000000000..7414dbb276
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/pics/design_process.sxd
Binary files 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
index 0000000000..4a0c012d56
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/pics/design_process.tif
Binary files 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
index 0000000000..6518404d5f
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.sxd
Binary files 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
index 0000000000..cb06e8edf1
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/pics/expt_state.tif
Binary files differ
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/makefile b/source4/heimdal/lib/hcrypto/libtommath/pics/makefile
new file mode 100644
index 0000000000..3ecb02ff73
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/pics/makefile
@@ -0,0 +1,35 @@
+# makes the images... yeah
+
+default: pses
+
+design_process.ps: design_process.tif
+ tiff2ps -s -e design_process.tif > design_process.ps
+
+sliding_window.ps: sliding_window.tif
+ tiff2ps -s -e sliding_window.tif > sliding_window.ps
+
+expt_state.ps: expt_state.tif
+ tiff2ps -s -e expt_state.tif > expt_state.ps
+
+primality.ps: primality.tif
+ tiff2ps -s -e primality.tif > primality.ps
+
+design_process.pdf: design_process.ps
+ epstopdf design_process.ps
+
+sliding_window.pdf: sliding_window.ps
+ epstopdf sliding_window.ps
+
+expt_state.pdf: expt_state.ps
+ epstopdf expt_state.ps
+
+primality.pdf: primality.ps
+ epstopdf primality.ps
+
+
+pses: sliding_window.ps expt_state.ps primality.ps design_process.ps
+pdfes: sliding_window.pdf expt_state.pdf primality.pdf design_process.pdf
+
+clean:
+ rm -rf *.ps *.pdf .xvpics
+ \ No newline at end of file
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pics/primality.tif b/source4/heimdal/lib/hcrypto/libtommath/pics/primality.tif
new file mode 100644
index 0000000000..76d6be3fac
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/pics/primality.tif
Binary files 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
index 0000000000..b9eb9a032d
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/pics/radix.sxd
Binary files 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
index 0000000000..91e7c0d9f4
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.sxd
Binary files 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
index 0000000000..bb4cb96ebf
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/pics/sliding_window.tif
Binary files differ
diff --git a/source4/heimdal/lib/hcrypto/libtommath/pretty.build b/source4/heimdal/lib/hcrypto/libtommath/pretty.build
new file mode 100644
index 0000000000..a708b8af22
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/pretty.build
@@ -0,0 +1,66 @@
+#!/bin/perl -w
+#
+# Cute little builder for perl
+# Total waste of development time...
+#
+# This will build all the object files and then the archive .a file
+# requires GCC, GNU make and a sense of humour.
+#
+# Tom St Denis
+use strict;
+
+my $count = 0;
+my $starttime = time;
+my $rate = 0;
+print "Scanning for source files...\n";
+foreach my $filename (glob "*.c") {
+ ++$count;
+}
+print "Source files to build: $count\nBuilding...\n";
+my $i = 0;
+my $lines = 0;
+my $filesbuilt = 0;
+foreach my $filename (glob "*.c") {
+ printf("Building %3.2f%%, ", (++$i/$count)*100.0);
+ if ($i % 4 == 0) { print "/, "; }
+ if ($i % 4 == 1) { print "-, "; }
+ if ($i % 4 == 2) { print "\\, "; }
+ if ($i % 4 == 3) { print "|, "; }
+ if ($rate > 0) {
+ my $tleft = ($count - $i) / $rate;
+ my $tsec = $tleft%60;
+ my $tmin = ($tleft/60)%60;
+ my $thour = ($tleft/3600)%60;
+ printf("%2d:%02d:%02d left, ", $thour, $tmin, $tsec);
+ }
+ my $cnt = ($i/$count)*30.0;
+ my $x = 0;
+ print "[";
+ for (; $x < $cnt; $x++) { print "#"; }
+ for (; $x < 30; $x++) { print " "; }
+ print "]\r";
+ my $tmp = $filename;
+ $tmp =~ s/\.c/".o"/ge;
+ if (open(SRC, "<$tmp")) {
+ close SRC;
+ } else {
+ !system("make $tmp > /dev/null 2>/dev/null") or die "\nERROR: Failed to make $tmp!!!\n";
+ open( SRC, "<$filename" ) or die "Couldn't open $filename for reading: $!";
+ ++$lines while (<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
index 0000000000..a780e759d6
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/tombc/grammar.txt
@@ -0,0 +1,35 @@
+program := program statement | statement | empty
+statement := { statement } |
+ identifier = numexpression; |
+ identifier[numexpression] = numexpression; |
+ function(expressionlist); |
+ for (identifer = numexpression; numexpression; identifier = numexpression) { statement } |
+ while (numexpression) { statement } |
+ if (numexpresion) { statement } elif |
+ break; |
+ continue;
+
+elif := else statement | empty
+function := abs | countbits | exptmod | jacobi | print | isprime | nextprime | issquare | readinteger | exit
+expressionlist := expressionlist, expression | expression
+
+// LR(1) !!!?
+expression := string | numexpression
+numexpression := cmpexpr && cmpexpr | cmpexpr \|\| cmpexpr | cmpexpr
+cmpexpr := boolexpr < boolexpr | boolexpr > boolexpr | boolexpr == boolexpr |
+ boolexpr <= boolexpr | boolexpr >= boolexpr | boolexpr
+boolexpr := shiftexpr & shiftexpr | shiftexpr ^ shiftexpr | shiftexpr \| shiftexpr | shiftexpr
+shiftexpr := addsubexpr << addsubexpr | addsubexpr >> addsubexpr | addsubexpr
+addsubexpr := mulexpr + mulexpr | mulexpr - mulexpr | mulexpr
+mulexpr := expr * expr | expr / expr | expr % expr | expr
+expr := -nexpr | nexpr
+nexpr := integer | identifier | ( numexpression ) | identifier[numexpression]
+
+identifier := identifer digits | identifier alpha | alpha
+alpha := a ... z | A ... Z
+integer := hexnumber | digits
+hexnumber := 0xhexdigits
+hexdigits := hexdigits hexdigit | hexdigit
+hexdigit := 0 ... 9 | a ... f | A ... F
+digits := digits digit | digit
+digit := 0 ... 9
diff --git a/source4/heimdal/lib/hcrypto/libtommath/tommath.h b/source4/heimdal/lib/hcrypto/libtommath/tommath.h
new file mode 100644
index 0000000000..426207a298
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/tommath.h
@@ -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
index 0000000000..fa95a0277a
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/tommath_class.h
@@ -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
index 0000000000..2fdebe6838
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/libtommath/tommath_superclass.h
@@ -0,0 +1,76 @@
+/* super class file for PK algos */
+
+/* default ... include all MPI */
+#define LTM_ALL
+
+/* RSA only (does not support DH/DSA/ECC) */
+/* #define SC_RSA_1 */
+
+/* For reference.... On an Athlon64 optimizing for speed...
+
+ LTM's mpi.o with all functions [striped] is 142KiB in size.
+
+*/
+
+/* Works for RSA only, mpi.o is 68KiB */
+#ifdef SC_RSA_1
+ #define BN_MP_SHRINK_C
+ #define BN_MP_LCM_C
+ #define BN_MP_PRIME_RANDOM_EX_C
+ #define BN_MP_INVMOD_C
+ #define BN_MP_GCD_C
+ #define BN_MP_MOD_C
+ #define BN_MP_MULMOD_C
+ #define BN_MP_ADDMOD_C
+ #define BN_MP_EXPTMOD_C
+ #define BN_MP_SET_INT_C
+ #define BN_MP_INIT_MULTI_C
+ #define BN_MP_CLEAR_MULTI_C
+ #define BN_MP_UNSIGNED_BIN_SIZE_C
+ #define BN_MP_TO_UNSIGNED_BIN_C
+ #define BN_MP_MOD_D_C
+ #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+ #define BN_REVERSE_C
+ #define BN_PRIME_TAB_C
+
+ /* other modifiers */
+ #define BN_MP_DIV_SMALL /* Slower division, not critical */
+
+ /* here we are on the last pass so we turn things off. The functions classes are still there
+ * but we remove them specifically from the build. This also invokes tweaks in functions
+ * like removing support for even moduli, etc...
+ */
+#ifdef LTM_LAST
+ #undef BN_MP_TOOM_MUL_C
+ #undef BN_MP_TOOM_SQR_C
+ #undef BN_MP_KARATSUBA_MUL_C
+ #undef BN_MP_KARATSUBA_SQR_C
+ #undef BN_MP_REDUCE_C
+ #undef BN_MP_REDUCE_SETUP_C
+ #undef BN_MP_DR_IS_MODULUS_C
+ #undef BN_MP_DR_SETUP_C
+ #undef BN_MP_DR_REDUCE_C
+ #undef BN_MP_REDUCE_IS_2K_C
+ #undef BN_MP_REDUCE_2K_SETUP_C
+ #undef BN_MP_REDUCE_2K_C
+ #undef BN_S_MP_EXPTMOD_C
+ #undef BN_MP_DIV_3_C
+ #undef BN_S_MP_MUL_HIGH_DIGS_C
+ #undef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+ #undef BN_FAST_MP_INVMOD_C
+
+ /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
+ * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines]
+ * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
+ * trouble.
+ */
+ #undef BN_S_MP_MUL_DIGS_C
+ #undef BN_S_MP_SQR_C
+ #undef BN_MP_MONTGOMERY_REDUCE_C
+#endif
+
+#endif
+
+/* $Source: /cvs/libtom/libtommath/tommath_superclass.h,v $ */
+/* $Revision: 1.3 $ */
+/* $Date: 2005/05/14 13:29:17 $ */
diff --git a/source4/heimdal/lib/hcrypto/md4.c b/source4/heimdal/lib/hcrypto/md4.c
index 435e662a42..1a9f77fed2 100644
--- a/source4/heimdal/lib/hcrypto/md4.c
+++ b/source4/heimdal/lib/hcrypto/md4.c
@@ -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
diff --git a/source4/heimdal/lib/hcrypto/md5.c b/source4/heimdal/lib/hcrypto/md5.c
index f99078737b..b35c76e293 100644
--- a/source4/heimdal/lib/hcrypto/md5.c
+++ b/source4/heimdal/lib/hcrypto/md5.c
@@ -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
diff --git a/source4/heimdal/lib/hcrypto/rand-fortuna.c b/source4/heimdal/lib/hcrypto/rand-fortuna.c
index c81eb9e2d7..11027b46cf 100644
--- a/source4/heimdal/lib/hcrypto/rand-fortuna.c
+++ b/source4/heimdal/lib/hcrypto/rand-fortuna.c
@@ -34,6 +34,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <rand.h>
+#include <heim_threads.h>
#ifdef KRB5
#include <krb5-types.h>
@@ -442,10 +443,20 @@ static int have_entropy;
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 = {
diff --git a/source4/heimdal/lib/hcrypto/rand-unix.c b/source4/heimdal/lib/hcrypto/rand-unix.c
index 63dc97fbfa..c52155baaa 100644
--- a/source4/heimdal/lib/hcrypto/rand-unix.c
+++ b/source4/heimdal/lib/hcrypto/rand-unix.c
@@ -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",
diff --git a/source4/heimdal/lib/hcrypto/rand.c b/source4/heimdal/lib/hcrypto/rand.c
index d360ffcab4..d5c1f687b9 100644
--- a/source4/heimdal/lib/hcrypto/rand.c
+++ b/source4/heimdal/lib/hcrypto/rand.c
@@ -46,6 +46,10 @@
#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;
diff --git a/source4/heimdal/lib/hcrypto/rand.h b/source4/heimdal/lib/hcrypto/rand.h
index f4e2485166..590bd8cf1a 100644
--- a/source4/heimdal/lib/hcrypto/rand.h
+++ b/source4/heimdal/lib/hcrypto/rand.h
@@ -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 */
diff --git a/source4/heimdal/lib/hcrypto/randi.h b/source4/heimdal/lib/hcrypto/randi.h
index a6d921413a..fe021a80ec 100644
--- a/source4/heimdal/lib/hcrypto/randi.h
+++ b/source4/heimdal/lib/hcrypto/randi.h
@@ -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 */
diff --git a/source4/heimdal/lib/hcrypto/rijndael-alg-fst.c b/source4/heimdal/lib/hcrypto/rijndael-alg-fst.c
index 9a7f0fd3d6..bf335afd9f 100644
--- a/source4/heimdal/lib/hcrypto/rijndael-alg-fst.c
+++ b/source4/heimdal/lib/hcrypto/rijndael-alg-fst.c
@@ -38,11 +38,6 @@
#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 */
diff --git a/source4/heimdal/lib/hcrypto/rsa-imath.c b/source4/heimdal/lib/hcrypto/rsa-imath.c
index a2b9d2a678..23d5352700 100644
--- a/source4/heimdal/lib/hcrypto/rsa-imath.c
+++ b/source4/heimdal/lib/hcrypto/rsa-imath.c
@@ -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
index 0000000000..ad3686e403
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/rsa-ltm.c
@@ -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;
+}
diff --git a/source4/heimdal/lib/hcrypto/rsa.c b/source4/heimdal/lib/hcrypto/rsa.c
index 6a883454a3..a6e09fe283 100644
--- a/source4/heimdal/lib/hcrypto/rsa.c
+++ b/source4/heimdal/lib/hcrypto/rsa.c
@@ -38,8 +38,12 @@
#include <krb5-types.h>
#include <rfc2459_asn1.h>
+#include <der.h>
+
#include <rsa.h>
+#include "common.h"
+
#include <roken.h>
/**
@@ -48,6 +52,20 @@
* 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);
diff --git a/source4/heimdal/lib/hcrypto/rsa.h b/source4/heimdal/lib/hcrypto/rsa.h
index 9354aaaa48..3fd805fcf0 100644
--- a/source4/heimdal/lib/hcrypto/rsa.h
+++ b/source4/heimdal/lib/hcrypto/rsa.h
@@ -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 *);
diff --git a/source4/heimdal/lib/hcrypto/sha.c b/source4/heimdal/lib/hcrypto/sha.c
index 062f70509c..9c8b39e241 100644
--- a/source4/heimdal/lib/hcrypto/sha.c
+++ b/source4/heimdal/lib/hcrypto/sha.c
@@ -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
diff --git a/source4/heimdal/lib/hcrypto/sha256.c b/source4/heimdal/lib/hcrypto/sha256.c
index baa87d15ff..5e601bb358 100644
--- a/source4/heimdal/lib/hcrypto/sha256.c
+++ b/source4/heimdal/lib/hcrypto/sha256.c
@@ -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
diff --git a/source4/heimdal/lib/hcrypto/ui.c b/source4/heimdal/lib/hcrypto/ui.c
index f6f8a1ffe2..e32bb9a0be 100644
--- a/source4/heimdal/lib/hcrypto/ui.c
+++ b/source4/heimdal/lib/hcrypto/ui.c
@@ -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
index 0000000000..3ed358df66
--- /dev/null
+++ b/source4/heimdal/lib/hcrypto/validate.c
@@ -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();
+}