summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/tdutils/td/utils/BigNum.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Telegram/tdlib/td/tdutils/td/utils/BigNum.cpp')
-rw-r--r--protocols/Telegram/tdlib/td/tdutils/td/utils/BigNum.cpp104
1 files changed, 87 insertions, 17 deletions
diff --git a/protocols/Telegram/tdlib/td/tdutils/td/utils/BigNum.cpp b/protocols/Telegram/tdlib/td/tdutils/td/utils/BigNum.cpp
index f553661d49..e7a93d4399 100644
--- a/protocols/Telegram/tdlib/td/tdutils/td/utils/BigNum.cpp
+++ b/protocols/Telegram/tdlib/td/tdutils/td/utils/BigNum.cpp
@@ -1,5 +1,5 @@
//
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -12,10 +12,13 @@ char disable_linker_warning_about_empty_file_bignum_cpp TD_UNUSED;
#include "td/utils/logging.h"
#include "td/utils/misc.h"
+#include "td/utils/SliceBuilder.h"
#include <openssl/bn.h>
#include <openssl/crypto.h>
+#include <algorithm>
+
namespace td {
class BigNumContext::Impl {
@@ -37,9 +40,8 @@ class BigNumContext::Impl {
BigNumContext::BigNumContext() : impl_(make_unique<Impl>()) {
}
-BigNumContext::BigNumContext(BigNumContext &&other) = default;
-BigNumContext &BigNumContext::operator=(BigNumContext &&other) = default;
-
+BigNumContext::BigNumContext(BigNumContext &&other) noexcept = default;
+BigNumContext &BigNumContext::operator=(BigNumContext &&other) noexcept = default;
BigNumContext::~BigNumContext() = default;
class BigNum::Impl {
@@ -68,6 +70,9 @@ BigNum::BigNum(const BigNum &other) : BigNum() {
}
BigNum &BigNum::operator=(const BigNum &other) {
+ if (this == &other) {
+ return *this;
+ }
CHECK(impl_ != nullptr);
CHECK(other.impl_ != nullptr);
BIGNUM *result = BN_copy(impl_->big_num, other.impl_->big_num);
@@ -75,20 +80,41 @@ BigNum &BigNum::operator=(const BigNum &other) {
return *this;
}
-BigNum::BigNum(BigNum &&other) = default;
-
-BigNum &BigNum::operator=(BigNum &&other) = default;
-
+BigNum::BigNum(BigNum &&other) noexcept = default;
+BigNum &BigNum::operator=(BigNum &&other) noexcept = default;
BigNum::~BigNum() = default;
BigNum BigNum::from_binary(Slice str) {
return BigNum(make_unique<Impl>(BN_bin2bn(str.ubegin(), narrow_cast<int>(str.size()), nullptr)));
}
-BigNum BigNum::from_decimal(CSlice str) {
+BigNum BigNum::from_le_binary(Slice str) {
+#if defined(OPENSSL_IS_BORINGSSL)
+ return BigNum(make_unique<Impl>(BN_le2bn(str.ubegin(), narrow_cast<int>(str.size()), nullptr)));
+#elif OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ return BigNum(make_unique<Impl>(BN_lebin2bn(str.ubegin(), narrow_cast<int>(str.size()), nullptr)));
+#else
+ string str_copy = str.str();
+ std::reverse(str_copy.begin(), str_copy.end());
+ return from_binary(str_copy);
+#endif
+}
+
+Result<BigNum> BigNum::from_decimal(CSlice str) {
BigNum result;
- int err = BN_dec2bn(&result.impl_->big_num, str.c_str());
- LOG_IF(FATAL, err == 0);
+ int res = BN_dec2bn(&result.impl_->big_num, str.c_str());
+ if (res == 0 || static_cast<size_t>(res) != str.size()) {
+ return Status::Error(PSLICE() << "Failed to parse \"" << str << "\" as BigNum");
+ }
+ return result;
+}
+
+Result<BigNum> BigNum::from_hex(CSlice str) {
+ BigNum result;
+ int res = BN_hex2bn(&result.impl_->big_num, str.c_str());
+ if (res == 0 || static_cast<size_t>(res) != str.size()) {
+ return Status::Error(PSLICE() << "Failed to parse \"" << str << "\" as hexadecimal BigNum");
+ }
return result;
}
@@ -99,10 +125,6 @@ BigNum BigNum::from_raw(void *openssl_big_num) {
BigNum::BigNum(unique_ptr<Impl> &&impl) : impl_(std::move(impl)) {
}
-void BigNum::ensure_const_time() {
- BN_set_flags(impl_->big_num, BN_FLG_CONSTTIME);
-}
-
int BigNum::get_num_bits() const {
return BN_num_bits(impl_->big_num);
}
@@ -126,7 +148,12 @@ bool BigNum::is_bit_set(int num) const {
}
bool BigNum::is_prime(BigNumContext &context) const {
- int result = BN_is_prime_ex(impl_->big_num, BN_prime_checks, context.impl_->big_num_context, nullptr);
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
+ int result = BN_check_prime(impl_->big_num, context.impl_->big_num_context, nullptr);
+#else
+ int result =
+ BN_is_prime_ex(impl_->big_num, get_num_bits() > 2048 ? 128 : 64, context.impl_->big_num_context, nullptr);
+#endif
LOG_IF(FATAL, result == -1);
return result == 1;
}
@@ -180,10 +207,32 @@ string BigNum::to_binary(int exact_size) const {
CHECK(exact_size >= num_size);
}
string res(exact_size, '\0');
- BN_bn2bin(impl_->big_num, reinterpret_cast<unsigned char *>(&res[exact_size - num_size]));
+ BN_bn2bin(impl_->big_num, MutableSlice(res).ubegin() + (exact_size - num_size));
return res;
}
+string BigNum::to_le_binary(int exact_size) const {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) || defined(OPENSSL_IS_BORINGSSL)
+ int num_size = get_num_bytes();
+ if (exact_size == -1) {
+ exact_size = num_size;
+ } else {
+ CHECK(exact_size >= num_size);
+ }
+ string result(exact_size, '\0');
+#if defined(OPENSSL_IS_BORINGSSL)
+ BN_bn2le_padded(MutableSlice(result).ubegin(), exact_size, impl_->big_num);
+#else
+ BN_bn2lebinpad(impl_->big_num, MutableSlice(result).ubegin(), exact_size);
+#endif
+ return result;
+#else
+ string result = to_binary(exact_size);
+ std::reverse(result.begin(), result.end());
+ return result;
+#endif
+}
+
string BigNum::to_decimal() const {
char *result = BN_bn2dec(impl_->big_num);
CHECK(result != nullptr);
@@ -214,12 +263,29 @@ void BigNum::mul(BigNum &r, BigNum &a, BigNum &b, BigNumContext &context) {
LOG_IF(FATAL, result != 1);
}
+void BigNum::mod_add(BigNum &r, BigNum &a, BigNum &b, const BigNum &m, BigNumContext &context) {
+ int result = BN_mod_add(r.impl_->big_num, a.impl_->big_num, b.impl_->big_num, m.impl_->big_num,
+ context.impl_->big_num_context);
+ LOG_IF(FATAL, result != 1);
+}
+
+void BigNum::mod_sub(BigNum &r, BigNum &a, BigNum &b, const BigNum &m, BigNumContext &context) {
+ int result = BN_mod_sub(r.impl_->big_num, a.impl_->big_num, b.impl_->big_num, m.impl_->big_num,
+ context.impl_->big_num_context);
+ LOG_IF(FATAL, result != 1);
+}
+
void BigNum::mod_mul(BigNum &r, BigNum &a, BigNum &b, const BigNum &m, BigNumContext &context) {
int result = BN_mod_mul(r.impl_->big_num, a.impl_->big_num, b.impl_->big_num, m.impl_->big_num,
context.impl_->big_num_context);
LOG_IF(FATAL, result != 1);
}
+void BigNum::mod_inverse(BigNum &r, BigNum &a, const BigNum &m, BigNumContext &context) {
+ auto result = BN_mod_inverse(r.impl_->big_num, a.impl_->big_num, m.impl_->big_num, context.impl_->big_num_context);
+ LOG_IF(FATAL, result != r.impl_->big_num);
+}
+
void BigNum::div(BigNum *quotient, BigNum *remainder, const BigNum &dividend, const BigNum &divisor,
BigNumContext &context) {
auto q = quotient == nullptr ? nullptr : quotient->impl_->big_num;
@@ -247,5 +313,9 @@ int BigNum::compare(const BigNum &a, const BigNum &b) {
return BN_cmp(a.impl_->big_num, b.impl_->big_num);
}
+StringBuilder &operator<<(StringBuilder &sb, const BigNum &bn) {
+ return sb << bn.to_decimal();
+}
+
} // namespace td
#endif