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

randombit / botan / 26864473078

02 Jun 2026 07:58PM UTC coverage: 89.389% (+0.02%) from 89.37%
26864473078

push

github

web-flow
Merge pull request #5639 from randombit/jack/sm4-hwaes-ks

Add hwaes hook for SM4 key schedule

110434 of 123543 relevant lines covered (89.39%)

11152828.24 hits per line

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

96.04
/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/assert.h>
11
#include <botan/numthry.h>
12
#include <botan/internal/barrett.h>
13
#include <botan/internal/divide.h>
14
#include <botan/internal/ffi_mp.h>
15
#include <botan/internal/ffi_rng.h>
16
#include <botan/internal/ffi_util.h>
17
#include <botan/internal/mem_utils.h>
18
#include <botan/internal/mod_inv.h>
19

20
extern "C" {
21

22
using namespace Botan_FFI;
23

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

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

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

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

43
int botan_mp_set_from_str(botan_mp_t mp, const char* str) {
41✔
44
   if(str == nullptr) {
41✔
45
      return BOTAN_FFI_ERROR_NULL_POINTER;
46
   }
47

48
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) { bn = Botan::BigInt(str); });
82✔
49
}
50

51
int botan_mp_set_from_radix_str(botan_mp_t mp, const char* str, size_t radix) {
12✔
52
   if(str == nullptr) {
12✔
53
      return BOTAN_FFI_ERROR_NULL_POINTER;
54
   }
55

56
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) {
24✔
57
      if(radix != 10 && radix != 16) {
58
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
59
      }
60

61
      bn = Botan::BigInt::from_radix_digits(std::string_view(str), radix);
62
      return BOTAN_FFI_SUCCESS;
63
   });
64
}
65

66
// NOLINTBEGIN(misc-misplaced-const)
67

68
int botan_mp_set_from_mp(botan_mp_t dest, const botan_mp_t source) {
4✔
69
   return BOTAN_FFI_VISIT(dest, [=](auto& bn) { bn = safe_get(source); });
8✔
70
}
71

72
int botan_mp_is_negative(const botan_mp_t mp) {
10✔
73
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) { return bn.signum() < 0 ? 1 : 0; });
20✔
74
}
75

76
int botan_mp_is_positive(const botan_mp_t mp) {
6✔
77
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) { return bn.signum() >= 0 ? 1 : 0; });
12✔
78
}
79

80
int botan_mp_flip_sign(botan_mp_t mp) {
5✔
81
   return BOTAN_FFI_VISIT(mp, [](auto& bn) { bn.flip_sign(); });
15✔
82
}
83

84
int botan_mp_from_bin(botan_mp_t mp, const uint8_t bin[], size_t bin_len) {
1✔
85
   if(bin_len > 0 && bin == nullptr) {
1✔
86
      return BOTAN_FFI_ERROR_NULL_POINTER;
87
   }
88
   return BOTAN_FFI_VISIT(mp, [=](auto& bn) { bn._assign_from_bytes({bin, bin_len}); });
2✔
89
}
90

91
int botan_mp_to_hex(const botan_mp_t mp, char* out) {
3✔
92
   if(out == nullptr) {
3✔
93
      return BOTAN_FFI_ERROR_NULL_POINTER;
94
   }
95
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) {
6✔
96
      const std::string hex = bn.to_hex_string();
97

98
      // Check that we are about to write no more than the documented upper bound
99
      const size_t upper_bound = 2 * bn.bytes() + 5;
100
      BOTAN_ASSERT_NOMSG(hex.size() + 1 <= upper_bound);
101
      std::memcpy(out, hex.c_str(), 1 + hex.size());
102
   });
103
}
104

105
int botan_mp_view_hex(const botan_mp_t mp, botan_view_ctx ctx, botan_view_str_fn view) {
36✔
106
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) -> int {
108✔
107
      const std::string hex = bn.to_hex_string();
108
      return invoke_view_callback(view, ctx, hex);
109
   });
110
}
111

112
int botan_mp_to_str(const botan_mp_t mp, uint8_t radix, char* out, size_t* out_len) {
14✔
113
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) -> int {
28✔
114
      if(radix == 0 || radix == 10) {
115
         return write_str_output(out, out_len, bn.to_dec_string());
116
      } else if(radix == 16) {
117
         return write_str_output(out, out_len, bn.to_hex_string());
118
      } else {
119
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
120
      }
121
   });
122
}
123

