• 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

96.92
/src/lib/ffi/ffi_kdf.cpp
1
/*
2
* (C) 2015,2017 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include <botan/ffi.h>
8

9
#include <botan/assert.h>
10
#include <botan/kdf.h>
11
#include <botan/pwdhash.h>
12
#include <botan/internal/ffi_rng.h>
13
#include <botan/internal/ffi_util.h>
14

15
#if defined(BOTAN_HAS_BCRYPT)
16
   #include <botan/bcrypt.h>
17
#endif
18

19
extern "C" {
20

21
using namespace Botan_FFI;
22

23
int botan_pbkdf(const char* algo,
1✔
24
                uint8_t out[],
25
                size_t out_len,
26
                const char* pass,
27
                const uint8_t salt[],
28
                size_t salt_len,
29
                size_t iterations) {
30
   return botan_pwdhash(algo, iterations, 0, 0, out, out_len, pass, 0, salt, salt_len);
1✔
31
}
32

33
int botan_pbkdf_timed(const char* algo,
2✔
34
                      uint8_t out[],
35
                      size_t out_len,
36
                      const char* password,
37
                      const uint8_t salt[],
38
                      size_t salt_len,
39
                      size_t ms_to_run,
40
                      size_t* iterations_used) {
41
   return botan_pwdhash_timed(algo,
2✔
42
                              static_cast<uint32_t>(ms_to_run),
43
                              iterations_used,
44
                              nullptr,
45
                              nullptr,
46
                              out,
47
                              out_len,
48
                              password,
49
                              0,
50
                              salt,
51
                              salt_len);
2✔
52
}
53

54
int botan_pwdhash(const char* algo,
9✔
55
                  size_t param1,
56
                  size_t param2,
57
                  size_t param3,
58
                  uint8_t out[],
59
                  size_t out_len,
60
                  const char* password,
61
                  size_t password_len,
62
                  const uint8_t salt[],
63
                  size_t salt_len) {
64
   if(algo == nullptr || password == nullptr) {
9✔
65
      return BOTAN_FFI_ERROR_NULL_POINTER;
66
   }
67
   if(out_len > 0 && out == nullptr) {
9✔
68
      return BOTAN_FFI_ERROR_NULL_POINTER;
69
   }
70
   if(salt_len > 0 && salt == nullptr) {
9✔
71
      return BOTAN_FFI_ERROR_NULL_POINTER;
72
   }
73

74
   if(password_len == 0) {
9✔
75
      password_len = std::strlen(password);
4✔
76
   }
77

78
   return ffi_guard_thunk(__func__, [=]() -> int {
9✔
79
      auto pwdhash_fam = Botan::PasswordHashFamily::create(algo);
9✔
80

81
      if(!pwdhash_fam) {
9✔
82
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
83
      }
84

85
      auto pwdhash = pwdhash_fam->from_params(param1, param2, param3);
9✔
86

87
      pwdhash->derive_key(out, out_len, password, password_len, salt, salt_len);
9✔
88

89
      return BOTAN_FFI_SUCCESS;
9✔
90
   });
27✔
91
}
92

93
int botan_pwdhash_timed(const char* algo,
4✔
94
                        uint32_t msec,
95
                        size_t* param1,
96
                        size_t* param2,
97
                        size_t* param3,
98
                        uint8_t out[],
99
                        size_t out_len,
100
                        const char* password,
101
                        size_t password_len,
102
                        const uint8_t salt[],
103
                        size_t salt_len) {
104
   if(algo == nullptr || password == nullptr) {
4✔
105
      return BOTAN_FFI_ERROR_NULL_POINTER;
106
   }
107
   if(out_len > 0 && out == nullptr) {
4✔
108
      return BOTAN_FFI_ERROR_NULL_POINTER;
109
   }
110
   if(salt_len > 0 && salt == nullptr) {
4✔
111
      return BOTAN_FFI_ERROR_NULL_POINTER;
112
   }
113

114
   if(password_len == 0) {
4✔
115
      password_len = std::strlen(password);
2✔
116
   }
117

118
   return ffi_guard_thunk(__func__, [=]() -> int {
4✔
119
      auto pwdhash_fam = Botan::PasswordHashFamily::create(algo);
4✔
120

121
      if(!pwdhash_fam) {
4✔
122
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
123
      }
124

125
      auto pwdhash = pwdhash_fam->tune_params(out_len, msec);
4✔
126

127
      if(param1 != nullptr) {
4✔
128
         *param1 = pwdhash->iterations();
4✔
129
      }
130
      if(param2 != nullptr) {
4✔
131
         *param2 = pwdhash->parallelism();
1✔
132
      }
133
      if(param3 != nullptr) {
4✔
134
         *param3 = pwdhash->memory_param();
1✔
135
      }
136

137
      pwdhash->derive_key(out, out_len, password, password_len, salt, salt_len);
4✔
138

139
      return BOTAN_FFI_SUCCESS;
4✔
140
   });
12✔
141
}
142

143
int botan_kdf(const char* kdf_algo,
2✔
144
              uint8_t out[],
145
              size_t out_len,
146
              const uint8_t secret[],
147
              size_t secret_len,
148
              const uint8_t salt[],
149
              size_t salt_len,
150
              const uint8_t label[],
151
              size_t label_len) {
152
   if(kdf_algo == nullptr) {
2✔
153
      return BOTAN_FFI_ERROR_NULL_POINTER;
154
   }
155
   if((out_len > 0 && out == nullptr) || (secret_len > 0 && secret == nullptr) || (salt_len > 0 && salt == nullptr) ||
2✔
156
      (label_len > 0 && label == nullptr)) {
2✔
157
      return BOTAN_FFI_ERROR_NULL_POINTER;
158
   }
159
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
160
      auto kdf = Botan::KDF::create_or_throw(kdf_algo);
2✔
161
      kdf->kdf(out, out_len, secret, secret_len, salt, salt_len, label, label_len);
2✔
162
      return BOTAN_FFI_SUCCESS;
2✔
163
   });
4✔
164
}
165

166
int botan_scrypt(uint8_t out[],
1✔
167
                 size_t out_len,
168
                 const char* password,
169
                 const uint8_t salt[],
170
                 size_t salt_len,
171
                 size_t N,
172
                 size_t r,
173
                 size_t p) {
174
   return botan_pwdhash("Scrypt", N, r, p, out, out_len, password, 0, salt, salt_len);
1✔
175
}
176

177
int botan_bcrypt_generate(
2✔
178
   uint8_t* out, size_t* out_len, const char* pass, botan_rng_t rng_obj, size_t wf, uint32_t flags) {
179
#if defined(BOTAN_HAS_BCRYPT)
180
   return ffi_guard_thunk(__func__, [=]() -> int {
2✔
181
      if(out == nullptr || out_len == nullptr || pass == nullptr) {
2✔
182
         return BOTAN_FFI_ERROR_NULL_POINTER;
183
      }
184

185
      if(flags != 0) {
2✔
186
         return BOTAN_FFI_ERROR_BAD_FLAG;
187
      }
188

189
      if(wf < 4 || wf > 18) {
2✔
190
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
191
      }
192

193
      if(*out_len < 61) {
2✔
194
         *out_len = 61;
×
195
         return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
×
196
      }
197

198
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
2✔
199
      const std::string bcrypt = Botan::generate_bcrypt(pass, rng, static_cast<uint16_t>(wf));
2✔
200
      // TODO(Botan4) change the type of out and remove this cast
201
      return write_str_output(reinterpret_cast<char*>(out), out_len, bcrypt);
2✔
202
   });
2✔
203
#else
204
   BOTAN_UNUSED(out, out_len, pass, rng_obj, wf, flags);
205
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
206
#endif
207
}
208

209
int botan_bcrypt_is_valid(const char* pass, const char* hash) {
5✔
210
   if(any_null_pointers(pass, hash)) {
5✔
211
      return BOTAN_FFI_ERROR_NULL_POINTER;
212
   }
213
#if defined(BOTAN_HAS_BCRYPT)
214
   return ffi_guard_thunk(__func__, [=]() -> int {
5✔
215
      return Botan::check_bcrypt(pass, hash) ? BOTAN_FFI_SUCCESS : BOTAN_FFI_INVALID_VERIFIER;
5✔
216
   });
5✔
217
#else
218
   BOTAN_UNUSED(pass, hash);
219
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
220
#endif
221
}
222
}
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