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

randombit / botan / 19012754211

02 Nov 2025 01:10PM UTC coverage: 90.677% (+0.006%) from 90.671%
19012754211

push

github

web-flow
Merge pull request #5137 from randombit/jack/clang-tidy-includes

Remove various unused includes flagged by clang-tidy misc-include-cleaner

100457 of 110786 relevant lines covered (90.68%)

12189873.8 hits per line

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

95.31
/src/lib/passhash/argon2fmt/argon2fmt.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/argon2fmt.h>
8

9
#include <botan/base64.h>
10
#include <botan/pwdhash.h>
11
#include <botan/rng.h>
12
#include <botan/internal/ct_utils.h>
13
#include <botan/internal/fmt.h>
14
#include <botan/internal/parsing.h>
15

16
namespace Botan {
17

18
namespace {
19

20
std::string strip_padding(std::string s) {
12✔
21
   while(!s.empty() && s[s.size() - 1] == '=') {
24✔
22
      s.resize(s.size() - 1);
12✔
23
   }
24
   return s;
12✔
25
}
26

27
std::string argon2_family(uint8_t y) {
14✔
28
   if(y == 0) {
14✔
29
      return "Argon2d";
3✔
30
   } else if(y == 1) {
11✔
31
      return "Argon2i";
3✔
32
   } else if(y == 2) {
8✔
33
      return "Argon2id";
8✔
34
   } else {
35
      throw Not_Implemented("Unknown Argon2 family type");
×
36
   }
37
}
38

39
}  // namespace
40

41
std::string argon2_generate_pwhash(const char* password,
6✔
42
                                   size_t password_len,
43
                                   RandomNumberGenerator& rng,
44
                                   size_t p,
45
                                   size_t M,
46
                                   size_t t,
47
                                   uint8_t y,
48
                                   size_t salt_len,
49
                                   size_t output_len) {
50
   std::vector<uint8_t> salt(salt_len);
6✔
51
   rng.randomize(salt.data(), salt.size());
6✔
52

53
   std::vector<uint8_t> output(output_len);
6✔
54

55
   auto pwdhash_fam = PasswordHashFamily::create_or_throw(argon2_family(y));
6✔
56
   auto pwdhash = pwdhash_fam->from_params(M, t, p);
6✔
57

58
   pwdhash->derive_key(output.data(), output.size(), password, password_len, salt.data(), salt.size());
6✔
59

60
   const auto enc_salt = strip_padding(base64_encode(salt));
6✔
61
   const auto enc_output = strip_padding(base64_encode(output));
6✔
62

63
   const std::string argon2_mode = [&]() -> std::string {
×
64
      if(y == 0) {
6✔
65
         return "d";
1✔
66
      } else if(y == 1) {
5✔
67
         return "i";
1✔
68
      } else {
69
         return "id";
4✔
70
      }
71
   }();
6✔
72

73
   return fmt("$argon2{}$v=19$m={},t={},p={}${}${}", argon2_mode, M, t, p, enc_salt, enc_output);
6✔
74
}
30✔
75

76
bool argon2_check_pwhash(const char* password, size_t password_len, std::string_view input_hash) {
8✔
77
   const std::vector<std::string> parts = split_on(input_hash, '$');
8✔
78

79
   if(parts.size() != 5) {
8✔
80
      return false;
81
   }
82

83
   uint8_t family = 0;
8✔
84

85
   if(parts[0] == "argon2d") {
8✔
86
      family = 0;
87
   } else if(parts[0] == "argon2i") {
6✔
88
      family = 1;
89
   } else if(parts[0] == "argon2id") {
4✔
90
      family = 2;
91
   } else {
92
      return false;
93
   }
94

95
   if(parts[1] != "v=19") {
8✔
96
      return false;
97
   }
98

99
   const std::vector<std::string> params = split_on(parts[2], ',');
8✔
100

101
   if(params.size() != 3) {
8✔
102
      return false;
103
   }
104

105
   size_t M = 0;
106
   size_t t = 0;
107
   size_t p = 0;
108

109
   for(const auto& param_str : params) {
32✔
110
      const std::vector<std::string> param = split_on(param_str, '=');
24✔
111

112
      if(param.size() != 2) {
24✔
113
         return false;
114
      }
115

116
      std::string_view key = param[0];
24✔
117
      const size_t val = to_u32bit(param[1]);
24✔
118
      if(key == "m") {
24✔
119
         M = val;
8✔
120
      } else if(key == "t") {
16✔
121
         t = val;
8✔
122
      } else if(key == "p") {
8✔
123
         p = val;
8✔
124
      } else {
125
         return false;
×
126
      }
127
   }
24✔
128

129
   std::vector<uint8_t> salt(base64_decode_max_output(parts[3].size()));
8✔
130
   salt.resize(base64_decode(salt.data(), parts[3], false));
8✔
131

132
   std::vector<uint8_t> hash(base64_decode_max_output(parts[4].size()));
8✔
133
   hash.resize(base64_decode(hash.data(), parts[4], false));
8✔
134

135
   if(hash.size() < 4) {
8✔
136
      return false;
137
   }
138

139
   std::vector<uint8_t> generated(hash.size());
8✔
140
   auto pwdhash_fam = PasswordHashFamily::create_or_throw(argon2_family(family));
16✔
141
   auto pwdhash = pwdhash_fam->from_params(M, t, p);
8✔
142

143
   pwdhash->derive_key(generated.data(), generated.size(), password, password_len, salt.data(), salt.size());
8✔
144

145
   return CT::is_equal(generated.data(), hash.data(), generated.size()).as_bool();
16✔
146
}
40✔
147

148
}  // 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