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

randombit / botan / 25147314492

30 Apr 2026 04:17AM UTC coverage: 89.359% (-0.01%) from 89.37%
25147314492

push

github

randombit
Avoid using BOTAN_ASSERT for input validation

107055 of 119803 relevant lines covered (89.36%)

11298138.36 hits per line

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

91.84
/src/lib/ffi/ffi_srp6.cpp
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/assert.h>
11
#include <botan/internal/ffi_rng.h>
12
#include <botan/internal/ffi_util.h>
13

14
#if defined(BOTAN_HAS_SRP6)
15
   #include <botan/bigint.h>
16
   #include <botan/dl_group.h>
17
   #include <botan/rng.h>
18
   #include <botan/srp6.h>
19
   #include <botan/symkey.h>
20
#endif
21

22
extern "C" {
23

24
using namespace Botan_FFI;
25

26
#if defined(BOTAN_HAS_SRP6)
27
BOTAN_FFI_DECLARE_STRUCT(botan_srp6_server_session_struct, Botan::SRP6_Server_Session, 0x44F7425F);
2✔
28
#else
29
BOTAN_FFI_DECLARE_DUMMY_STRUCT(botan_srp6_server_session_struct, 0x44F7425F);
30
#endif
31

32
int botan_srp6_server_session_init(botan_srp6_server_session_t* srp6) {
2✔
33
#if defined(BOTAN_HAS_SRP6)
34
   if(srp6 == nullptr) {
2✔
35
      return BOTAN_FFI_ERROR_NULL_POINTER;
36
   }
37
   return ffi_guard_thunk(
2✔
38
      __func__, [=]() -> int { return ffi_new_object(srp6, std::make_unique<Botan::SRP6_Server_Session>()); });
4✔
39
#else
40
   BOTAN_UNUSED(srp6);
41
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
42
#endif
43
}
44

45
int botan_srp6_server_session_destroy(botan_srp6_server_session_t srp6) {
2✔
46
   return BOTAN_FFI_CHECKED_DELETE(srp6);
2✔
47
}
48

49
int botan_srp6_group_size(const char* group_id, size_t* group_p_bytes) {
4✔
50
#if defined(BOTAN_HAS_SRP6)
51
   if(any_null_pointers(group_id, group_p_bytes)) {
4✔
52
      return BOTAN_FFI_ERROR_NULL_POINTER;
53
   }
54

55
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
56
      const auto group = Botan::DL_Group::from_name(group_id);
4✔
57
      *group_p_bytes = group.p_bytes();
4✔
58
      return BOTAN_FFI_SUCCESS;
4✔
59
   });
8✔
60
#else
61
   BOTAN_UNUSED(group_id, group_p_bytes);
62
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
63
#endif
64
}
65

66
int botan_srp6_server_session_step1(botan_srp6_server_session_t srp6,
3✔
67
                                    const uint8_t* verifier,
68
                                    size_t verifier_len,
69
                                    const char* group_id,
70
                                    const char* hash_id,
71
                                    botan_rng_t rng_obj,
72
                                    uint8_t b_pub[],
73
                                    size_t* b_pub_len) {
74
#if defined(BOTAN_HAS_SRP6)
75
   return BOTAN_FFI_VISIT(srp6, [=](auto& s) -> int {
11✔
76
      if(any_null_pointers(verifier, group_id, hash_id, rng_obj)) {
77
         return BOTAN_FFI_ERROR_NULL_POINTER;
78
      }
79
      try {
80
         const auto group = Botan::DL_Group::from_name(group_id);
81
         const auto rc = check_and_prepare_output_space(b_pub, b_pub_len, group.p_bytes());
82
         if(rc != BOTAN_FFI_SUCCESS) {
83
            return rc;
84
         }
85

86
         Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
87
         auto v_bn = Botan::BigInt::from_bytes(std::span{verifier, verifier_len});
88
         auto b_pub_bn = s.step1(v_bn, group, hash_id, group.exponent_bits(), rng);
89
         return write_vec_output(b_pub, b_pub_len, b_pub_bn.serialize(group.p_bytes()));
90
      } catch(Botan::Decoding_Error&) {
91
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
92
      } catch(Botan::Lookup_Error&) {
93
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
94
      }
95
   });
96
#else
97
   BOTAN_UNUSED(srp6, verifier, verifier_len, group_id, hash_id, rng_obj, b_pub, b_pub_len);
98
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
99
#endif
100
}
101

