/src/Botan-3.4.0/src/lib/ffi/ffi_srp6.cpp
Line | Count | Source |
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 | | |
21 | | extern "C" { |
22 | | |
23 | | using namespace Botan_FFI; |
24 | | |
25 | | #if defined(BOTAN_HAS_SRP6) |
26 | | BOTAN_FFI_DECLARE_STRUCT(botan_srp6_server_session_struct, Botan::SRP6_Server_Session, 0x44F7425F); |
27 | | #else |
28 | | BOTAN_FFI_DECLARE_DUMMY_STRUCT(botan_srp6_server_session_struct, 0x44F7425F); |
29 | | #endif |
30 | | |
31 | 0 | int botan_srp6_server_session_init(botan_srp6_server_session_t* srp6) { |
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 | 0 | BOTAN_UNUSED(srp6); |
39 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
40 | 0 | #endif |
41 | 0 | } |
42 | | |
43 | 0 | int botan_srp6_server_session_destroy(botan_srp6_server_session_t srp6) { |
44 | 0 | return BOTAN_FFI_CHECKED_DELETE(srp6); |
45 | 0 | } |
46 | | |
47 | 0 | int 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) { |
50 | | return BOTAN_FFI_ERROR_NULL_POINTER; |
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 | 0 | BOTAN_UNUSED(group_id, group_p_bytes); |
60 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
61 | 0 | #endif |
62 | 0 | } |
63 | | |
64 | | int botan_srp6_server_session_step1(botan_srp6_server_session_t srp6, |
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 | 0 | 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) { |
75 | | return BOTAN_FFI_ERROR_NULL_POINTER; |
76 | | } |
77 | | try { |
78 | | Botan::RandomNumberGenerator& rng = safe_get(rng_obj); |
79 | | auto v_bn = Botan::BigInt::decode(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, Botan::BigInt::encode(b_pub_bn)); |
82 | | } catch(Botan::Decoding_Error&) { |
83 | | return BOTAN_FFI_ERROR_BAD_PARAMETER; |
84 | | } catch(Botan::Lookup_Error&) { |
85 | | return BOTAN_FFI_ERROR_BAD_PARAMETER; |
86 | | } |
87 | | }); |
88 | | #else |
89 | 0 | BOTAN_UNUSED(srp6, verifier, verifier_len, group_id, hash_id, rng_obj, b_pub, b_pub_len); |
90 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
91 | 0 | #endif |
92 | 0 | } |
93 | | |
94 | | int botan_srp6_server_session_step2( |
95 | 0 | 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) { |
99 | | return BOTAN_FFI_ERROR_NULL_POINTER; |
100 | | } |
101 | | try { |
102 | | Botan::BigInt a_bn = Botan::BigInt::decode(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&) { |
106 | | return BOTAN_FFI_ERROR_BAD_PARAMETER; |
107 | | } |
108 | | }); |
109 | | #else |
110 | 0 | BOTAN_UNUSED(srp6, a, a_len, key, key_len); |
111 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
112 | 0 | #endif |
113 | 0 | } |
114 | | |
115 | | int 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 | 0 | 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) { |
126 | | return BOTAN_FFI_ERROR_NULL_POINTER; |
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, Botan::BigInt::encode(verifier_bn)); |
132 | | } catch(Botan::Lookup_Error&) { |
133 | | return BOTAN_FFI_ERROR_BAD_PARAMETER; |
134 | | } |
135 | | }); |
136 | | #else |
137 | 0 | BOTAN_UNUSED(username, password, group_id, hash_id); |
138 | 0 | BOTAN_UNUSED(salt, salt_len, verifier, verifier_len); |
139 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
140 | 0 | #endif |
141 | 0 | } |
142 | | |
143 | | int 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 | 0 | 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) { |
159 | | return BOTAN_FFI_ERROR_NULL_POINTER; |
160 | | } |
161 | | try { |
162 | | std::vector<uint8_t> saltv(salt, salt + salt_len); |
163 | | Botan::RandomNumberGenerator& rng = safe_get(rng_obj); |
164 | | auto b_bn = Botan::BigInt::decode(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, Botan::BigInt::encode(A_bn)); |
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&) { |
176 | | return BOTAN_FFI_ERROR_BAD_PARAMETER; |
177 | | } |
178 | | }); |
179 | | #else |
180 | 0 | BOTAN_UNUSED(identity, password, group_id, hash_id, rng_obj); |
181 | 0 | BOTAN_UNUSED(salt, salt_len, b, b_len, A, A_len, K, K_len); |
182 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
183 | 0 | #endif |
184 | 0 | } |
185 | | } |