• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 16293079084

15 Jul 2025 12:20PM UTC coverage: 90.627% (+0.003%) from 90.624%
16293079084

push

github

web-flow
Merge pull request #4990 from randombit/jack/string-and-span

Improve string<->span conversions

99640 of 109945 relevant lines covered (90.63%)

12253617.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.4
/src/lib/ffi/ffi_mp.cpp
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/internal/barrett.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
#include <botan/internal/mem_utils.h>
17
#include <botan/internal/mod_inv.h>
18

19
extern "C" {
20

21
using namespace Botan_FFI;
22

23
int botan_mp_init(botan_mp_t* mp_out) {
151✔
24
   return ffi_guard_thunk(__func__, [=]() -> int {
151✔
25
      if(mp_out == nullptr) {
151✔
26
         return BOTAN_FFI_ERROR_NULL_POINTER;
27
      }
28

29
      auto mp = std::make_unique<Botan::BigInt>();
151✔
30
      return ffi_new_object(mp_out, std::move(mp));
151✔
31
   });
151✔
32
}
33

34
int botan_mp_clear(botan_mp_t mp) {
×
35
   return BOTAN_FFI_VISIT(mp, [](auto& bn) { bn.clear(); });
×
36
}
37

38
int botan_mp_set_from_int(botan_mp_t mp, int initial_value) {
2✔
39
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) { bn = Botan::BigInt::from_s32(initial_value); });
4✔
40
}
41

42
int botan_mp_set_from_str(botan_mp_t mp, const char* str) {
35✔
43
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) { bn = Botan::BigInt(str); });
70✔
44
}
45

46
int botan_mp_set_from_radix_str(botan_mp_t mp, const char* str, size_t radix) {
10✔
47
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) {
20✔
48
      Botan::BigInt::Base base;
49
      if(radix == 10) {
50
         base = Botan::BigInt::Decimal;
51
      } else if(radix == 16) {
52
         base = Botan::BigInt::Hexadecimal;
53
      } else {
54
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
55
      }
56

57
      bn = Botan::BigInt::decode(Botan::cstr_as_span_of_bytes(str), base);
58
      return BOTAN_FFI_SUCCESS;
59
   });
60
}
61

62
int botan_mp_set_from_mp(botan_mp_t dest, const botan_mp_t source) {
4✔
63
   return BOTAN_FFI_VISIT(dest, [=](auto& bn) { bn = safe_get(source); });
8✔
64
}
65

66
int botan_mp_is_negative(const botan_mp_t mp) {
10✔
67
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) { return bn.is_negative() ? 1 : 0; });
20✔
68
}
69

70
int botan_mp_is_positive(const botan_mp_t mp) {
6✔
71
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) { return bn.is_positive() ? 1 : 0; });
12✔
72
}
73

74
int botan_mp_flip_sign(botan_mp_t mp) {
5✔
75
   return BOTAN_FFI_VISIT(mp, [](auto& bn) { bn.flip_sign(); });
15✔
76
}
77

78
int botan_mp_from_bin(botan_mp_t mp, const uint8_t bin[], size_t bin_len) {
1✔
79
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) { bn._assign_from_bytes({bin, bin_len}); });
2✔
80
}
81

82
int botan_mp_to_hex(const botan_mp_t mp, char* out) {
38✔
83
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) {
76✔
84
      const std::string hex = bn.to_hex_string();
85
      std::memcpy(out, hex.c_str(), 1 + hex.size());
86
   });
87
}
88

89
int botan_mp_to_str(const botan_mp_t mp, uint8_t digit_base, char* out, size_t* out_len) {
14✔
90
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) -> int {
28✔
91
      if(digit_base == 0 || digit_base == 10) {
92
         return write_str_output(out, out_len, bn.to_dec_string());
93
      } else if(digit_base == 16) {
94
         return write_str_output(out, out_len, bn.to_hex_string());
95
      } else {
96
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
97
      }
98
   });
