2
This file is part of TON Blockchain Library.
4
TON Blockchain Library is free software: you can redistribute it and/or modify
5
it under the terms of the GNU Lesser General Public License as published by
6
the Free Software Foundation, either version 2 of the License, or
7
(at your option) any later version.
9
TON Blockchain Library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU Lesser General Public License for more details.
14
You should have received a copy of the GNU Lesser General Public License
15
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
17
Copyright 2017-2020 Telegram Systems LLP
19
#include "openssl/bignum.h"
21
#ifdef OPENSSL_IS_BORINGSSL
22
#include <openssl/mem.h>
30
BN_CTX* get_ctx(void) {
31
thread_local BN_CTX* ctx = BN_CTX_new();
35
BignumBitref& BignumBitref::operator=(bool val) {
44
const Bignum operator+(const Bignum& x, const Bignum& y) {
46
bn_assert(BN_add(z.bn_ptr(), x.bn_ptr(), y.bn_ptr()));
50
const Bignum operator+(const Bignum& x, long y) {
53
bn_assert(BN_add_word(z.bn_ptr(), y));
57
bn_assert(BN_sub_word(z.bn_ptr(), -y));
65
const Bignum operator+ (Bignum&& x, long y) {
67
bn_assert (BN_add_word (x.bn_ptr(), y));
69
bn_assert (BN_sub_word (x.bn_ptr(), -y));
76
const Bignum operator+ (long y, Bignum&& x) {
81
const Bignum operator-(const Bignum& x, const Bignum& y) {
83
bn_assert(BN_sub(z.bn_ptr(), x.bn_ptr(), y.bn_ptr()));
88
const Bignum operator- (Bignum&& x, long y) {
93
const Bignum operator*(const Bignum& x, const Bignum& y) {
95
bn_assert(BN_mul(z.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx()));
99
const Bignum operator*(const Bignum& x, long y) {
102
bn_assert(BN_mul_word(z.bn_ptr(), y));
107
bn_assert(BN_mul_word(z.bn_ptr(), -y));
116
const Bignum operator* (Bignum&& x, long y) {
118
bn_assert (BN_mul_word (x.bn_ptr(), y));
121
bn_assert (BN_mul_word (x.bn_ptr(), -y));
125
return std::move (x);
129
const Bignum operator/(const Bignum& x, const Bignum& y) {
131
bn_assert(BN_div(z.bn_ptr(), w.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx()));
135
const Bignum Bignum::divmod(const Bignum& y) {
137
bn_assert(BN_div(val, w.bn_ptr(), val, y.bn_ptr(), get_ctx()));
141
const Bignum operator%(const Bignum& x, const Bignum& y) {
143
bn_assert(BN_mod(z.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx()));
147
unsigned long operator%(const Bignum& x, unsigned long y) {
148
BN_ULONG rem = BN_mod_word(x.bn_ptr(), y);
149
bn_assert(rem != (BN_ULONG)(-1));
150
return static_cast<unsigned long>(rem);
153
const Bignum operator<<(const Bignum& x, int r) {
155
bn_assert(BN_lshift(z.bn_ptr(), x.bn_ptr(), r));
159
const Bignum operator>>(const Bignum& x, int r) {
161
bn_assert(BN_rshift(z.bn_ptr(), x.bn_ptr(), r));
165
const Bignum abs(const Bignum& x) {
173
const Bignum sqr(const Bignum& x) {
175
bn_assert(BN_sqr(z.bn_ptr(), x.bn_ptr(), get_ctx()));
179
void Bignum::export_msb(unsigned char* buffer, std::size_t size) const {
180
bn_assert(size <= (1 << 20));
181
bn_assert(sign() >= 0);
182
std::size_t n = BN_num_bytes(val);
183
bn_assert(n <= size);
184
bn_assert(BN_bn2bin(val, buffer + size - n) == static_cast<int>(n));
185
std::memset(buffer, 0, size - n);
188
Bignum& Bignum::import_msb(const unsigned char* buffer, std::size_t size) {
189
bn_assert(size <= (1 << 20));
191
while (i < size && !buffer[i]) {
194
bn_assert(BN_bin2bn(buffer + i, static_cast<int>(size - i), val) == val);
198
void Bignum::export_lsb(unsigned char* buffer, std::size_t size) const {
199
bn_assert(size <= (1 << 20));
200
bn_assert(sign() >= 0);
201
std::size_t n = BN_num_bytes(val);
202
bn_assert(n <= size);
203
bn_assert(BN_bn2bin(val, buffer) == (int)n);
204
std::memset(buffer + n, 0, size - n);
205
for (std::size_t i = 0; 2 * i + 1 < n; i++) {
206
std::swap(buffer[i], buffer[n - 1 - i]);
210
Bignum& Bignum::import_lsb(const unsigned char* buffer, std::size_t size) {
211
bn_assert(size <= (1 << 20));
212
while (size > 0 && !buffer[size - 1]) {
216
// Use BN_set_word, because from 1.1.0 BN_zero may return void
217
bn_assert(BN_set_word(val, 0));
220
unsigned char tmp_buff[1024];
221
unsigned char* tmp = (size < 1024 ? tmp_buff : new unsigned char[size]);
222
unsigned char* ptr = tmp + size;
223
for (std::size_t i = 0; i < size; i++) {
226
bn_assert(BN_bin2bn(tmp, static_cast<int>(size), val) == val);
227
if (tmp != tmp_buff) {
233
std::string Bignum::to_str() const {
234
char* ptr = BN_bn2dec(val);
241
std::string Bignum::to_hex() const {
242
char* ptr = BN_bn2hex(val);
249
std::ostream& operator<<(std::ostream& os, const Bignum& x) {
250
return os << x.to_str();
253
std::istream& operator>>(std::istream& is, Bignum& x) {
256
x = dec_string(word);
260
bool is_prime(const Bignum& p) {
261
#if OPENSSL_VERSION_MAJOR >= 3
262
int result = BN_check_prime(p.bn_ptr(), get_ctx(), nullptr);
263
LOG_IF(FATAL, result == -1);
266
return BN_is_prime_fasttest_ex(p.bn_ptr(), BN_prime_checks, get_ctx(), true, 0);