124
int botan_mp_view_str(const botan_mp_t mp, uint8_t radix, botan_view_ctx ctx, botan_view_str_fn view) {
3✔
125
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) -> int {
9✔
126
      if(radix == 10) {
127
         return invoke_view_callback(view, ctx, bn.to_dec_string());
128
      } else if(radix == 16) {
129
         return invoke_view_callback(view, ctx, bn.to_hex_string());
130
      } else {
131
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
132
      }
133
   });
134
}
135

136
int botan_mp_to_bin(const botan_mp_t mp, uint8_t vec[]) {
3✔
137
   if(vec == nullptr) {
3✔
138
      return BOTAN_FFI_ERROR_NULL_POINTER;
139
   }
140
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) { bn.serialize_to(std::span{vec, bn.bytes()}); });
6✔
141
}
142

143
int botan_mp_view_bin(const botan_mp_t mp, botan_view_ctx ctx, botan_view_bin_fn view) {
3✔
144
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) {
15✔
145
      const auto bytes = bn.serialize();
146
      return invoke_view_callback(view, ctx, bytes);
147
   });
148
}
149

150
int botan_mp_to_uint32(const botan_mp_t mp, uint32_t* val) {
5✔
151
   if(val == nullptr) {
5✔
152
      return BOTAN_FFI_ERROR_NULL_POINTER;
153
   }
154
   return BOTAN_FFI_VISIT(mp, [=](const auto& bn) { *val = bn.to_u32bit(); });
10✔
155
}
156

157
int botan_mp_destroy(botan_mp_t mp) {
190✔
158
   return BOTAN_FFI_CHECKED_DELETE(mp);
190✔
159
}
160

161
int botan_mp_add(botan_mp_t result, const botan_mp_t x, const botan_mp_t y) {
5✔
162
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
10✔
163
      if(result == x) {
164
         res += safe_get(y);
165
      } else {
166
         res = safe_get(x) + safe_get(y);
167
      }
168
   });
169
}
170

171
int botan_mp_sub(botan_mp_t result, const botan_mp_t x, const botan_mp_t y) {
2✔
172
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
4✔
173
      if(result == x) {
174
         res -= safe_get(y);
175
      } else {
176
         res = safe_get(x) - safe_get(y);
177
      }
178
   });
179
}
180

181
int botan_mp_add_u32(botan_mp_t result, const botan_mp_t x, uint32_t y) {
2✔
182
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
4✔
183
      if(result == x) {
184
         res += static_cast<Botan::word>(y);
185
      } else {
186
         res = safe_get(x) + static_cast<Botan::word>(y);
187
      }
188
   });
189
}
190

191
int botan_mp_sub_u32(botan_mp_t result, const botan_mp_t x, uint32_t y) {
2✔
192
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
4✔
193
      if(result == x) {
194
         res -= static_cast<Botan::word>(y);
195
      } else {
196
         res = safe_get(x) - static_cast<Botan::word>(y);
197
      }
198
   });
199
}
200

201
int botan_mp_mul(botan_mp_t result, const botan_mp_t x, const botan_mp_t y) {
6✔
202
   return BOTAN_FFI_VISIT(result, [=](auto& res) {
12✔
203
      if(result == x) {
204
         res *= safe_get(y);
205
      } else {
206
         res = safe_get(x) * safe_get(y);
207
      }
208
   });
209
}
210

211
int botan_mp_div(botan_mp_t quotient, botan_mp_t remainder, const botan_mp_t x, const botan_mp_t y) {
2✔
212
   return BOTAN_FFI_VISIT(quotient, [=](auto& q) {
4✔
213
      Botan::BigInt r;
214
      Botan::vartime_divide(safe_get(x), safe_get(y), q, r);
215
      safe_get(remainder) = r;
216
   });
217
}
218

219
int botan_mp_equal(const botan_mp_t x_w, const botan_mp_t y_w) {
25✔
220
   return BOTAN_FFI_VISIT(x_w, [=](const auto& x) -> int { return x == safe_get(y_w); });
50✔
221
}
222

223
int botan_mp_is_zero(const botan_mp_t mp) {
3✔
224
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) -> int { return bn.is_zero(); });
6✔
225
}
226

227
int botan_mp_is_odd(const botan_mp_t mp) {
2✔
228
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) -> int { return bn.is_odd(); });
5✔
229
}
230

231
int botan_mp_is_even(const botan_mp_t mp) {
2✔
232
   return BOTAN_FFI_VISIT(mp, [](const auto& bn) -> int { return bn.is_even(); });
5✔
233
}
234

235
int botan_mp_cmp(int* result, const botan_mp_t x_w, const botan_mp_t y_w) {
46✔
236
   if(result == nullptr) {
46✔
237
      return BOTAN_FFI_ERROR_NULL_POINTER;
238
   }
239
   return BOTAN_FFI_VISIT(x_w, [=](auto& x) { *result = x.cmp(safe_get(y_w)); });
92✔
240
}
241

242
int botan_mp_swap(botan_mp_t x_w, botan_mp_t y_w) {
×
243
   return BOTAN_FFI_VISIT(x_w, [=](auto& x) { x.swap(safe_get(y_w)); });
×
244
}
245

246
// Return (base^exponent) % modulus
247
int botan_mp_powmod(botan_mp_t out, const botan_mp_t base, const botan_mp_t exponent, const botan_mp_t modulus) {
2✔
248
   return BOTAN_FFI_VISIT(
4✔
249
      out, [=](auto& o) { o = Botan::power_mod(safe_get(base), safe_get(exponent), safe_get(modulus)); });
250
}
251

252
int botan_mp_lshift(botan_mp_t out, const botan_mp_t in, size_t shift) {
3✔
253
   return BOTAN_FFI_VISIT(out, [=](auto& o) { o = safe_get(in) << shift; });
6✔
254
}
255

256
int botan_mp_rshift(botan_mp_t out, const botan_mp_t in, size_t shift) {
4✔
257
   return BOTAN_FFI_VISIT(out, [=](auto& o) { o = safe_get(in) >> shift; });
8✔
258
}
259

260
int botan_mp_mod_inverse(botan_mp_t out, const botan_mp_t in, const botan_mp_t modulus) {
2✔
261
   return BOTAN_FFI_VISIT(out, [=](auto& o) {
4✔
262
      o = Botan::inverse_mod_general(safe_get(in), safe_get(modulus)).value_or(Botan::BigInt::zero());
263
   });
264
}
265

266
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✔
267
   return BOTAN_FFI_VISIT(out, [=](auto& o) {
6✔
268
      auto reducer = Botan::Barrett_Reduction::for_secret_modulus(safe_get(modulus));
269
      o = reducer.multiply(safe_get(x), safe_get(y));
270
   });
271
}
272

273
int botan_mp_rand_bits(botan_mp_t rand_out, botan_rng_t rng, size_t bits) {
2✔
274
   return BOTAN_FFI_VISIT(rng, [=](auto& r) { safe_get(rand_out).randomize(r, bits); });
4✔
275
}
276

277
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✔
278
   return BOTAN_FFI_VISIT(
30✔
279
      rng, [=](auto& r) { safe_get(rand_out) = Botan::BigInt::random_integer(r, safe_get(lower), safe_get(upper)); });
280
}
281

282
int botan_mp_gcd(botan_mp_t out, const botan_mp_t x, const botan_mp_t y) {
4✔
283
   return BOTAN_FFI_VISIT(out, [=](auto& o) { o = Botan::gcd(safe_get(x), safe_get(y)); });
8✔
284
}
285

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

290
int botan_mp_get_bit(const botan_mp_t mp, size_t bit) {
6✔
291
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) -> int { return n.get_bit(bit); });
12✔
292
}
293

294
int botan_mp_set_bit(botan_mp_t mp, size_t bit) {
2✔
295
   return BOTAN_FFI_VISIT(mp, [=](auto& n) { n.set_bit(bit); });
4✔
296
}
297

298
int botan_mp_clear_bit(botan_mp_t mp, size_t bit) {
2✔
299
   return BOTAN_FFI_VISIT(mp, [=](auto& n) { n.clear_bit(bit); });
4✔
300
}
301

302
int botan_mp_num_bits(const botan_mp_t mp, size_t* bits) {
7✔
303
   if(bits == nullptr) {
7✔
304
      return BOTAN_FFI_ERROR_NULL_POINTER;
305
   }
306
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) { *bits = n.bits(); });
14✔
307
}
308

309
int botan_mp_num_bytes(const botan_mp_t mp, size_t* bytes) {
10✔
310
   if(bytes == nullptr) {
10✔
311
      return BOTAN_FFI_ERROR_NULL_POINTER;
312
   }
313
   return BOTAN_FFI_VISIT(mp, [=](const auto& n) { *bytes = n.bytes(); });
20✔
314
}
315

316
// NOLINTEND(misc-misplaced-const)
317
}
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