/* * (C) 2015,2017 Jack Lloyd * (C) 2017 Ribose Inc * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #include #include #include #include #include extern "C" { using namespace Botan_FFI; int botan_mp_init(botan_mp_t* mp_out) { return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() { 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(initial_value)); } else { bn = Botan::BigInt(static_cast(-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::decode(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, { std::vector 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(const 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 hex = Botan::BigInt::encode(bn, base); hex.push_back(0); // null terminator return write_str_output(out, out_len, hex); }); } 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, { 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, { res = safe_get(x) - safe_get(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, { 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::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_DO(Botan::BigInt, x_w, x, { return x == safe_get(y_w); }); } int botan_mp_is_zero(const botan_mp_t mp) { return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { return bn.is_zero(); }); } int botan_mp_is_odd(const botan_mp_t mp) { return BOTAN_FFI_DO(Botan::BigInt, mp, bn, { return bn.is_odd(); }); } int botan_mp_is_even(const botan_mp_t mp) { return BOTAN_FFI_DO(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_DO(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_DO(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(); }); } }