Coverage Report

Created: 2025-08-28 06:21

/src/Botan-3.4.0/src/lib/ffi/ffi_mp.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* (C) 2015,2017 Jack Lloyd
3
* (C) 2017 Ribose Inc
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/ffi.h>
9
10
#include <botan/numthry.h>
11
#include <botan/reducer.h>
12
#include <botan/internal/divide.h>
13
#include <botan/internal/ffi_mp.h>
14
#include <botan/internal/ffi_rng.h>
15
#include <botan/internal/ffi_util.h>
16
17
extern "C" {
18
19
using namespace Botan_FFI;
20
21
302k
int botan_mp_init(botan_mp_t* mp_out) {
22
302k
   return ffi_guard_thunk(__func__, [=]() -> int {
23
302k
      if(mp_out == nullptr) {
24
0
         return BOTAN_FFI_ERROR_NULL_POINTER;
25
0
      }
26
27
302k
      auto mp = std::make_unique<Botan::BigInt>();
28
302k
      *mp_out = new botan_mp_struct(std::move(mp));
29
302k
      return BOTAN_FFI_SUCCESS;
30
302k
   });
31
302k
}
32
33
0
int botan_mp_clear(botan_mp_t mp) {
34
0
   return BOTAN_FFI_VISIT(mp, [](auto& bn) { bn.clear(); });
35
0
}
36
37
0
int botan_mp_set_from_int(botan_mp_t mp, int initial_value) {
38
0
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) { bn = Botan::BigInt::from_s32(initial_value); });
39
0
}
40
41
0
int botan_mp_set_from_str(botan_mp_t mp, const char* str) {
42
0
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) { bn = Botan::BigInt(str); });
43
0
}
44
45
0
int botan_mp_set_from_radix_str(botan_mp_t mp, const char* str, size_t radix) {
46
0
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) {
47
0
      Botan::BigInt::Base base;
48
0
      if(radix == 10)
49
0
         base = Botan::BigInt::Decimal;
50
0
      else if(radix == 16)
51
0
         base = Botan::BigInt::Hexadecimal;
52
0
      else
53
0
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
54
55
0
      const uint8_t* bytes = Botan::cast_char_ptr_to_uint8(str);
56
0
      const size_t len = strlen(str);
57
58
0
      bn = Botan::BigInt(bytes, len, base);
59
0
      return BOTAN_FFI_SUCCESS;
60
0
   });
61
0
}
62
63
0
int botan_mp_set_from_mp(botan_mp_t dest, const botan_mp_t source) {
64
0
   return BOTAN_FFI_VISIT(dest, [=](auto& bn) { bn = safe_get(source); });
65
0
}
66
67
0
int botan_mp_is_negative(const botan_mp_t mp) {
68
0
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) { return bn.is_negative() ? 1 : 0; });
69
0
}
70
71
0
int botan_mp_is_positive(const botan_mp_t mp) {
72
0
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) { return bn.is_positive() ? 1 : 0; });
73
0
}
74
75
0
int botan_mp_flip_sign(botan_mp_t mp) {
76
0
   return BOTAN_FFI_VISIT(mp, [](auto& bn) { bn.flip_sign(); });
77
0
}
78
79
302k
int botan_mp_from_bin(botan_mp_t mp, const uint8_t bin[], size_t bin_len) {
80
302k
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) { bn.binary_decode(bin, bin_len); });
81
302k
}
82
83
0
int botan_mp_to_hex(const botan_mp_t mp, char* out) {
84
0
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) {
85
0
      const std::string hex = bn.to_hex_string();
86
0
      std::memcpy(out, hex.c_str(), 1 + hex.size());
87
0
   });
88
0
}
89
90
0
int botan_mp_to_str(const botan_mp_t mp, uint8_t digit_base, char* out, size_t* out_len) {
91
0
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) -> int {
92
0
      if(digit_base == 0 || digit_base == 10)
93
0
         return write_str_output(out, out_len, bn.to_dec_string());
94
0
      else if(digit_base == 16)
95
0
         return write_str_output(out, out_len, bn.to_hex_string());
96
0
      else
97
0
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
98
0
   });
