aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-03-29 09:46:10 -0400
committerJack Lloyd <[email protected]>2017-03-29 09:46:10 -0400
commit122e2f9cf62773238c4910a26dc93df2c9c2dfe5 (patch)
tree09b8fe71d8eecb8578a8c43b24017ad4ca649800 /src/lib
parent46af43636dbd39aa2eb9f99c37a900275c08c9e9 (diff)
parent3a2bdcf10e98ecdfb9bb4943cb09d5baf7bf6ba1 (diff)
Merge GH #946 Expose multiple precision integers in C interface
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ffi/ffi.cpp387
-rw-r--r--src/lib/ffi/ffi.h120
-rw-r--r--src/lib/ffi/info.txt3
3 files changed, 500 insertions, 10 deletions
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 9c5b837fb..75b10502c 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -1,5 +1,5 @@
/*
-* (C) 2015 Jack Lloyd
+* (C) 2015,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -21,6 +21,10 @@
#include <botan/mem_ops.h>
#include <botan/x509_key.h>
#include <botan/pk_algs.h>
+#include <botan/bigint.h>
+#include <botan/reducer.h>
+#include <botan/numthry.h>
+#include <botan/divide.h>
#include <cstring>
#include <memory>
@@ -94,7 +98,7 @@ void log_exception(const char* func_name, const char* what)
int ffi_error_exception_thrown(const char* exn)
{
- printf("exception %s\n", exn);
+ fprintf(stderr, "exception %s\n", exn);
return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
@@ -108,6 +112,16 @@ T& safe_get(botan_struct<T,M>* p)
throw FFI_Error("Invalid object pointer");
}
+template<typename T, uint32_t M>
+const T& safe_get(const botan_struct<T,M>* p)
+ {
+ if(!p)
+ throw FFI_Error("Null pointer argument");
+ if(const T* t = p->get())
+ return *t;
+ throw FFI_Error("Invalid object pointer");
+ }
+
template<typename T, uint32_t M, typename F>
int apply_fn(botan_struct<T, M>* o, const char* func_name, F func)
{
@@ -167,6 +181,13 @@ inline int write_str_output(char out[], size_t* out_len, const std::string& str)
return write_str_output(reinterpret_cast<uint8_t*>(out), out_len, str);
}
+inline int write_str_output(char out[], size_t* out_len, const std::vector<uint8_t>& str_vec)
+ {
+ return write_output(reinterpret_cast<uint8_t*>(out), out_len,
+ reinterpret_cast<const uint8_t*>(str_vec.data()),
+ str_vec.size());
+ }
+
#define BOTAN_FFI_DO(T, obj, param, block) apply_fn(obj, BOTAN_CURRENT_FUNCTION, [=](T& param) -> int { do { block } while(0); return 0; })
}
@@ -183,6 +204,7 @@ struct botan_cipher_struct : public botan_struct<Botan::Cipher_Mode, 0xB4A2BF9C>
};
BOTAN_FFI_DECLARE_STRUCT(botan_rng_struct, Botan::RandomNumberGenerator, 0x4901F9C1);
+BOTAN_FFI_DECLARE_STRUCT(botan_mp_struct, Botan::BigInt, 0xC828B9D2);
BOTAN_FFI_DECLARE_STRUCT(botan_hash_struct, Botan::HashFunction, 0x1F0A4F84);
BOTAN_FFI_DECLARE_STRUCT(botan_mac_struct, Botan::MessageAuthenticationCode, 0xA06E8FC1);
BOTAN_FFI_DECLARE_STRUCT(botan_pubkey_struct, Botan::Public_Key, 0x2C286519);
@@ -195,6 +217,7 @@ BOTAN_FFI_DECLARE_STRUCT(botan_pk_op_ka_struct, Botan::PK_Key_Agreement, 0x2939C
BOTAN_FFI_DECLARE_STRUCT(botan_x509_cert_struct, Botan::X509_Certificate, 0x8F628937);
+
#if defined(BOTAN_HAS_TLS)
BOTAN_FFI_DECLARE_STRUCT(botan_tls_channel_struct, Botan::TLS::Channel, 0x0212FE99);
#endif
@@ -301,6 +324,203 @@ int botan_rng_reseed(botan_rng_t rng, size_t bits)
return BOTAN_FFI_DO(Botan::RandomNumberGenerator, rng, r, { r.reseed_from_rng(Botan::system_rng(), bits); });
}
+int botan_mp_init(botan_mp_t* mp)
+ {
+ *mp = new botan_mp_struct(new Botan::BigInt);
+ return 0;
+ }
+
+int botan_mp_set_from_int(botan_mp_t mp, int initial_value)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, {
+ if(initial_value >= 0)
+ {
+ bn = Botan::BigInt(static_cast<uint64_t>(initial_value));
+ }
+ else
+ {
+ bn = Botan::BigInt(static_cast<uint64_t>(-initial_value));
+ bn.flip_sign();
+ }
+ });
+ }
+
+int botan_mp_set_from_str(botan_mp_t mp, const char* str)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { bn = Botan::BigInt(str); });
+ }
+
+int botan_mp_set_from_mp(botan_mp_t dest, botan_mp_t source)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, dest, bn, { bn = safe_get(source); });
+ }
+
+int botan_mp_is_negative(botan_mp_t mp)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { return bn.is_negative() ? 1 : 0; });
+ }
+
+int botan_mp_flip_sign(botan_mp_t mp)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { bn.flip_sign(); });
+ }
+
+int botan_mp_from_bin(botan_mp_t mp, const uint8_t bin[], size_t bin_len)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { bn.binary_decode(bin, bin_len); });
+ }
+
+int botan_mp_to_hex(botan_mp_t mp, char* out)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, {
+ std::vector<uint8_t> hex = Botan::BigInt::encode(bn, Botan::BigInt::Hexadecimal);
+ std::memcpy(out, hex.data(), hex.size());
+ out[hex.size()] = 0; // null terminate
+ });
+ }
+
+int botan_mp_to_str(botan_mp_t mp, uint8_t digit_base, char* out, size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, {
+ Botan::BigInt::Base base;
+ if(digit_base == 0 || digit_base == 10)
+ base = Botan::BigInt::Decimal;
+ else if(digit_base == 16)
+ base = Botan::BigInt::Hexadecimal;
+ else
+ throw FFI_Error("botan_mp_to_str invalid digit base");
+
+ std::vector<uint8_t> hex = Botan::BigInt::encode(bn, base);
+ hex.push_back(0); // null terminator
+ write_str_output(out, out_len, hex);
+ });
+ }
+
+int botan_mp_to_bin(botan_mp_t mp, uint8_t vec[])
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { bn.binary_encode(vec); });
+ }
+
+int botan_mp_destroy(botan_mp_t mp)
+ {
+ delete mp;
+ return 0;
+ }
+
+int botan_mp_add(botan_mp_t result, botan_mp_t x, botan_mp_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, result, res, { res = safe_get(x) + safe_get(y); });
+ }
+
+int botan_mp_sub(botan_mp_t result, botan_mp_t x, botan_mp_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, result, res, { res = safe_get(x) - safe_get(y); });
+ }
+
+int botan_mp_mul(botan_mp_t result, botan_mp_t x, botan_mp_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, result, res, { res = safe_get(x) * safe_get(y); });
+ }
+
+int botan_mp_div(botan_mp_t quotient,
+ botan_mp_t remainder,
+ botan_mp_t x, botan_mp_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, quotient, q, {
+ Botan::BigInt r;
+ Botan::divide(safe_get(x), safe_get(y), q, r);
+ safe_get(remainder) = r;
+ });
+ }
+
+int botan_mp_equal(botan_mp_t x_w, botan_mp_t y_w)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, x_w, x, { return x == safe_get(y_w); });
+ }
+
+int botan_mp_cmp(int* result, botan_mp_t x_w, botan_mp_t y_w)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, x_w, x, { *result = x.cmp(safe_get(y_w)); });
+ }
+
+int botan_mp_swap(botan_mp_t x_w, botan_mp_t y_w)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, x_w, x, { x.swap(safe_get(y_w)); });
+ }
+
+// Return (base^exponent) % modulus
+int botan_mp_powmod(botan_mp_t out, botan_mp_t base, botan_mp_t exponent, botan_mp_t modulus)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, out, o,
+ { o = Botan::power_mod(safe_get(base), safe_get(exponent), safe_get(modulus)); });
+ }
+
+int botan_mp_lshift(botan_mp_t out, botan_mp_t in, size_t shift)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, out, o, { o = safe_get(in) << shift; });
+ }
+
+int botan_mp_rshift(botan_mp_t out, botan_mp_t in, size_t shift)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, out, o, { o = safe_get(in) >> shift; });
+ }
+
+int botan_mp_mod_inverse(botan_mp_t out, botan_mp_t in, botan_mp_t modulus)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, out, o, { o = Botan::inverse_mod(safe_get(in), safe_get(modulus)); });
+ }
+
+int botan_mp_mod_mul(botan_mp_t out, botan_mp_t x, botan_mp_t y, botan_mp_t modulus)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, out, o, {
+ Botan::Modular_Reducer reducer(safe_get(modulus));
+ o = reducer.multiply(safe_get(x), safe_get(y));
+ });
+ }
+
+int botan_mp_rand_bits(botan_mp_t rand_out, botan_rng_t rng, size_t bits)
+ {
+ return BOTAN_FFI_DO(Botan::RandomNumberGenerator, rng, r, {
+ safe_get(rand_out).randomize(r, bits); });
+ }
+
+int botan_mp_rand_range(botan_mp_t rand_out,
+ botan_rng_t rng,
+ botan_mp_t lower,
+ botan_mp_t upper)
+ {
+ return BOTAN_FFI_DO(Botan::RandomNumberGenerator, rng, r, {
+ safe_get(rand_out) = Botan::BigInt::random_integer(r, safe_get(lower), safe_get(upper)); });
+ }
+
+int botan_mp_gcd(botan_mp_t out, botan_mp_t x, botan_mp_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, out, o, {
+ o = Botan::gcd(safe_get(x), safe_get(y)); });
+ }
+
+int botan_mp_is_prime(botan_mp_t mp, botan_rng_t rng, size_t test_prob)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, n,
+ { return (Botan::is_prime(n, safe_get(rng), test_prob)) ? 1 : 0; });
+ }
+
+int botan_mp_bit_set(botan_mp_t mp, size_t bit)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, n, { return (n.get_bit(bit)); });
+ }
+
+int botan_mp_num_bits(botan_mp_t mp, size_t* bits)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, n, { *bits = n.bits(); });
+ }
+
+int botan_mp_num_bytes(botan_mp_t mp, size_t* bytes)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, n, { *bytes = n.bytes(); });
+ }
+
+
int botan_hash_init(botan_hash_t* hash, const char* hash_name, uint32_t flags)
{
try
@@ -801,7 +1021,7 @@ int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size
int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str)
- {
+ {
try
{
if(key_obj == nullptr || rng_obj == nullptr || param_str == nullptr || *param_str == 0)
@@ -919,6 +1139,163 @@ int botan_privkey_load(botan_privkey_t* key, botan_rng_t rng_obj,
return -1;
}
+int botan_privkey_load_rsa(botan_privkey_t* key,
+ botan_mp_t p, botan_mp_t q, botan_mp_t d)
+ {
+ *key = nullptr;
+
+#if defined(BOTAN_HAS_RSA)
+ try
+ {
+ *key = new botan_privkey_struct(new Botan::RSA_PrivateKey(safe_get(p),
+ safe_get(q),
+ safe_get(d)));
+ return 0;
+ }
+ catch(std::exception& e)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, e.what());
+ }
+ return -1;
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_pubkey_load_rsa(botan_pubkey_t* key,
+ botan_mp_t n, botan_mp_t e)
+ {
+ *key = nullptr;
+
+#if defined(BOTAN_HAS_RSA)
+ try
+ {
+ *key = new botan_pubkey_struct(new Botan::RSA_PublicKey(safe_get(n), safe_get(e)));
+ return 0;
+ }
+ catch(std::exception& exn)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, exn.what());
+ }
+
+ return -1;
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t key)
+ {
+#if defined(BOTAN_HAS_RSA)
+ return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
+ if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<Botan::RSA_PrivateKey*>(&k))
+ {
+ safe_get(p) = rsa->get_p();
+ }
+ else
+ throw FFI_Error("Passed non-RSA key to botan_privkey_rsa_get_p");
+ });
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t key)
+ {
+#if defined(BOTAN_HAS_RSA)
+ return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
+ if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<Botan::RSA_PrivateKey*>(&k))
+ {
+ safe_get(q) = rsa->get_q();
+ }
+ else
+ throw FFI_Error("Passed non-RSA key to botan_privkey_rsa_get_q");
+ });
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t key)
+ {
+#if defined(BOTAN_HAS_RSA)
+ return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
+ if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<Botan::RSA_PrivateKey*>(&k))
+ {
+ safe_get(n) = rsa->get_n();
+ }
+ else
+ throw FFI_Error("Passed non-RSA key to botan_privkey_rsa_get_n");
+ });
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t key)
+ {
+#if defined(BOTAN_HAS_RSA)
+ return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
+ if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<Botan::RSA_PrivateKey*>(&k))
+ {
+ safe_get(e) = rsa->get_e();
+ }
+ else
+ throw FFI_Error("Passed non-RSA key to botan_privkey_rsa_get_e");
+ });
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t key)
+ {
+#if defined(BOTAN_HAS_RSA)
+ return BOTAN_FFI_DO(Botan::Private_Key, key, k, {
+ if(const Botan::RSA_PrivateKey* rsa = dynamic_cast<Botan::RSA_PrivateKey*>(&k))
+ {
+ safe_get(d) = rsa->get_e();
+ }
+ else
+ throw FFI_Error("Passed non-RSA key to botan_privkey_rsa_get_d");
+ });
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t key)
+ {
+#if defined(BOTAN_HAS_RSA)
+ return BOTAN_FFI_DO(Botan::Public_Key, key, k, {
+ if(const Botan::RSA_PublicKey* rsa = dynamic_cast<Botan::RSA_PublicKey*>(&k))
+ {
+ safe_get(e) = rsa->get_e();
+ }
+ else
+ throw FFI_Error("Passed non-RSA key to botan_pubkey_rsa_get_e");
+ });
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t key)
+ {
+#if defined(BOTAN_HAS_RSA)
+ return BOTAN_FFI_DO(Botan::Public_Key, key, k, {
+ if(const Botan::RSA_PublicKey* rsa = dynamic_cast<Botan::RSA_PublicKey*>(&k))
+ {
+ safe_get(n) = rsa->get_n();
+ }
+ else
+ throw FFI_Error("Passed non-RSA key to botan_pubkey_rsa_get_n");
+ });
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
int botan_privkey_destroy(botan_privkey_t key)
{
delete key;
@@ -959,14 +1336,14 @@ int botan_pubkey_check_key(botan_pubkey_t key, botan_rng_t rng, uint32_t flags)
const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS);
return BOTAN_FFI_DO(Botan::Public_Key, key, k,
- { return (k.check_key(safe_get(rng), strong) == true) ? 0 : 1; });
+ { return (k.check_key(safe_get(rng), strong) == true) ? 0 : -1; });
}
int botan_privkey_check_key(botan_privkey_t key, botan_rng_t rng, uint32_t flags)
{
const bool strong = (flags & BOTAN_CHECK_KEY_EXPENSIVE_TESTS);
return BOTAN_FFI_DO(Botan::Private_Key, key, k,
- { return (k.check_key(safe_get(rng), strong) == true) ? 0 : 1; });
+ { return (k.check_key(safe_get(rng), strong) == true) ? 0 : -1; });
}
int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index 8ac9f3c82..2cb8d38bd 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -1,6 +1,6 @@
/*
* FFI (C89 API)
-* (C) 2015 Jack Lloyd
+* (C) 2015,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -158,6 +158,7 @@ BOTAN_DLL int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len);
* @return 0 on success, 1 on failure
*/
BOTAN_DLL int botan_hex_encode(const uint8_t* x, size_t len, char* out, uint32_t flags);
+
// TODO: botan_hex_decode
// TODO: botan_base64_encode
// TODO: botan_base64_decode
@@ -171,7 +172,8 @@ typedef struct botan_rng_struct* botan_rng_t;
* Initialize a random number generator object
* @param rng rng object
* @param rng_type type of the rng, possible values:
-* "system" or nullptr: System_RNG, "user": AutoSeeded_RNG
+* "system": System_RNG, "user": AutoSeeded_RNG
+* Set rng_type to null or empty string to let the library choose
*
* TODO: replace rng_type with simple flags?
*/
@@ -182,7 +184,7 @@ BOTAN_DLL int botan_rng_init(botan_rng_t* rng, const char* rng_type);
* @param rng rng object
* @param out output buffer of size out_len
* @param out_len number of requested bytes
-* @return 0 on success, -1 on failure
+* @return 0 on success, negative on failure
*
* TODO: better name
*/
@@ -279,7 +281,7 @@ typedef struct botan_mac_struct* botan_mac_t;
* @param mac mac object
* @param mac_name name of the hash function, e.g., "HMAC(SHA-384)"
* @param flags should be 0 in current API revision, all other uses are reserved
-* and return -1
+* and return a negative value (error code)
* @return 0 on success, a negative value on failure
*/
BOTAN_DLL int botan_mac_init(botan_mac_t* mac, const char* mac_name, uint32_t flags);
@@ -453,6 +455,92 @@ BOTAN_DLL int botan_bcrypt_generate(uint8_t* out, size_t* out_len,
size_t work_factor,
uint32_t flags);
+/*
+* Multiple precision integers
+*/
+typedef struct botan_mp_struct* botan_mp_t;
+
+BOTAN_DLL int botan_mp_init(botan_mp_t* mp);
+BOTAN_DLL int botan_mp_destroy(botan_mp_t mp);
+
+// writes botan_mp_num_bytes(mp)*2 + 1 bytes to out[]
+BOTAN_DLL int botan_mp_to_hex(botan_mp_t mp, char* out);
+BOTAN_DLL int botan_mp_to_str(botan_mp_t mp, uint8_t base, char* out, size_t* out_len);
+
+BOTAN_DLL int botan_mp_set_from_int(botan_mp_t mp, int initial_value);
+BOTAN_DLL int botan_mp_set_from_mp(botan_mp_t dest, botan_mp_t source);
+BOTAN_DLL int botan_mp_set_from_str(botan_mp_t dest, const char* str);
+
+BOTAN_DLL int botan_mp_num_bits(botan_mp_t n, size_t* bits);
+BOTAN_DLL int botan_mp_num_bytes(botan_mp_t n, size_t* bytes);
+
+// Writes botan_mp_num_bytes(mp) to vec
+BOTAN_DLL int botan_mp_to_bin(botan_mp_t mp, uint8_t vec[]);
+BOTAN_DLL int botan_mp_from_bin(botan_mp_t mp, const uint8_t vec[], size_t vec_len);
+
+BOTAN_DLL int botan_mp_is_negative(botan_mp_t mp);
+BOTAN_DLL int botan_mp_flip_sign(botan_mp_t mp);
+
+BOTAN_DLL int botan_mp_add(botan_mp_t result, botan_mp_t x, botan_mp_t y);
+BOTAN_DLL int botan_mp_sub(botan_mp_t result, botan_mp_t x, botan_mp_t y);
+BOTAN_DLL int botan_mp_mul(botan_mp_t result, botan_mp_t x, botan_mp_t y);
+
+BOTAN_DLL int botan_mp_div(botan_mp_t quotient,
+ botan_mp_t remainder,
+ botan_mp_t x, botan_mp_t y);
+
+BOTAN_DLL int botan_mp_mod_mul(botan_mp_t result, botan_mp_t x, botan_mp_t y, botan_mp_t mod);
+
+/*
+* Returns 0 if x != y
+* Returns 1 if x == y
+* Returns negative number on error
+*/
+BOTAN_DLL int botan_mp_equal(botan_mp_t x, botan_mp_t y);
+
+/*
+* Sets *result to comparison result:
+* -1 if x < y, 0 if x == y, 1 if x > y
+* Returns negative number on error or zero on success
+*/
+BOTAN_DLL int botan_mp_cmp(int* result, botan_mp_t x, botan_mp_t y);
+
+/*
+* Swap two botan_mp_t
+*/
+BOTAN_DLL int botan_mp_swap(botan_mp_t x, botan_mp_t y);
+
+// Return (base^exponent) % modulus
+BOTAN_DLL int botan_mp_powmod(botan_mp_t out, botan_mp_t base, botan_mp_t exponent, botan_mp_t modulus);
+
+BOTAN_DLL int botan_mp_lshift(botan_mp_t out, botan_mp_t in, size_t shift);
+BOTAN_DLL int botan_mp_rshift(botan_mp_t out, botan_mp_t in, size_t shift);
+
+BOTAN_DLL int botan_mp_mod_inverse(botan_mp_t out, botan_mp_t in, botan_mp_t modulus);
+
+BOTAN_DLL int botan_mp_rand_bits(botan_mp_t rand_out, botan_rng_t rng, size_t bits);
+
+BOTAN_DLL int botan_mp_rand_range(botan_mp_t rand_out, botan_rng_t rng,
+ botan_mp_t lower_bound, botan_mp_t upper_bound);
+
+BOTAN_DLL int botan_mp_gcd(botan_mp_t out, botan_mp_t x, botan_mp_t y);
+
+/**
+* Returns 0 if n is not prime
+* Returns 1 if n is prime
+* Returns negative number on error
+*/
+BOTAN_DLL int botan_mp_is_prime(botan_mp_t n, botan_rng_t rng, size_t test_prob);
+
+/**
+* Returns 0 if specified bit of n is not set
+* Returns 1 if specified bit of n is set
+* Returns negative number on error
+*/
+BOTAN_DLL int botan_mp_bit_set(botan_mp_t n, size_t bit);
+
+/* Bcrypt password hashing */
+
/**
* Check a previously created password hash
* @param pass the password to check against
@@ -526,6 +614,9 @@ BOTAN_DLL int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out
BOTAN_DLL int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len);
+/**
+* Returns 0 if key is valid, negative if invalid key or some other error
+*/
BOTAN_DLL int botan_pubkey_check_key(botan_pubkey_t key, botan_rng_t rng, uint32_t flags);
BOTAN_DLL int botan_pubkey_estimated_strength(botan_pubkey_t key, size_t* estimate);
@@ -537,6 +628,27 @@ BOTAN_DLL int botan_pubkey_destroy(botan_pubkey_t key);
/*
+* Algorithm specific key operations: RSA
+*/
+BOTAN_DLL int botan_privkey_load_rsa(botan_privkey_t* key,
+ botan_mp_t p,
+ botan_mp_t q,
+ botan_mp_t d);
+
+BOTAN_DLL int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t rsa_key);
+BOTAN_DLL int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t rsa_key);
+BOTAN_DLL int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t rsa_key);
+BOTAN_DLL int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t rsa_key);
+BOTAN_DLL int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t rsa_key);
+
+BOTAN_DLL int botan_pubkey_load_rsa(botan_pubkey_t* key,
+ botan_mp_t n,
+ botan_mp_t e);
+
+BOTAN_DLL int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t rsa_key);
+BOTAN_DLL int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t rsa_key);
+
+/*
* Public Key Encryption
*/
typedef struct botan_pk_op_encrypt_struct* botan_pk_op_encrypt_t;
diff --git a/src/lib/ffi/info.txt b/src/lib/ffi/info.txt
index 7b3068274..e1d29981f 100644
--- a/src/lib/ffi/info.txt
+++ b/src/lib/ffi/info.txt
@@ -1,10 +1,11 @@
-define FFI 20151015
+define FFI 20170327
<requires>
aead
kdf
pbkdf
pubkey
+bigint
x509
#tls
system_rng