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

randombit / botan / 6704830136

31 Oct 2023 09:55AM UTC coverage: 91.722% (+0.001%) from 91.721%
6704830136

push

github

web-flow
Merge pull request #3752 from randombit/jack/allocator-helper

Split out allocator helpers to allocator.h

80150 of 87384 relevant lines covered (91.72%)

8593301.14 hits per line

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

96.72
/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/mem_ops.h>
11
#include <botan/pwdhash.h>
12
#include <botan/rng.h>
13
#include <botan/internal/ct_utils.h>
14
#include <botan/internal/fmt.h>
15
#include <botan/internal/parsing.h>
16

17
namespace Botan {
18

19
namespace {
20

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

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

40
}  // namespace
41

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

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

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

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

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

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

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

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

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

84
   uint8_t family = 0;
8✔
85

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

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

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

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

106
   size_t M = 0, t = 0, p = 0;
107

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

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

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

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

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

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

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

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

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

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