Botan 3.12.0
Crypto and TLS for C&
ffi_ec.cpp
Go to the documentation of this file.
1/*
2* (C) 2025 Jack Lloyd
3* (C) 2025,2026 Dominik Schricker
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/ffi.h>
9
10#include <botan/internal/ffi_ec.h>
11#include <botan/internal/ffi_mp.h>
12#include <botan/internal/ffi_oid.h>
13#include <botan/internal/ffi_rng.h>
14#include <botan/internal/ffi_util.h>
15#include <functional>
16
17extern "C" {
18
19using namespace Botan_FFI;
20
22 return BOTAN_FFI_CHECKED_DELETE(ec_group);
23}
24
26 if(out == nullptr) {
28 }
30 *out = 1;
31 } else {
32 *out = 0;
33 }
34 return BOTAN_FFI_SUCCESS;
35}
36
37int botan_ec_group_supports_named_group(const char* name, int* out) {
38 return ffi_guard_thunk(__func__, [=]() -> int {
39 if(name == nullptr || out == nullptr) {
41 }
43 *out = 1;
44 } else {
45 *out = 0;
46 }
47 return BOTAN_FFI_SUCCESS;
48 });
49}
50
53 botan_mp_t p,
54 botan_mp_t a,
55 botan_mp_t b,
56 botan_mp_t base_x,
57 botan_mp_t base_y,
58 botan_mp_t order) {
59 return ffi_guard_thunk(__func__, [=]() -> int {
60 if(ec_group == nullptr) {
62 }
63
64 Botan::EC_Group group(
65 safe_get(oid), safe_get(p), safe_get(a), safe_get(b), safe_get(base_x), safe_get(base_y), safe_get(order));
66
67 auto group_ptr = std::make_unique<Botan::EC_Group>(std::move(group));
68 return ffi_new_object(ec_group, std::move(group_ptr));
69 });
70}
71
72int botan_ec_group_from_ber(botan_ec_group_t* ec_group, const uint8_t* ber, size_t ber_len) {
73 return ffi_guard_thunk(__func__, [=]() -> int {
74 if(ec_group == nullptr || ber == nullptr) {
76 }
77
78 Botan::EC_Group group(ber, ber_len);
79
80 auto group_ptr = std::make_unique<Botan::EC_Group>(std::move(group));
81 return ffi_new_object(ec_group, std::move(group_ptr));
82 });
83}
84
85int botan_ec_group_from_pem(botan_ec_group_t* ec_group, const char* pem) {
86 return ffi_guard_thunk(__func__, [=]() -> int {
87 if(ec_group == nullptr || pem == nullptr) {
89 }
90
92
93 auto group_ptr = std::make_unique<Botan::EC_Group>(std::move(group));
94 return ffi_new_object(ec_group, std::move(group_ptr));
95 });
96}
97
99 return ffi_guard_thunk(__func__, [=]() -> int {
100 if(ec_group == nullptr) {
102 }
103
105
106 auto group_ptr = std::make_unique<Botan::EC_Group>(std::move(group));
107 return ffi_new_object(ec_group, std::move(group_ptr));
108 });
109}
110
111int botan_ec_group_from_name(botan_ec_group_t* ec_group, const char* name) {
112 return ffi_guard_thunk(__func__, [=]() -> int {
113 if(ec_group == nullptr || name == nullptr) {
115 }
116
118
119 auto group_ptr = std::make_unique<Botan::EC_Group>(std::move(group));
120 return ffi_new_object(ec_group, std::move(group_ptr));
121 });
122}
123
125 return BOTAN_FFI_VISIT(oid, [=](const auto& o) -> int { return Botan::EC_Group::unregister(o) ? 1 : 0; });
126}
127
129 return BOTAN_FFI_VISIT(ec_group,
130 [=](const auto& g) -> int { return invoke_view_callback(view, ctx, g.DER_encode()); });
131}
132
134 return BOTAN_FFI_VISIT(ec_group, [=](const auto& g) -> int {
135 return invoke_view_callback(view, ctx, g.PEM_encode(Botan::EC_Group_Encoding::NamedCurve));
136 });
137}
138
140 return BOTAN_FFI_VISIT(ec_group, [=](const auto& g) -> int {
141 if(oid == nullptr) {
143 }
144 auto oid_ptr = std::make_unique<Botan::OID>(g.get_curve_oid());
145 return ffi_new_object(oid, std::move(oid_ptr));
146 });
147}
148
149namespace {
150int botan_ec_group_get_component(botan_mp_t* out,
151 botan_ec_group_t ec_group,
152 const std::function<const Botan::BigInt&(const Botan::EC_Group&)>& getter) {
153 return BOTAN_FFI_VISIT(ec_group, [=](const auto& g) -> int {
154 if(out == nullptr) {
156 }
157 auto val = std::make_unique<Botan::BigInt>(getter(g));
158 return ffi_new_object(out, std::move(val));
159 });
160}
161} // namespace
162
164 return botan_ec_group_get_component(p, ec_group, [](const auto& g) -> const Botan::BigInt& { return g.get_p(); });
165}
166
168 return botan_ec_group_get_component(a, ec_group, [](const auto& g) -> const Botan::BigInt& { return g.get_a(); });
169}
170
172 return botan_ec_group_get_component(b, ec_group, [](const auto& g) -> const Botan::BigInt& { return g.get_b(); });
173}
174
176 return botan_ec_group_get_component(
177 g_x, ec_group, [](const auto& g) -> const Botan::BigInt& { return g.get_g_x(); });
178}
179
181 return botan_ec_group_get_component(
182 g_y, ec_group, [](const auto& g) -> const Botan::BigInt& { return g.get_g_y(); });
183}
184
186 return botan_ec_group_get_component(
187 order, ec_group, [](const auto& g) -> const Botan::BigInt& { return g.get_order(); });
188}
189
191 return BOTAN_FFI_VISIT(curve1_w, [=](const auto& curve1) -> int { return curve1 == safe_get(curve2_w); });
192}
193
194// ec scalars
195
197 return BOTAN_FFI_CHECKED_DELETE(ec_scalar);
198}
199
201 if(Botan::any_null_pointers(ec_scalar)) {
203 }
204 return BOTAN_FFI_VISIT(ec_group, [=](const auto& g) -> int {
205 return ffi_new_object(ec_scalar, std::make_unique<Botan::EC_Scalar>(Botan::EC_Scalar::random(g, safe_get(rng))));
206 });
207}
208
210 if(Botan::any_null_pointers(ec_scalar)) {
212 }
213 return BOTAN_FFI_VISIT(ec_group, [=](const auto& g) -> int {
214 return ffi_new_object(ec_scalar,
215 std::make_unique<Botan::EC_Scalar>(Botan::EC_Scalar::from_bigint(g, safe_get(mp))));
216 });
217}
218
222 }
223 return BOTAN_FFI_VISIT(ec_scalar, [=](const auto& sc) -> int {
224 return ffi_new_object(mp, std::make_unique<Botan::BigInt>(sc.to_bigint()));
225 });
226}
227
228// ec points
229
231 return BOTAN_FFI_CHECKED_DELETE(ec_point);
232}
233
235 if(Botan::any_null_pointers(ec_point)) {
237 }
238 return BOTAN_FFI_VISIT(ec_group, [=](const auto& g) -> int {
239 return ffi_new_object(ec_point, std::make_unique<Botan::EC_AffinePoint>(Botan::EC_AffinePoint::identity(g)));
240 });
241}
242
244 if(Botan::any_null_pointers(ec_point)) {
246 }
247 return BOTAN_FFI_VISIT(ec_group, [=](const auto& g) -> int {
248 return ffi_new_object(ec_point, std::make_unique<Botan::EC_AffinePoint>(Botan::EC_AffinePoint::generator(g)));
249 });
250}
251
253 if(Botan::any_null_pointers(ec_point)) {
255 }
256 return ffi_guard_thunk(__func__, [=]() -> int {
257 std::optional<Botan::EC_AffinePoint> pt =
259 if(!pt.has_value()) {
261 }
262
263 return ffi_new_object(ec_point, std::make_unique<Botan::EC_AffinePoint>(pt.value()));
264 });
265}
266
268 botan_ec_group_t ec_group,
269 const uint8_t* bytes,
270 size_t bytes_len) {
271 if(Botan::any_null_pointers(ec_point, bytes)) {
273 }
274 return BOTAN_FFI_VISIT(ec_group, [=](const auto& g) -> int {
275 Botan::EC_AffinePoint pt(g, std::span{bytes, bytes_len});
276 return ffi_new_object(ec_point, std::make_unique<Botan::EC_AffinePoint>(std::move(pt)));
277 });
278}
279
281 return BOTAN_FFI_VISIT(ec_point, [=](const auto& p) -> int {
282 auto bytes = p.x_bytes();
283 return invoke_view_callback(view, ctx, bytes);
284 });
285}
286
288 return BOTAN_FFI_VISIT(ec_point, [=](const auto& p) -> int {
289 auto bytes = p.y_bytes();
290 return invoke_view_callback(view, ctx, bytes);
291 });
292}
293
295 return BOTAN_FFI_VISIT(ec_point, [=](const auto& p) -> int {
296 auto bytes = p.xy_bytes();
297 return invoke_view_callback(view, ctx, bytes);
298 });
299}
300
302 return BOTAN_FFI_VISIT(ec_point, [=](const auto& p) -> int {
303 auto bytes = p.serialize_uncompressed();
304 return invoke_view_callback(view, ctx, bytes);
305 });
306}
307
309 return BOTAN_FFI_VISIT(ec_point, [=](const auto& p) -> int {
310 auto bytes = p.serialize_compressed();
311 return invoke_view_callback(view, ctx, bytes);
312 });
313}
314
316 return BOTAN_FFI_VISIT(ec_point, [=](const auto& p) -> int { return p.is_identity() ? 1 : 0; });
317}
318
320 return BOTAN_FFI_VISIT(x_w, [=](const auto& x) -> int { return x == safe_get(y_w) ? 1 : 0; });
321}
322
324 botan_ec_point_t ec_point,
325 botan_ec_scalar_t ec_scalar,
326 botan_rng_t rng) {
327 if(Botan::any_null_pointers(result)) {
329 }
330 return BOTAN_FFI_VISIT(ec_point, [=](auto& pt) -> int {
331 Botan::EC_AffinePoint res = pt.mul(safe_get(ec_scalar), safe_get(rng));
332 return ffi_new_object(result, std::make_unique<Botan::EC_AffinePoint>(std::move(res)));
333 });
334}
335
337 if(Botan::any_null_pointers(result)) {
339 }
340 return BOTAN_FFI_VISIT(ec_point, [=](auto& pt) -> int {
341 Botan::EC_AffinePoint res = pt.negate();
342 return ffi_new_object(result, std::make_unique<Botan::EC_AffinePoint>(std::move(res)));
343 });
344}
345
347 if(Botan::any_null_pointers(result)) {
349 }
350 return BOTAN_FFI_VISIT(x_w, [=](auto& x) -> int {
351 Botan::EC_AffinePoint res = x.add(safe_get(y_w));
352 return ffi_new_object(result, std::make_unique<Botan::EC_AffinePoint>(std::move(res)));
353 });
354}
355}
EC_AffinePoint negate() const
Point negation.
static EC_AffinePoint identity(const EC_Group &group)
Return the identity element.
Definition ec_apoint.cpp:79
static std::optional< EC_AffinePoint > from_bigint_xy(const EC_Group &group, const BigInt &x, const BigInt &y)
Definition ec_apoint.cpp:93
EC_AffinePoint mul(const EC_Scalar &scalar, RandomNumberGenerator &rng) const
Multiply a point by a scalar returning a complete point.
EC_AffinePoint add(const EC_AffinePoint &q) const
static EC_AffinePoint generator(const EC_Group &group)
Return the standard group generator.
Definition ec_apoint.cpp:84
static EC_Group from_name(std::string_view name)
Definition ec_group.cpp:468
static EC_Group from_PEM(std::string_view pem)
Definition ec_group.cpp:511
static EC_Group from_OID(const OID &oid)
Definition ec_group.cpp:457
static bool supports_application_specific_group()
Definition ec_group.cpp:439
static bool unregister(const OID &oid)
Definition ec_group.cpp:612
static bool supports_named_group(std::string_view name)
Definition ec_group.cpp:412
static EC_Scalar from_bigint(const EC_Group &group, const BigInt &bn)
Definition ec_scalar.cpp:69
static EC_Scalar random(const EC_Group &group, RandomNumberGenerator &rng)
Definition ec_scalar.cpp:61
struct botan_asn1_oid_struct * botan_asn1_oid_t
Definition ffi.h:1253
struct botan_ec_group_struct * botan_ec_group_t
Definition ffi.h:1302
int(* botan_view_bin_fn)(botan_view_ctx view_ctx, const uint8_t *data, size_t len)
Definition ffi.h:163
struct botan_mp_struct * botan_mp_t
Definition ffi.h:1032
void * botan_view_ctx
Definition ffi.h:154
struct botan_rng_struct * botan_rng_t
Definition ffi.h:291
struct botan_ec_scalar_struct * botan_ec_scalar_t
Definition ffi.h:1446
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:133
@ BOTAN_FFI_SUCCESS
Definition ffi.h:116
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition ffi.h:134
struct botan_ec_point_struct * botan_ec_point_t
Definition ffi.h:1447
int(* botan_view_str_fn)(botan_view_ctx view_ctx, const char *str, size_t len)
Definition ffi.h:172
int botan_ec_group_get_g_x(botan_mp_t *g_x, botan_ec_group_t ec_group)
Definition ffi_ec.cpp:175
int botan_ec_point_destroy(botan_ec_point_t ec_point)
Definition ffi_ec.cpp:230
int botan_ec_point_equal(botan_ec_point_t x_w, botan_ec_point_t y_w)
Definition ffi_ec.cpp:319
int botan_ec_group_view_pem(botan_ec_group_t ec_group, botan_view_ctx ctx, botan_view_str_fn view)
Definition ffi_ec.cpp:133
int botan_ec_group_get_curve_oid(botan_asn1_oid_t *oid, botan_ec_group_t ec_group)
Definition ffi_ec.cpp:139
int botan_ec_group_from_params(botan_ec_group_t *ec_group, botan_asn1_oid_t oid, botan_mp_t p, botan_mp_t a, botan_mp_t b, botan_mp_t base_x, botan_mp_t base_y, botan_mp_t order)
Definition ffi_ec.cpp:51
int botan_ec_group_get_g_y(botan_mp_t *g_y, botan_ec_group_t ec_group)
Definition ffi_ec.cpp:180
int botan_ec_point_mul(botan_ec_point_t *result, botan_ec_point_t ec_point, botan_ec_scalar_t ec_scalar, botan_rng_t rng)
Definition ffi_ec.cpp:323
int botan_ec_point_add(botan_ec_point_t *result, botan_ec_point_t x_w, botan_ec_point_t y_w)
Definition ffi_ec.cpp:346
int botan_ec_point_generator(botan_ec_point_t *ec_point, botan_ec_group_t ec_group)
Definition ffi_ec.cpp:243
int botan_ec_scalar_to_mp(botan_ec_scalar_t ec_scalar, botan_mp_t *mp)
Definition ffi_ec.cpp:219
int botan_ec_group_get_a(botan_mp_t *a, botan_ec_group_t ec_group)
Definition ffi_ec.cpp:167
int botan_ec_point_view_x_bytes(botan_ec_point_t ec_point, botan_view_ctx ctx, botan_view_bin_fn view)
Definition ffi_ec.cpp:280
int botan_ec_group_view_der(botan_ec_group_t ec_group, botan_view_ctx ctx, botan_view_bin_fn view)
Definition ffi_ec.cpp:128
int botan_ec_group_supports_named_group(const char *name, int *out)
Definition ffi_ec.cpp:37
int botan_ec_point_from_bytes(botan_ec_point_t *ec_point, botan_ec_group_t ec_group, const uint8_t *bytes, size_t bytes_len)
Definition ffi_ec.cpp:267
int botan_ec_group_equal(botan_ec_group_t curve1_w, botan_ec_group_t curve2_w)
Definition ffi_ec.cpp:190
int botan_ec_group_get_order(botan_mp_t *order, botan_ec_group_t ec_group)
Definition ffi_ec.cpp:185
int botan_ec_point_identity(botan_ec_point_t *ec_point, botan_ec_group_t ec_group)
Definition ffi_ec.cpp:234
int botan_ec_group_from_oid(botan_ec_group_t *ec_group, botan_asn1_oid_t oid)
Definition ffi_ec.cpp:98
int botan_ec_scalar_from_mp(botan_ec_scalar_t *ec_scalar, botan_ec_group_t ec_group, botan_mp_t mp)
Definition ffi_ec.cpp:209
int botan_ec_group_from_name(botan_ec_group_t *ec_group, const char *name)
Definition ffi_ec.cpp:111
int botan_ec_group_supports_application_specific_group(int *out)
Definition ffi_ec.cpp:25
int botan_ec_group_destroy(botan_ec_group_t ec_group)
Definition ffi_ec.cpp:21
int botan_ec_point_negate(botan_ec_point_t *result, botan_ec_point_t ec_point)
Definition ffi_ec.cpp:336
int botan_ec_point_view_xy_bytes(botan_ec_point_t ec_point, botan_view_ctx ctx, botan_view_bin_fn view)
Definition ffi_ec.cpp:294
int botan_ec_point_from_xy(botan_ec_point_t *ec_point, botan_ec_group_t ec_group, botan_mp_t x, botan_mp_t y)
Definition ffi_ec.cpp:252
int botan_ec_group_unregister(botan_asn1_oid_t oid)
Definition ffi_ec.cpp:124
int botan_ec_group_get_b(botan_mp_t *b, botan_ec_group_t ec_group)
Definition ffi_ec.cpp:171
int botan_ec_group_get_p(botan_mp_t *p, botan_ec_group_t ec_group)
Definition ffi_ec.cpp:163
int botan_ec_group_from_ber(botan_ec_group_t *ec_group, const uint8_t *ber, size_t ber_len)
Definition ffi_ec.cpp:72
int botan_ec_scalar_destroy(botan_ec_scalar_t ec_scalar)
Definition ffi_ec.cpp:196
int botan_ec_group_from_pem(botan_ec_group_t *ec_group, const char *pem)
Definition ffi_ec.cpp:85
int botan_ec_scalar_random(botan_ec_scalar_t *ec_scalar, botan_ec_group_t ec_group, botan_rng_t rng)
Definition ffi_ec.cpp:200
int botan_ec_point_view_uncompressed(botan_ec_point_t ec_point, botan_view_ctx ctx, botan_view_bin_fn view)
Definition ffi_ec.cpp:301
int botan_ec_point_view_y_bytes(botan_ec_point_t ec_point, botan_view_ctx ctx, botan_view_bin_fn view)
Definition ffi_ec.cpp:287
int botan_ec_point_is_identity(botan_ec_point_t ec_point)
Definition ffi_ec.cpp:315
int botan_ec_point_view_compressed(botan_ec_point_t ec_point, botan_view_ctx ctx, botan_view_bin_fn view)
Definition ffi_ec.cpp:308
#define BOTAN_FFI_VISIT(obj, lambda)
Definition ffi_util.h:158
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition ffi_util.h:188
int invoke_view_callback(botan_view_bin_fn view, botan_view_ctx ctx, std::span< const uint8_t > buf)
Definition ffi_util.h:190
T & safe_get(botan_struct< T, M > *p)
Definition ffi_util.h:79
BOTAN_FFI_ERROR ffi_new_object(T *obj, Args &&... args)
Definition ffi_util.h:178
int ffi_guard_thunk(const char *func_name, T thunk)
Definition ffi_util.h:95
bool any_null_pointers(Ptrs... ptr)
Definition mem_utils.h:54