102
int botan_srp6_server_session_step2(
3✔
103
   botan_srp6_server_session_t srp6, const uint8_t a[], size_t a_len, uint8_t key[], size_t* key_len) {
104
#if defined(BOTAN_HAS_SRP6)
105
   return BOTAN_FFI_VISIT(srp6, [=](auto& s) -> int {
15✔
106
      if(!a) {
107
         return BOTAN_FFI_ERROR_NULL_POINTER;
108
      }
109
      try {
110
         const Botan::BigInt a_bn = Botan::BigInt::from_bytes({a, a_len});
111
         auto key_sk = s.step2(a_bn);
112
         return write_vec_output(key, key_len, key_sk.bits_of());
113
      } catch(Botan::Decoding_Error&) {
114
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
115
      }
116
   });
117
#else
118
   BOTAN_UNUSED(srp6, a, a_len, key, key_len);
119
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
120
#endif
121
}
122

123
int botan_srp6_generate_verifier(const char* username,
3✔
124
                                 const char* password,
125
                                 const uint8_t salt[],
126
                                 size_t salt_len,
127
                                 const char* group_id,
128
                                 const char* hash_id,
129
                                 uint8_t verifier[],
130
                                 size_t* verifier_len) {
131
#if defined(BOTAN_HAS_SRP6)
132
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
133
      if(any_null_pointers(username, password, salt, group_id, hash_id)) {
6✔
134
         return BOTAN_FFI_ERROR_NULL_POINTER;
135
      }
136
      try {
3✔
137
         const std::vector<uint8_t> salt_vec(salt, salt + salt_len);
3✔
138
         const auto group = Botan::DL_Group::from_name(group_id);
3✔
139
         const size_t p_bytes = group.p_bytes();
3✔
140
         auto verifier_bn = Botan::srp6_generate_verifier(username, password, salt_vec, group, hash_id);
6✔
141
         return write_vec_output(verifier, verifier_len, verifier_bn.serialize(p_bytes));
3✔
142
      } catch(Botan::Lookup_Error&) {
9✔
143
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
×
144
      }
×
145
   });
3✔
146
#else
147
   BOTAN_UNUSED(username, password, group_id, hash_id);
148
   BOTAN_UNUSED(salt, salt_len, verifier, verifier_len);
149
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
150
#endif
151
}
152

153
int botan_srp6_client_agree(const char* identity,
3✔
154
                            const char* password,
155
                            const char* group_id,
156
                            const char* hash_id,
157
                            const uint8_t salt[],
158
                            size_t salt_len,
159
                            const uint8_t b[],
160
                            size_t b_len,
161
                            botan_rng_t rng_obj,
162
                            uint8_t A[],
163
                            size_t* A_len,
164
                            uint8_t K[],
165
                            size_t* K_len) {
166
#if defined(BOTAN_HAS_SRP6)
167
   return ffi_guard_thunk(__func__, [=]() -> int {
3✔
168
      if(any_null_pointers(identity, password, salt, group_id, hash_id, b, rng_obj)) {
6✔
169
         return BOTAN_FFI_ERROR_NULL_POINTER;
170
      }
171
      try {
3✔
172
         const std::vector<uint8_t> saltv(salt, salt + salt_len);
3✔
173
         Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
3✔
174
         auto b_bn = Botan::BigInt::from_bytes({b, b_len});
3✔
175
         const auto group = Botan::DL_Group::from_name(group_id);
3✔
176
         const size_t a_bits = group.exponent_bits();
3✔
177
         auto [A_bn, K_sk] = Botan::srp6_client_agree(identity, password, group, hash_id, saltv, b_bn, a_bits, rng);
3✔
178
         auto ret_a = write_vec_output(A, A_len, A_bn.serialize(group.p_bytes()));
3✔
179
         auto ret_k = write_vec_output(K, K_len, K_sk.bits_of());
3✔
180
         if(ret_a != BOTAN_FFI_SUCCESS) {
3✔
181
            return ret_a;
1✔
182
         }
183
         if(ret_k != BOTAN_FFI_SUCCESS) {
184
            return ret_k;
185
         }
186
         return BOTAN_FFI_SUCCESS;
187
      } catch(Botan::Lookup_Error&) {
9✔
188
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
×
189
      }
×
190
   });
3✔
191
#else
192
   BOTAN_UNUSED(identity, password, group_id, hash_id, rng_obj);
193
   BOTAN_UNUSED(salt, salt_len, b, b_len, A, A_len, K, K_len);
194
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
195
#endif
196
}
197
}
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