99
}
100

101
int botan_mp_to_bin(const botan_mp_t mp, uint8_t vec[]) {
3✔
102
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) { bn.serialize_to(std::span{vec, bn.bytes()}); });
6✔
103
}
104

105
int botan_mp_to_uint32(const botan_mp_t mp, uint32_t* val) {
5✔
106
   if(val == nullptr) {
5✔
107
      return BOTAN_FFI_ERROR_NULL_POINTER;
108
   }
109
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) { *val = bn.to_u32bit(); });
10✔
110
}
111

112
int botan_mp_destroy(botan_mp_t mp) {
171✔
113
   return BOTAN_FFI_CHECKED_DELETE(mp);
171✔
114
}
115

116
int botan_mp_add(botan_mp_t result, const botan_mp_t x, const botan_mp_t y) {
5✔
117
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
10✔
118
      if(result == x) {
119
         res += safe_get(y);
120
      } else {
121
         res = safe_get(x) + safe_get(y);
122
      }
123
   });
124
}
125

126
int botan_mp_sub(botan_mp_t result, const botan_mp_t x, const botan_mp_t y) {
1✔
127
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
2✔
128
      if(result == x) {
129
         res -= safe_get(y);
130
      } else {
131
         res = safe_get(x) - safe_get(y);
132
      }
133
   });
134
}
135

136
int botan_mp_add_u32(botan_mp_t result, const botan_mp_t x, uint32_t y) {
2✔
137
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
4✔
138
      if(result == x) {
139
         res += static_cast<Botan::word>(y);
140
      } else {
141
         res = safe_get(x) + static_cast<Botan::word>(y);
142
      }
143
   });
144
}
145

146
int botan_mp_sub_u32(botan_mp_t result, const botan_mp_t x, uint32_t y) {
1✔
147
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
2✔
148
      if(result == x) {
149
         res -= static_cast<Botan::word>(y);
150
      } else {
151
         res = safe_get(x) - static_cast<Botan::word>(y);
152
      }
153
   });
154
}
155

156
int botan_mp_mul(botan_mp_t result, const botan_mp_t x, const botan_mp_t y) {
6✔
157
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
12✔
158
      if(result == x) {
159
         res *= safe_get(y);
160
      } else {
161
         res = safe_get(x) * safe_get(y);
162
      }
163
   });
164
}
165

166
int botan_mp_div(botan_mp_t quotient, botan_mp_t remainder, const botan_mp_t x, const botan_mp_t y) {
2✔
167
   return BOTAN_FFI_VISIT(quotient, [=](auto& q) {
4✔
168
      Botan::BigInt r;
169
      Botan::vartime_divide(safe_get(x), safe_get(y), q, r);
170
      safe_get(remainder) = r;
171
   });
172
}
173

174
int botan_mp_equal(const botan_mp_t x_w, const botan_mp_t y_w) {
23✔
175
   return BOTAN_FFI_VISIT(x_w, [=](const auto& x) -> int { return x == safe_get(y_w); });
46✔
176
}
177

178
int botan_mp_is_zero(const botan_mp_t mp) {
3✔
179
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) -> int { return bn.is_zero(); });
6✔
180
}
181

182
int botan_mp_is_odd(const botan_mp_t mp) {
2✔
183
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) -> int { return bn.is_odd(); });
5✔
184
}
185

186
int botan_mp_is_even(const botan_mp_t mp) {
2✔
187
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) -> int { return bn.is_even(); });
5✔
188
}
189

190
int botan_mp_cmp(int* result, const botan_mp_t x_w, const botan_mp_t y_w) {
44✔
191
   return BOTAN_FFI_VISIT(x_w, [=](auto& x) { *result = x.cmp(safe_get(y_w)); });
88✔
192
}
193

194
int botan_mp_swap(botan_mp_t x_w, botan_mp_t y_w) {
×
195
   return BOTAN_FFI_VISIT(x_w, [=](auto& x) { x.swap(safe_get(y_w)); });
×
196
}
197

