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

randombit / botan / 5123321399

30 May 2023 04:06PM UTC coverage: 92.213% (+0.004%) from 92.209%
5123321399

Pull #3558

github

web-flow
Merge dd72f7389 into 057bcbc35
Pull Request #3558: Add braces around all if/else statements

75602 of 81986 relevant lines covered (92.21%)

11859779.3 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/pwdhash.h>
11
#include <botan/rng.h>
12
#include <botan/internal/fmt.h>
13
#include <botan/internal/parsing.h>
14

15
namespace Botan {
16

17
namespace {
18

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

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

38
}  // namespace
39

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

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

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

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

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

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

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

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

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

82
   uint8_t family = 0;
8✔
83

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

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

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

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

104
   size_t M = 0, t = 0, p = 0;
105

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

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

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

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

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

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

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

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

142
   return constant_time_compare(generated.data(), hash.data(), generated.size());
8✔
143
}
40✔
144

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

© 2025 Coveralls, Inc