summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/ffi/ffi_mp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/lib/ffi/ffi_mp.cpp')
-rw-r--r--comm/third_party/botan/src/lib/ffi/ffi_mp.cpp312
1 files changed, 312 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/ffi/ffi_mp.cpp b/comm/third_party/botan/src/lib/ffi/ffi_mp.cpp
new file mode 100644
index 0000000000..68869e6ecf
--- /dev/null
+++ b/comm/third_party/botan/src/lib/ffi/ffi_mp.cpp
@@ -0,0 +1,312 @@
+/*
+* (C) 2015,2017 Jack Lloyd
+* (C) 2017 Ribose Inc
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/ffi.h>
+#include <botan/internal/ffi_util.h>
+#include <botan/internal/ffi_rng.h>
+#include <botan/internal/ffi_mp.h>
+#include <botan/reducer.h>
+#include <botan/numthry.h>
+#include <botan/divide.h>
+
+extern "C" {
+
+using namespace Botan_FFI;
+
+int botan_mp_init(botan_mp_t* mp_out)
+ {
+ return ffi_guard_thunk(__func__, [=]() -> int {
+ if(mp_out == nullptr)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+ *mp_out = new botan_mp_struct(new Botan::BigInt);
+ return BOTAN_FFI_SUCCESS;
+ });
+ }
+
+int botan_mp_clear(botan_mp_t mp)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { bn.clear(); });
+ }
+
+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_radix_str(botan_mp_t mp, const char* str, size_t radix)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, {
+ Botan::BigInt::Base base;
+ if(radix == 10)
+ base = Botan::BigInt::Decimal;
+ else if(radix == 16)
+ base = Botan::BigInt::Hexadecimal;
+ else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+
+ const uint8_t* bytes = Botan::cast_char_ptr_to_uint8(str);
+ const size_t len = strlen(str);
+
+ bn = Botan::BigInt(bytes, len, base);
+ });
+ }
+
+int botan_mp_set_from_mp(botan_mp_t dest, const botan_mp_t source)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, dest, bn, { bn = safe_get(source); });
+ }
+
+int botan_mp_is_negative(const botan_mp_t mp)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { return bn.is_negative() ? 1 : 0; });
+ }
+
+int botan_mp_is_positive(const botan_mp_t mp)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { return bn.is_positive() ? 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(const botan_mp_t mp, char* out)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, {
+ const std::string hex = bn.to_hex_string();
+ std::memcpy(out, hex.c_str(), 1 + hex.size());
+ });
+ }
+
+int botan_mp_to_str(const botan_mp_t mp, uint8_t digit_base, char* out, size_t* out_len)
+ {
+ return BOTAN_FFI_RETURNING(Botan::BigInt, mp, bn, {
+
+ if(digit_base == 0 || digit_base == 10)
+ return write_str_output(out, out_len, bn.to_dec_string());
+ else if(digit_base == 16)
+ return write_str_output(out, out_len, bn.to_hex_string());
+ else
+ return BOTAN_FFI_ERROR_BAD_PARAMETER;
+ });
+ }
+
+int botan_mp_to_bin(const botan_mp_t mp, uint8_t vec[])
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { bn.binary_encode(vec); });
+ }
+
+int botan_mp_to_uint32(const botan_mp_t mp, uint32_t* val)
+ {
+ if(val == nullptr)
+ {
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+ }
+ return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { *val = bn.to_u32bit(); });
+ }
+
+int botan_mp_destroy(botan_mp_t mp)
+ {
+ return BOTAN_FFI_CHECKED_DELETE(mp);
+ }
+
+int botan_mp_add(botan_mp_t result, const botan_mp_t x, const botan_mp_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, result, res, {
+ if(result == x)
+ res += safe_get(y);
+ else
+ res = safe_get(x) + safe_get(y);
+ });
+ }
+
+int botan_mp_sub(botan_mp_t result, const botan_mp_t x, const botan_mp_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, result, res, {
+ if(result == x)
+ res -= safe_get(y);
+ else
+ res = safe_get(x) - safe_get(y);
+ });
+ }
+
+int botan_mp_add_u32(botan_mp_t result, const botan_mp_t x, uint32_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, result, res, {
+ if(result == x)
+ res += static_cast<Botan::word>(y);
+ else
+ res = safe_get(x) + static_cast<Botan::word>(y);
+ });
+ }
+
+int botan_mp_sub_u32(botan_mp_t result, const botan_mp_t x, uint32_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, result, res, {
+ if(result == x)
+ res -= static_cast<Botan::word>(y);
+ else
+ res = safe_get(x) - static_cast<Botan::word>(y);
+ });
+ }
+
+int botan_mp_mul(botan_mp_t result, const botan_mp_t x, const botan_mp_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, result, res, {
+ if(result == x)
+ res *= safe_get(y);
+ else
+ res = safe_get(x) * safe_get(y);
+ });
+ }
+
+int botan_mp_div(botan_mp_t quotient,
+ botan_mp_t remainder,
+ const botan_mp_t x, const botan_mp_t y)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, quotient, q, {
+ Botan::BigInt r;
+ Botan::vartime_divide(safe_get(x), safe_get(y), q, r);
+ safe_get(remainder) = r;
+ });
+ }
+
+int botan_mp_equal(const botan_mp_t x_w, const botan_mp_t y_w)
+ {
+ return BOTAN_FFI_RETURNING(Botan::BigInt, x_w, x, { return x == safe_get(y_w); });
+ }
+
+int botan_mp_is_zero(const botan_mp_t mp)
+ {
+ return BOTAN_FFI_RETURNING(Botan::BigInt, mp, bn, { return bn.is_zero(); });
+ }
+
+int botan_mp_is_odd(const botan_mp_t mp)
+ {
+ return BOTAN_FFI_RETURNING(Botan::BigInt, mp, bn, { return bn.is_odd(); });
+ }
+
+int botan_mp_is_even(const botan_mp_t mp)
+ {
+ return BOTAN_FFI_RETURNING(Botan::BigInt, mp, bn, { return bn.is_even(); });
+ }
+
+int botan_mp_cmp(int* result, const botan_mp_t x_w, const 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, const botan_mp_t base, const botan_mp_t exponent, const 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, const 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, const 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, const botan_mp_t in, const 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, const botan_mp_t x, const botan_mp_t y, const 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,
+ const botan_mp_t lower,
+ const 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, const botan_mp_t x, const 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(const botan_mp_t mp, botan_rng_t rng, size_t test_prob)
+ {
+ return BOTAN_FFI_RETURNING(Botan::BigInt, mp, n,
+ { return (Botan::is_prime(n, safe_get(rng), test_prob)) ? 1 : 0; });
+ }
+
+int botan_mp_get_bit(const botan_mp_t mp, size_t bit)
+ {
+ return BOTAN_FFI_RETURNING(Botan::BigInt, mp, n, { return (n.get_bit(bit)); });
+ }
+
+int botan_mp_set_bit(botan_mp_t mp, size_t bit)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, n, { n.set_bit(bit); });
+ }
+
+int botan_mp_clear_bit(botan_mp_t mp, size_t bit)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, n, { n.clear_bit(bit); });
+ }
+
+int botan_mp_num_bits(const botan_mp_t mp, size_t* bits)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, n, { *bits = n.bits(); });
+ }
+
+int botan_mp_num_bytes(const botan_mp_t mp, size_t* bytes)
+ {
+ return BOTAN_FFI_DO(Botan::BigInt, mp, n, { *bytes = n.bytes(); });
+ }
+
+}