Botan 3.6.1
Crypto and TLS for C&
ffi_srp6.cpp
Go to the documentation of this file.
1/*
2* (C) 2022 Rostyslav Khudolii
3* 2023 Jack Lloyd
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_rng.h>
11#include <botan/internal/ffi_util.h>
12
13#if defined(BOTAN_HAS_SRP6)
14 #include <botan/bigint.h>
15 #include <botan/dl_group.h>
16 #include <botan/rng.h>
17 #include <botan/srp6.h>
18 #include <botan/symkey.h>
19#endif
20
21extern "C" {
22
23using namespace Botan_FFI;
24
25#if defined(BOTAN_HAS_SRP6)
26BOTAN_FFI_DECLARE_STRUCT(botan_srp6_server_session_struct, Botan::SRP6_Server_Session, 0x44F7425F);
27#else
28BOTAN_FFI_DECLARE_DUMMY_STRUCT(botan_srp6_server_session_struct, 0x44F7425F);
29#endif
30
32#if defined(BOTAN_HAS_SRP6)
33 return ffi_guard_thunk(__func__, [=]() -> int {
34 *srp6 = new botan_srp6_server_session_struct(std::make_unique<Botan::SRP6_Server_Session>());
35 return BOTAN_FFI_SUCCESS;
36 });
37#else
38 BOTAN_UNUSED(srp6);
40#endif
41}
42
46
47int botan_srp6_group_size(const char* group_id, size_t* group_p_bytes) {
48#if defined(BOTAN_HAS_SRP6)
49 if(group_id == nullptr || group_p_bytes == nullptr) {
51 }
52
53 return ffi_guard_thunk(__func__, [=]() -> int {
54 Botan::DL_Group group(group_id);
55 *group_p_bytes = group.p_bytes();
56 return BOTAN_FFI_SUCCESS;
57 });
58#else
59 BOTAN_UNUSED(group_id, group_p_bytes);
61#endif
62}
63
65 const uint8_t* verifier,
66 size_t verifier_len,
67 const char* group_id,
68 const char* hash_id,
69 botan_rng_t rng_obj,
70 uint8_t b_pub[],
71 size_t* b_pub_len) {
72#if defined(BOTAN_HAS_SRP6)
73 return BOTAN_FFI_VISIT(srp6, [=](auto& s) -> int {
74 if(!verifier || !group_id || !hash_id || !rng_obj) {
76 }
77 try {
79 auto v_bn = Botan::BigInt::from_bytes(std::span{verifier, verifier_len});
80 auto b_pub_bn = s.step1(v_bn, group_id, hash_id, rng);
81 return write_vec_output(b_pub, b_pub_len, b_pub_bn.serialize());
82 } catch(Botan::Decoding_Error&) {
84 } catch(Botan::Lookup_Error&) {
86 }
87 });
88#else
89 BOTAN_UNUSED(srp6, verifier, verifier_len, group_id, hash_id, rng_obj, b_pub, b_pub_len);
91#endif
92}
93
95 botan_srp6_server_session_t srp6, const uint8_t a[], size_t a_len, uint8_t key[], size_t* key_len) {
96#if defined(BOTAN_HAS_SRP6)
97 return BOTAN_FFI_VISIT(srp6, [=](auto& s) -> int {
98 if(!a) {
100 }
101 try {
102 Botan::BigInt a_bn = Botan::BigInt::from_bytes({a, a_len});
103 auto key_sk = s.step2(a_bn);
104 return write_vec_output(key, key_len, key_sk.bits_of());
105 } catch(Botan::Decoding_Error&) {
107 }
108 });
109#else
110 BOTAN_UNUSED(srp6, a, a_len, key, key_len);
112#endif
113}
114
115int botan_srp6_generate_verifier(const char* username,
116 const char* password,
117 const uint8_t salt[],
118 size_t salt_len,
119 const char* group_id,
120 const char* hash_id,
121 uint8_t verifier[],
122 size_t* verifier_len) {
123#if defined(BOTAN_HAS_SRP6)
124 return ffi_guard_thunk(__func__, [=]() -> int {
125 if(!username || !password || !salt || !group_id || !hash_id) {
127 }
128 try {
129 std::vector<uint8_t> salt_vec(salt, salt + salt_len);
130 auto verifier_bn = Botan::srp6_generate_verifier(username, password, salt_vec, group_id, hash_id);
131 return write_vec_output(verifier, verifier_len, verifier_bn.serialize());
132 } catch(Botan::Lookup_Error&) {
134 }
135 });
136#else
137 BOTAN_UNUSED(username, password, group_id, hash_id);
138 BOTAN_UNUSED(salt, salt_len, verifier, verifier_len);
140#endif
141}
142
143int botan_srp6_client_agree(const char* identity,
144 const char* password,
145 const char* group_id,
146 const char* hash_id,
147 const uint8_t salt[],
148 size_t salt_len,
149 const uint8_t b[],
150 size_t b_len,
151 botan_rng_t rng_obj,
152 uint8_t A[],
153 size_t* A_len,
154 uint8_t K[],
155 size_t* K_len) {
156#if defined(BOTAN_HAS_SRP6)
157 return ffi_guard_thunk(__func__, [=]() -> int {
158 if(!identity || !password || !salt || !group_id || !hash_id || !b || !rng_obj) {
160 }
161 try {
162 std::vector<uint8_t> saltv(salt, salt + salt_len);
164 auto b_bn = Botan::BigInt::from_bytes({b, b_len});
165 auto [A_bn, K_sk] = Botan::srp6_client_agree(identity, password, group_id, hash_id, saltv, b_bn, rng);
166 auto ret_a = write_vec_output(A, A_len, A_bn.serialize());
167 auto ret_k = write_vec_output(K, K_len, K_sk.bits_of());
168 if(ret_a != BOTAN_FFI_SUCCESS) {
169 return ret_a;
170 }
171 if(ret_k != BOTAN_FFI_SUCCESS) {
172 return ret_k;
173 }
174 return BOTAN_FFI_SUCCESS;
175 } catch(Botan::Lookup_Error&) {
177 }
178 });
179#else
180 BOTAN_UNUSED(identity, password, group_id, hash_id, rng_obj);
181 BOTAN_UNUSED(salt, salt_len, b, b_len, A, A_len, K, K_len);
183#endif
184}
185}
#define BOTAN_UNUSED
Definition assert.h:118
static BigInt from_bytes(std::span< const uint8_t > bytes)
Definition bigint.cpp:95
size_t p_bytes() const
Definition dl_group.cpp:456
struct botan_srp6_server_session_struct * botan_srp6_server_session_t
Definition ffi.h:2103
struct botan_rng_struct * botan_rng_t
Definition ffi.h:272
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:135
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:129
@ BOTAN_FFI_SUCCESS
Definition ffi.h:114
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition ffi.h:130
int botan_srp6_server_session_step2(botan_srp6_server_session_t srp6, const uint8_t a[], size_t a_len, uint8_t key[], size_t *key_len)
Definition ffi_srp6.cpp:94
int botan_srp6_server_session_init(botan_srp6_server_session_t *srp6)
Definition ffi_srp6.cpp:31
int botan_srp6_server_session_destroy(botan_srp6_server_session_t srp6)
Definition ffi_srp6.cpp:43
int botan_srp6_group_size(const char *group_id, size_t *group_p_bytes)
Definition ffi_srp6.cpp:47
int botan_srp6_server_session_step1(botan_srp6_server_session_t srp6, const uint8_t *verifier, size_t verifier_len, const char *group_id, const char *hash_id, botan_rng_t rng_obj, uint8_t b_pub[], size_t *b_pub_len)
Definition ffi_srp6.cpp:64
int botan_srp6_generate_verifier(const char *username, const char *password, const uint8_t salt[], size_t salt_len, const char *group_id, const char *hash_id, uint8_t verifier[], size_t *verifier_len)
Definition ffi_srp6.cpp:115
int botan_srp6_client_agree(const char *identity, const char *password, const char *group_id, const char *hash_id, const uint8_t salt[], size_t salt_len, const uint8_t b[], size_t b_len, botan_rng_t rng_obj, uint8_t A[], size_t *A_len, uint8_t K[], size_t *K_len)
Definition ffi_srp6.cpp:143
#define BOTAN_FFI_VISIT(obj, lambda)
Definition ffi_util.h:124
#define BOTAN_FFI_CHECKED_DELETE(o)
Definition ffi_util.h:143
#define BOTAN_FFI_DECLARE_DUMMY_STRUCT(NAME, MAGIC)
Definition ffi_util.h:56
#define BOTAN_FFI_DECLARE_STRUCT(NAME, TYPE, MAGIC)
Definition ffi_util.h:51
T & safe_get(botan_struct< T, M > *p)
Definition ffi_util.h:63
int ffi_guard_thunk(const char *func_name, const std::function< int()> &thunk)
Definition ffi.cpp:118
int write_vec_output(uint8_t out[], size_t *out_len, const std::vector< uint8_t, Alloc > &buf)
Definition ffi_util.h:201
std::pair< BigInt, SymmetricKey > srp6_client_agree(std::string_view identifier, std::string_view password, std::string_view group_id, std::string_view hash_id, const std::vector< uint8_t > &salt, const BigInt &B, RandomNumberGenerator &rng)
Definition srp6.cpp:65
BigInt srp6_generate_verifier(std::string_view identifier, std::string_view password, const std::vector< uint8_t > &salt, std::string_view group_id, std::string_view hash_id)
Definition srp6.cpp:128