Coverage Report

Created: 2025-10-13 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Botan-3.4.0/src/lib/ffi/ffi_kdf.cpp
Line
Count
Source
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/kdf.h>
10
#include <botan/pwdhash.h>
11
#include <botan/internal/ffi_rng.h>
12
#include <botan/internal/ffi_util.h>
13
14
#if defined(BOTAN_HAS_BCRYPT)
15
   #include <botan/bcrypt.h>
16
#endif
17
18
extern "C" {
19
20
using namespace Botan_FFI;
21
22
int botan_pbkdf(const char* algo,
23
                uint8_t out[],
24
                size_t out_len,
25
                const char* pass,
26
                const uint8_t salt[],
27
                size_t salt_len,
28
0
                size_t iterations) {
29
0
   return botan_pwdhash(algo, iterations, 0, 0, out, out_len, pass, 0, salt, salt_len);
30
0
}
31
32
int botan_pbkdf_timed(const char* algo,
33
                      uint8_t out[],
34
                      size_t out_len,
35
                      const char* password,
36
                      const uint8_t salt[],
37
                      size_t salt_len,
38
                      size_t ms_to_run,
39
0
                      size_t* iterations_used) {
40
0
   return botan_pwdhash_timed(algo,
41
0
                              static_cast<uint32_t>(ms_to_run),
42
0
                              iterations_used,
43
0
                              nullptr,
44
0
                              nullptr,
45
0
                              out,
46
0
                              out_len,
47
0
                              password,
48
0
                              0,
49
0
                              salt,
50
0
                              salt_len);
51
0
}
52
53
int botan_pwdhash(const char* algo,
54
                  size_t param1,
55
                  size_t param2,
56
                  size_t param3,
57
                  uint8_t out[],
58
                  size_t out_len,
59
                  const char* password,
60
                  size_t password_len,
61
                  const uint8_t salt[],
62
0
                  size_t salt_len) {
63
0
   if(algo == nullptr || password == nullptr) {
64
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
65
0
   }
66
67
0
   if(password_len == 0) {
68
0
      password_len = std::strlen(password);
69
0
   }
70
71
0
   return ffi_guard_thunk(__func__, [=]() -> int {
72
0
      auto pwdhash_fam = Botan::PasswordHashFamily::create(algo);
73
74
0
      if(!pwdhash_fam) {
75
0
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
76
0
      }
77
78
0
      auto pwdhash = pwdhash_fam->from_params(param1, param2, param3);
79
80
0
      pwdhash->derive_key(out, out_len, password, password_len, salt, salt_len);
81
82
0
      return BOTAN_FFI_SUCCESS;
83
0
   });
84
0
}
85
86
int botan_pwdhash_timed(const char* algo,
87
                        uint32_t msec,
88
                        size_t* param1,
89
                        size_t* param2,
90
                        size_t* param3,
91
                        uint8_t out[],
92
                        size_t out_len,
93
                        const char* password,
94
                        size_t password_len,
95
                        const uint8_t salt[],
96
0
                        size_t salt_len) {
97
0
   if(algo == nullptr || password == nullptr) {
98
0
      return BOTAN_FFI_ERROR_NULL_POINTER;
99
0
   }
100
101
0
   if(password_len == 0) {
102
0
      password_len = std::strlen(password);
103
0
   }
104
105
0
   return ffi_guard_thunk(__func__, [=]() -> int {
106
0
      auto pwdhash_fam = Botan::PasswordHashFamily::create(algo);
107
108
0
      if(!pwdhash_fam) {
109
0
         return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
110
0
      }
111
112
0
      auto pwdhash = pwdhash_fam->tune(out_len, std::chrono::milliseconds(msec));
113
114
0
      if(param1) {
115
0
         *param1 = pwdhash->iterations();
116
0
      }
117
0
      if(param2) {
118
0
         *param2 = pwdhash->parallelism();
119
0
      }
120
0
      if(param3) {
121
0
         *param3 = pwdhash->memory_param();
122
0
      }
123
124
0
      pwdhash->derive_key(out, out_len, password, password_len, salt, salt_len);
125
126
0
      return BOTAN_FFI_SUCCESS;
127
0
   });
128
0
}
129
130
int botan_kdf(const char* kdf_algo,
131
              uint8_t out[],
132
              size_t out_len,
133
              const uint8_t secret[],
134
              size_t secret_len,
135
              const uint8_t salt[],
136
              size_t salt_len,
137
              const uint8_t label[],
138
0
              size_t label_len) {
139
0
   return ffi_guard_thunk(__func__, [=]() -> int {
140
0
      auto kdf = Botan::KDF::create_or_throw(kdf_algo);
141
0
      kdf->kdf(out, out_len, secret, secret_len, salt, salt_len, label, label_len);
142
0
      return BOTAN_FFI_SUCCESS;
143
0
   });
144
0
}
145
146
int botan_scrypt(uint8_t out[],
147
                 size_t out_len,
148
                 const char* password,
149
                 const uint8_t salt[],
150
                 size_t salt_len,
151
                 size_t N,
152
                 size_t r,
153
0
                 size_t p) {
154
0
   return botan_pwdhash("Scrypt", N, r, p, out, out_len, password, 0, salt, salt_len);
155
0
}
156
157
int botan_bcrypt_generate(
158
0
   uint8_t* out, size_t* out_len, const char* pass, botan_rng_t rng_obj, size_t wf, uint32_t flags) {
159
#if defined(BOTAN_HAS_BCRYPT)
160
   return ffi_guard_thunk(__func__, [=]() -> int {
161
      if(out == nullptr || out_len == nullptr || pass == nullptr) {
162
         return BOTAN_FFI_ERROR_NULL_POINTER;
163
      }
164
165
      if(flags != 0) {
166
         return BOTAN_FFI_ERROR_BAD_FLAG;
167
      }
168
169
      if(wf < 4 || wf > 18) {
170
         return BOTAN_FFI_ERROR_BAD_PARAMETER;
171
      }
172
173
      if(*out_len < 61) {
174
         *out_len = 61;
175
         return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
176
      }
177
178
      Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
179
      const std::string bcrypt = Botan::generate_bcrypt(pass, rng, static_cast<uint16_t>(wf));
180
      return write_str_output(out, out_len, bcrypt);
181
   });
182
#else
183
0
   BOTAN_UNUSED(out, out_len, pass, rng_obj, wf, flags);
184
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
185
0
#endif
186
0
}
187
188
0
int botan_bcrypt_is_valid(const char* pass, const char* hash) {
189
#if defined(BOTAN_HAS_BCRYPT)
190
   return ffi_guard_thunk(__func__, [=]() -> int {
191
      return Botan::check_bcrypt(pass, hash) ? BOTAN_FFI_SUCCESS : BOTAN_FFI_INVALID_VERIFIER;
192
   });
193
#else
194
0
   BOTAN_UNUSED(pass, hash);
195
0
   return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
196
0
#endif
197
0
}
198
}