99
0
}
100
101
0
int botan_mp_to_bin(const botan_mp_t mp, uint8_t vec[]) {
102
0
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) { bn.binary_encode(vec); });
103
0
}
104
105
0
int botan_mp_to_uint32(const botan_mp_t mp, uint32_t* val) {
106
0
   if(val == nullptr) {
107
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
108
0
   }
109
0
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) { *val = bn.to_u32bit(); });
110
0
}
111
112
302k
int botan_mp_destroy(botan_mp_t mp) {
113
302k
   return BOTAN_FFI_CHECKED_DELETE(mp);
114
302k
}
115
116
0
int botan_mp_add(botan_mp_t result, const botan_mp_t x, const botan_mp_t y) {
117
0
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
118
0
      if(result == x)
119
0
         res += safe_get(y);
120
0
      else
121
0
         res = safe_get(x) + safe_get(y);
122
0
   });
123
0
}
124
125
0
int botan_mp_sub(botan_mp_t result, const botan_mp_t x, const botan_mp_t y) {
126
0
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
127
0
      if(result == x)
128
0
         res -= safe_get(y);
129
0
      else
130
0
         res = safe_get(x) - safe_get(y);
131
0
   });
132
0
}
133
134
0
int botan_mp_add_u32(botan_mp_t result, const botan_mp_t x, uint32_t y) {
135
0
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
136
0
      if(result == x)
137
0
         res += static_cast<Botan::word>(y);
138
0
      else
139
0
         res = safe_get(x) + static_cast<Botan::word>(y);
140
0
   });
141
0
}
142
143
0
int botan_mp_sub_u32(botan_mp_t result, const botan_mp_t x, uint32_t y) {
144
0
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
145
0
      if(result == x)
146
0
         res -= static_cast<Botan::word>(y);
147
0
      else
148
0
         res = safe_get(x) - static_cast<Botan::word>(y);
149
0
   });
150
0
}
151
152
0
int botan_mp_mul(botan_mp_t result, const botan_mp_t x, const botan_mp_t y) {
153
0
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
154
0
      if(result == x)
155
0
         res *= safe_get(y);
156
0
      else
157
0
         res = safe_get(x) * safe_get(y);
158
0
   });
