Coverage Report

Created: 2021-02-21 07:20

/src/botan/src/lib/pbkdf/pbkdf.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* PBKDF
3
* (C) 2012 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/pbkdf.h>
9
#include <botan/exceptn.h>
10
#include <botan/internal/scan_name.h>
11
12
#if defined(BOTAN_HAS_PBKDF2)
13
#include <botan/pbkdf2.h>
14
#endif
15
16
#if defined(BOTAN_HAS_PGP_S2K)
17
#include <botan/pgp_s2k.h>
18
#endif
19
20
namespace Botan {
21
22
std::unique_ptr<PBKDF> PBKDF::create(const std::string& algo_spec,
23
                                     const std::string& provider)
24
0
   {
25
0
   const SCAN_Name req(algo_spec);
26
27
0
#if defined(BOTAN_HAS_PBKDF2)
28
0
   if(req.algo_name() == "PBKDF2")
29
0
      {
30
      // TODO OpenSSL
31
32
0
      if(provider.empty() || provider == "base")
33
0
         {
34
0
         if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")"))
35
0
            return std::unique_ptr<PBKDF>(new PKCS5_PBKDF2(mac.release()));
36
37
0
         if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
38
0
            return std::unique_ptr<PBKDF>(new PKCS5_PBKDF2(mac.release()));
39
0
         }
40
41
0
      return nullptr;
42
0
      }
43
0
#endif
44
45
0
#if defined(BOTAN_HAS_PGP_S2K)
46
0
   if(req.algo_name() == "OpenPGP-S2K" && req.arg_count() == 1)
47
0
      {
48
0
      if(auto hash = HashFunction::create(req.arg(0)))
49
0
         return std::unique_ptr<PBKDF>(new OpenPGP_S2K(hash.release()));
50
0
      }
51
0
#endif
52
53
0
   BOTAN_UNUSED(req);
54
0
   BOTAN_UNUSED(provider);
55
56
0
   return nullptr;
57
0
   }
58
59
//static
60
std::unique_ptr<PBKDF>
61
PBKDF::create_or_throw(const std::string& algo,
62
                             const std::string& provider)
63
0
   {
64
0
   if(auto pbkdf = PBKDF::create(algo, provider))
65
0
      {
66
0
      return pbkdf;
67
0
      }
68
0
   throw Lookup_Error("PBKDF", algo, provider);
69
0
   }
70
71
std::vector<std::string> PBKDF::providers(const std::string& algo_spec)
72
0
   {
73
0
   return probe_providers_of<PBKDF>(algo_spec, { "base", "openssl" });
74
0
   }
75
76
void PBKDF::pbkdf_timed(uint8_t out[], size_t out_len,
77
                        const std::string& passphrase,
78
                        const uint8_t salt[], size_t salt_len,
79
                        std::chrono::milliseconds msec,
80
                        size_t& iterations) const
81
0
   {
82
0
   iterations = pbkdf(out, out_len, passphrase, salt, salt_len, 0, msec);
83
0
   }
84
85
void PBKDF::pbkdf_iterations(uint8_t out[], size_t out_len,
86
                             const std::string& passphrase,
87
                             const uint8_t salt[], size_t salt_len,
88
                             size_t iterations) const
89
0
   {
90
0
   if(iterations == 0)
91
0
      throw Invalid_Argument(name() + ": Invalid iteration count");
92
93
0
   const size_t iterations_run = pbkdf(out, out_len, passphrase,
94
0
                                       salt, salt_len, iterations,
95
0
                                       std::chrono::milliseconds(0));
96
0
   BOTAN_ASSERT_EQUAL(iterations, iterations_run, "Expected PBKDF iterations");
97
0
   }
98
99
secure_vector<uint8_t> PBKDF::pbkdf_iterations(size_t out_len,
100
                                            const std::string& passphrase,
101
                                            const uint8_t salt[], size_t salt_len,
102
                                            size_t iterations) const
103
0
   {
104
0
   secure_vector<uint8_t> out(out_len);
105
0
   pbkdf_iterations(out.data(), out_len, passphrase, salt, salt_len, iterations);
106
0
   return out;
107
0
   }
108
109
secure_vector<uint8_t> PBKDF::pbkdf_timed(size_t out_len,
110
                                       const std::string& passphrase,
111
                                       const uint8_t salt[], size_t salt_len,
112
                                       std::chrono::milliseconds msec,
113
                                       size_t& iterations) const
114
0
   {
115
0
   secure_vector<uint8_t> out(out_len);
116
0
   pbkdf_timed(out.data(), out_len, passphrase, salt, salt_len, msec, iterations);
117
0
   return out;
118
0
   }
119
120
}