Coverage Report

Created: 2020-06-30 13:58

/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/scan_name.h>
11
12
#if defined(BOTAN_HAS_PBKDF1)
13
#include <botan/pbkdf1.h>
14
#endif
15
16
#if defined(BOTAN_HAS_PBKDF2)
17
#include <botan/pbkdf2.h>
18
#endif
19
20
#if defined(BOTAN_HAS_PGP_S2K)
21
#include <botan/pgp_s2k.h>
22
#endif
23
24
namespace Botan {
25
26
std::unique_ptr<PBKDF> PBKDF::create(const std::string& algo_spec,
27
                                     const std::string& provider)
28
0
   {
29
0
   const SCAN_Name req(algo_spec);
30
0
31
0
#if defined(BOTAN_HAS_PBKDF2)
32
0
   if(req.algo_name() == "PBKDF2")
33
0
      {
34
0
      // TODO OpenSSL
35
0
36
0
      if(provider.empty() || provider == "base")
37
0
         {
38
0
         if(auto mac = MessageAuthenticationCode::create(req.arg(0)))
39
0
            return std::unique_ptr<PBKDF>(new PKCS5_PBKDF2(mac.release()));
40
0
41
0
         if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")"))
42
0
            return std::unique_ptr<PBKDF>(new PKCS5_PBKDF2(mac.release()));
43
0
         }
44
0
45
0
      return nullptr;
46
0
      }
47
0
#endif
48
0
49
0
#if defined(BOTAN_HAS_PBKDF1)
50
0
   if(req.algo_name() == "PBKDF1" && req.arg_count() == 1)
51
0
      {
52
0
      if(auto hash = HashFunction::create(req.arg(0)))
53
0
         return std::unique_ptr<PBKDF>(new PKCS5_PBKDF1(hash.release()));
54
0
55
0
      }
56
0
#endif
57
0
58
0
#if defined(BOTAN_HAS_PGP_S2K)
59
0
   if(req.algo_name() == "OpenPGP-S2K" && req.arg_count() == 1)
60
0
      {
61
0
      if(auto hash = HashFunction::create(req.arg(0)))
62
0
         return std::unique_ptr<PBKDF>(new OpenPGP_S2K(hash.release()));
63
0
      }
64
0
#endif
65
0
66
0
   BOTAN_UNUSED(req);
67
0
   BOTAN_UNUSED(provider);
68
0
69
0
   return nullptr;
70
0
   }
71
72
//static
73
std::unique_ptr<PBKDF>
74
PBKDF::create_or_throw(const std::string& algo,
75
                             const std::string& provider)
76
0
   {
77
0
   if(auto pbkdf = PBKDF::create(algo, provider))
78
0
      {
79
0
      return pbkdf;
80
0
      }
81
0
   throw Lookup_Error("PBKDF", algo, provider);
82
0
   }
83
84
std::vector<std::string> PBKDF::providers(const std::string& algo_spec)
85
0
   {
86
0
   return probe_providers_of<PBKDF>(algo_spec, { "base", "openssl" });
87
0
   }
88
89
void PBKDF::pbkdf_timed(uint8_t out[], size_t out_len,
90
                        const std::string& passphrase,
91
                        const uint8_t salt[], size_t salt_len,
92
                        std::chrono::milliseconds msec,
93
                        size_t& iterations) const
94
0
   {
95
0
   iterations = pbkdf(out, out_len, passphrase, salt, salt_len, 0, msec);
96
0
   }
97
98
void PBKDF::pbkdf_iterations(uint8_t out[], size_t out_len,
99
                             const std::string& passphrase,
100
                             const uint8_t salt[], size_t salt_len,
101
                             size_t iterations) const
102
0
   {
103
0
   if(iterations == 0)
104
0
      throw Invalid_Argument(name() + ": Invalid iteration count");
105
0
106
0
   const size_t iterations_run = pbkdf(out, out_len, passphrase,
107
0
                                       salt, salt_len, iterations,
108
0
                                       std::chrono::milliseconds(0));
109
0
   BOTAN_ASSERT_EQUAL(iterations, iterations_run, "Expected PBKDF iterations");
110
0
   }
111
112
secure_vector<uint8_t> PBKDF::pbkdf_iterations(size_t out_len,
113
                                            const std::string& passphrase,
114
                                            const uint8_t salt[], size_t salt_len,
115
                                            size_t iterations) const
116
0
   {
117
0
   secure_vector<uint8_t> out(out_len);
118
0
   pbkdf_iterations(out.data(), out_len, passphrase, salt, salt_len, iterations);
119
0
   return out;
120
0
   }
121
122
secure_vector<uint8_t> PBKDF::pbkdf_timed(size_t out_len,
123
                                       const std::string& passphrase,
124
                                       const uint8_t salt[], size_t salt_len,
125
                                       std::chrono::milliseconds msec,
126
                                       size_t& iterations) const
127
0
   {
128
0
   secure_vector<uint8_t> out(out_len);
129
0
   pbkdf_timed(out.data(), out_len, passphrase, salt, salt_len, msec, iterations);
130
0
   return out;
131
0
   }
132
133
}