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

randombit / botan / 25416417447

05 May 2026 05:54PM UTC coverage: 91.667% (+2.3%) from 89.323%
25416417447

push

github

web-flow
Merge pull request #5572 from randombit/jack/fix-5571

Avoid a hidden dependency of <algorithm> in secmem.h

110208 of 120227 relevant lines covered (91.67%)

11269830.86 hits per line

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

76.19
/src/lib/pbkdf/argon2/argon2pwhash.cpp
1
/**
2
* (C) 2019 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include <botan/argon2.h>
8

9
#include <botan/assert.h>
10
#include <botan/exceptn.h>
11
#include <botan/internal/fmt.h>
12
#include <botan/internal/time_utils.h>
13
#include <algorithm>
14
#include <limits>
15

16
namespace Botan {
17

18
Argon2::Argon2(uint8_t family, size_t M, size_t t, size_t p) : m_family(family), m_M(M), m_t(t), m_p(p) {
1,106✔
19
   BOTAN_ARG_CHECK(m_p >= 1 && m_p <= 128, "Invalid Argon2 threads parameter");
1,106✔
20
   BOTAN_ARG_CHECK(m_M >= 8 * m_p && m_M <= 8192 * 1024, "Invalid Argon2 M parameter");
1,106✔
21
   BOTAN_ARG_CHECK(m_t >= 1 && m_t <= std::numeric_limits<uint32_t>::max(), "Invalid Argon2 t parameter");
1,106✔
22
}
1,106✔
23

24
void Argon2::derive_key(uint8_t output[],
35✔
25
                        size_t output_len,
26
                        const char* password,
27
                        size_t password_len,
28
                        const uint8_t salt[],
29
                        size_t salt_len) const {
30
   argon2(output, output_len, password, password_len, salt, salt_len, nullptr, 0, nullptr, 0);
35✔
31
}
35✔
32

33
void Argon2::derive_key(uint8_t output[],
1,071✔
34
                        size_t output_len,
35
                        const char* password,
36
                        size_t password_len,
37
                        const uint8_t salt[],
38
                        size_t salt_len,
39
                        const uint8_t ad[],
40
                        size_t ad_len,
41
                        const uint8_t key[],
42
                        size_t key_len) const {
43
   argon2(output, output_len, password, password_len, salt, salt_len, key, key_len, ad, ad_len);
1,071✔
44
}
1,071✔
45

46
namespace {
47

48
std::string argon2_family_name(uint8_t f) {
10✔
49
   switch(f) {
10✔
50
      case 0:
2✔
51
         return "Argon2d";
2✔
52
      case 1:
2✔
53
         return "Argon2i";
2✔
54
      case 2:
6✔
55
         return "Argon2id";
6✔
56
      default:
×
57
         throw Invalid_Argument("Unknown Argon2 parameter");
×
58
   }
59
}
60

61
}  // namespace
62

63
std::string Argon2::to_string() const {
4✔
64
   return fmt("{}({},{},{})", argon2_family_name(m_family), m_M, m_t, m_p);
4✔
65
}
66

67
Argon2_Family::Argon2_Family(uint8_t family) : m_family(family) {
1,091✔
68
   if(m_family != 0 && m_family != 1 && m_family != 2) {
1,091✔
69
      throw Invalid_Argument("Unknown Argon2 family identifier");
×
70
   }
71
}
1,091✔
72

73
std::string Argon2_Family::name() const {
6✔
74
   return argon2_family_name(m_family);
6✔
75
}
76

77
std::unique_ptr<PasswordHash> Argon2_Family::tune_params(size_t /*output_length*/,
6✔
78
                                                         uint64_t desired_msec,
79
                                                         std::optional<size_t> max_memory,
80
                                                         uint64_t tune_msec) const {
81
   // If not set use 256 MB as default max
82
   const size_t max_kib = max_memory.value_or(256) * 1024;
6✔
83

84
   // Tune with a large memory otherwise we measure cache vs RAM speeds and underestimate
85
   // costs for larger params. Default is 36 MiB, or use 128 for long times.
86
   const size_t tune_M = (desired_msec >= 200 ? 128 : 36) * 1024;
6✔
87
   const size_t p = 1;
6✔
88
   size_t t = 1;
6✔
89

90
   size_t M = 4 * 1024;
6✔
91

92
   auto pwhash = this->from_params(tune_M, t, p);
6✔
93

94
   auto tune_fn = [&]() {
12✔
95
      uint8_t output[64] = {0};
6✔
96
      pwhash->derive_key(output, sizeof(output), "test", 4, nullptr, 0);
6✔
97
   };
12✔
98

99
   const uint64_t measured_time = measure_cost(tune_msec, tune_fn) / (tune_M / M);
6✔
100

101
   const uint64_t target_nsec = desired_msec * static_cast<uint64_t>(1000000);
6✔
102

103
   /*
104
   * Argon2 scaling rules:
105
   * k*M, k*t, k*p all increase cost by about k
106
   *
107
   * First preference is to increase M up to max allowed value.
108
   * Any remaining time budget is spent on increasing t.
109
   */
110

111
   uint64_t est_nsec = measured_time;
6✔
112

113
   if(est_nsec < target_nsec && M < max_kib) {
6✔
114
      const uint64_t desired_cost_increase = (target_nsec + est_nsec - 1) / est_nsec;
×
115
      const uint64_t mem_headroom = max_kib / M;
×
116

117
      const uint64_t M_mult = std::min(desired_cost_increase, mem_headroom);
×
118
      M *= static_cast<size_t>(M_mult);
×
119
      est_nsec *= M_mult;
×
120
   }
121

122
   if(est_nsec < target_nsec / 2) {
6✔
123
      const uint64_t desired_cost_increase = (target_nsec + est_nsec - 1) / est_nsec;
×
124
      t *= static_cast<size_t>(desired_cost_increase);
×
125
   }
126

127
   return this->from_params(M, t, p);
6✔
128
}
6✔
129

130
std::unique_ptr<PasswordHash> Argon2_Family::default_params() const {
4✔
131
   return this->from_params(128 * 1024, 1, 1);
4✔
132
}
133

134
std::unique_ptr<PasswordHash> Argon2_Family::from_iterations(size_t iter) const {
×
135
   /*
136
   These choices are arbitrary, but should not change in future
137
   releases since they will break applications expecting deterministic
138
   mapping from iteration count to params
139
   */
140
   const size_t M = iter;
×
141
   const size_t t = 1;
×
142
   const size_t p = 1;
×
143
   return this->from_params(M, t, p);
×
144
}
145

146
std::unique_ptr<PasswordHash> Argon2_Family::from_params(size_t M, size_t t, size_t p) const {
1,106✔
147
   return std::make_unique<Argon2>(m_family, M, t, p);
1,106✔
148
}
149

150
}  // namespace Botan
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