159
0
}
160
161
0
int botan_mp_div(botan_mp_t quotient, botan_mp_t remainder, const botan_mp_t x, const botan_mp_t y) {
162
0
   return BOTAN_FFI_VISIT(quotient, [=](auto& q) {
163
0
      Botan::BigInt r;
164
0
      Botan::vartime_divide(safe_get(x), safe_get(y), q, r);
165
0
      safe_get(remainder) = r;
166
0
   });
167
0
}
168
169
0
int botan_mp_equal(const botan_mp_t x_w, const botan_mp_t y_w) {
170
0
   return BOTAN_FFI_VISIT(x_w, [=](const auto& x) -> int { return x == safe_get(y_w); });
171
0
}
172
173
0
int botan_mp_is_zero(const botan_mp_t mp) {
174
0
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) -> int { return bn.is_zero(); });
175
0
}
176
177
0
int botan_mp_is_odd(const botan_mp_t mp) {
178
0
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) -> int { return bn.is_odd(); });
179
0
}
180
181
0
int botan_mp_is_even(const botan_mp_t mp) {
182
0
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) -> int { return bn.is_even(); });
183
0
}
184
185
0
int botan_mp_cmp(int* result, const botan_mp_t x_w, const botan_mp_t y_w) {
186
0
   return BOTAN_FFI_VISIT(x_w, [=](auto& x) { *result = x.cmp(safe_get(y_w)); });
187
0
}
188
189
0
int botan_mp_swap(botan_mp_t x_w, botan_mp_t y_w) {
190
0
   return BOTAN_FFI_VISIT(x_w, [=](auto& x) { x.swap(safe_get(y_w)); });
191
0
}
192
193
// Return (base^exponent) % modulus
194
0
int botan_mp_powmod(botan_mp_t out, const botan_mp_t base, const botan_mp_t exponent, const botan_mp_t modulus) {
195
0
   return BOTAN_FFI_VISIT(
196
0
      out, [=](auto& o) { o = Botan::power_mod(safe_get(base), safe_get(exponent), safe_get(modulus)); });
197
0
}
198
199
0
int botan_mp_lshift(botan_mp_t out, const botan_mp_t in, size_t shift) {
200
0
   return BOTAN_FFI_VISIT(out, [=](auto& o) { o = safe_get(in) << shift; });
201
0
}
202
203
0
int botan_mp_rshift(botan_mp_t out, const botan_mp_t in, size_t shift) {
204
0
   return BOTAN_FFI_VISIT(out, [=](auto& o) { o = safe_get(in) >> shift; });
205
0
}
206
207
0
int botan_mp_mod_inverse(botan_mp_t out, const botan_mp_t in, const botan_mp_t modulus) {
208
0
   return BOTAN_FFI_VISIT(out, [=](auto& o) { o = Botan::inverse_mod(safe_get(in), safe_get(modulus)); });
209
0
}
210
211
0
int botan_mp_mod_mul(botan_mp_t out, const botan_mp_t x, const botan_mp_t y, const botan_mp_t modulus) {
212
0
   return BOTAN_FFI_VISIT(out, [=](auto& o) {
213
0
      Botan::Modular_Reducer reducer(safe_get(modulus));
214
0
      o = reducer.multiply(safe_get(x), safe_get(y));
215
0
   });
216
0
}
217
218
0
int botan_mp_rand_bits(botan_mp_t rand_out, botan_rng_t rng, size_t bits) {
219
0
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { safe_get(rand_out).randomize(r, bits); });
220
0
}
221
222
0
int botan_mp_rand_range(botan_mp_t rand_out, botan_rng_t rng, const botan_mp_t lower, const botan_mp_t upper) {
223
0
   return BOTAN_FFI_VISIT(
224
0
      rng, [=](auto& r) { safe_get(rand_out) = Botan::BigInt::random_integer(r, safe_get(lower), safe_get(upper)); });
225
0
}
226
227
0
int botan_mp_gcd(botan_mp_t out, const botan_mp_t x, const botan_mp_t y) {
228
0
   return BOTAN_FFI_VISIT(out, [=](auto& o) { o = Botan::gcd(safe_get(x), safe_get(y)); });
229
0
}
230
231
0
int botan_mp_is_prime(const botan_mp_t mp, botan_rng_t rng, size_t test_prob) {
232
0
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) { return (Botan::is_prime(n, safe_get(rng), test_prob)) ? 1 : 0; });
233
0
}
234
235
0
int botan_mp_get_bit(const botan_mp_t mp, size_t bit) {
236
0
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) -> int { return n.get_bit(bit); });
237
0
}
238
239
0
int botan_mp_set_bit(botan_mp_t mp, size_t bit) {
240
0
   return BOTAN_FFI_VISIT(mp, [=](auto& n) { n.set_bit(bit); });
241
0
}
242
243
0
int botan_mp_clear_bit(botan_mp_t mp, size_t bit) {
244
0
   return BOTAN_FFI_VISIT(mp, [=](auto& n) { n.clear_bit(bit); });
245
0
}
246
247
0
int botan_mp_num_bits(const botan_mp_t mp, size_t* bits) {
248
0
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) { *bits = n.bits(); });
249
0
}
250
251
0
int botan_mp_num_bytes(const botan_mp_t mp, size_t* bytes) {
252
0
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) { *bytes = n.bytes(); });
253
0
}
254
}