198
// Return (base^exponent) % modulus
199
int botan_mp_powmod(botan_mp_t out, const botan_mp_t base, const botan_mp_t exponent, const botan_mp_t modulus) {
2✔
200
   return BOTAN_FFI_VISIT(
4✔
201
      out, [=](auto& o) { o = Botan::power_mod(safe_get(base), safe_get(exponent), safe_get(modulus)); });
202
}
203

204
int botan_mp_lshift(botan_mp_t out, const botan_mp_t in, size_t shift) {
2✔
205
   return BOTAN_FFI_VISIT(out, [=](auto& o) { o = safe_get(in) << shift; });
4✔
206
}
207

208
int botan_mp_rshift(botan_mp_t out, const botan_mp_t in, size_t shift) {
4✔
209
   return BOTAN_FFI_VISIT(out, [=](auto& o) { o = safe_get(in) >> shift; });
8✔
210
}
211

212
int botan_mp_mod_inverse(botan_mp_t out, const botan_mp_t in, const botan_mp_t modulus) {
2✔
213
   return BOTAN_FFI_VISIT(out, [=](auto& o) {
4✔
214
      o = Botan::inverse_mod_general(safe_get(in), safe_get(modulus)).value_or(Botan::BigInt::zero());
215
   });
216
}
217

218
int botan_mp_mod_mul(botan_mp_t out, const botan_mp_t x, const botan_mp_t y, const botan_mp_t modulus) {
2✔
219
   return BOTAN_FFI_VISIT(out, [=](auto& o) {
6✔
220
      auto reducer = Botan::Barrett_Reduction::for_secret_modulus(safe_get(modulus));
221
      o = reducer.multiply(safe_get(x), safe_get(y));
222
   });
223
}
224

225
int botan_mp_rand_bits(botan_mp_t rand_out, botan_rng_t rng, size_t bits) {
2✔
226
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { safe_get(rand_out).randomize(r, bits); });
4✔
227
}
228

229
int botan_mp_rand_range(botan_mp_t rand_out, botan_rng_t rng, const botan_mp_t lower, const botan_mp_t upper) {
10✔
230
   return BOTAN_FFI_VISIT(
30✔
231
      rng, [=](auto& r) { safe_get(rand_out) = Botan::BigInt::random_integer(r, safe_get(lower), safe_get(upper)); });
232
}
233

234
int botan_mp_gcd(botan_mp_t out, const botan_mp_t x, const botan_mp_t y) {
4✔
235
   return BOTAN_FFI_VISIT(out, [=](auto& o) { o = Botan::gcd(safe_get(x), safe_get(y)); });
8✔
236
}
237

238
int botan_mp_is_prime(const botan_mp_t mp, botan_rng_t rng, size_t test_prob) {
5✔
239
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) { return (Botan::is_prime(n, safe_get(rng), test_prob)) ? 1 : 0; });
10✔
240
}
241

242
int botan_mp_get_bit(const botan_mp_t mp, size_t bit) {
6✔
243
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) -> int { return n.get_bit(bit); });
12✔
244
}
245

246
int botan_mp_set_bit(botan_mp_t mp, size_t bit) {
2✔
247
   return BOTAN_FFI_VISIT(mp, [=](auto& n) { n.set_bit(bit); });
4✔
248
}
249

250
int botan_mp_clear_bit(botan_mp_t mp, size_t bit) {
2✔
251
   return BOTAN_FFI_VISIT(mp, [=](auto& n) { n.clear_bit(bit); });
4✔
252
}
253

254
int botan_mp_num_bits(const botan_mp_t mp, size_t* bits) {
7✔
255
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) { *bits = n.bits(); });
14✔
256
}
257

258
int botan_mp_num_bytes(const botan_mp_t mp, size_t* bytes) {
45✔
259
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) { *bytes = n.bytes(); });
90✔
260
}
261
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc