/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 | | } |