aboutsummaryrefslogtreecommitdiffstats
path: root/src/pbe/get_pbe.cpp
blob: 65c73eb31426092b5be15e5384afaedab22c34b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
* PBE Retrieval
* (C) 1999-2007 Jack Lloyd
*
* Distributed under the terms of the Botan license
*/

#include <botan/get_pbe.h>
#include <botan/oids.h>
#include <botan/scan_name.h>
#include <botan/parsing.h>
#include <botan/libstate.h>

#if defined(BOTAN_HAS_PBE_PKCS_V15)
  #include <botan/pbes1.h>
#endif

#if defined(BOTAN_HAS_PBE_PKCS_V20)
  #include <botan/pbes2.h>
  #include <botan/hmac.h>
#endif

namespace Botan {

/*
* Get an encryption PBE, set new parameters
*/
PBE* get_pbe(const std::string& algo_spec,
             const std::string& passphrase,
             std::chrono::milliseconds msec,
             RandomNumberGenerator& rng)
   {
   SCAN_Name request(algo_spec);

   const std::string pbe = request.algo_name();
   std::string digest_name = request.arg(0);
   const std::string cipher = request.arg(1);

   std::vector<std::string> cipher_spec = split_on(cipher, '/');
   if(cipher_spec.size() != 2)
      throw Invalid_Argument("PBE: Invalid cipher spec " + cipher);

   const std::string cipher_algo = global_state().deref_alias(cipher_spec[0]);
   const std::string cipher_mode = cipher_spec[1];

   if(cipher_mode != "CBC")
      throw Invalid_Argument("PBE: Invalid cipher mode " + cipher);

   Algorithm_Factory& af = global_state().algorithm_factory();

   const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_algo);
   if(!block_cipher)
      throw Algorithm_Not_Found(cipher_algo);

   const HashFunction* hash_function = af.prototype_hash_function(digest_name);
   if(!hash_function)
      throw Algorithm_Not_Found(digest_name);

   if(request.arg_count() != 2)
      throw Invalid_Algorithm_Name(algo_spec);

#if defined(BOTAN_HAS_PBE_PKCS_V15)
   if(pbe == "PBE-PKCS5v15")
      return new PBE_PKCS5v15(block_cipher->clone(),
                              hash_function->clone(),
                              passphrase,
                              msec,
                              rng);
#endif

#if defined(BOTAN_HAS_PBE_PKCS_V20)
   if(pbe == "PBE-PKCS5v20")
      return new PBE_PKCS5v20(block_cipher->clone(),
                              new HMAC(hash_function->clone()),
                              passphrase,
                              msec,
                              rng);
#endif

   throw Algorithm_Not_Found(algo_spec);
   }

/*
* Get a decryption PBE, decode parameters
*/
PBE* get_pbe(const OID& pbe_oid,
             const std::vector<byte>& params,
             const std::string& passphrase)
   {
   SCAN_Name request(OIDS::lookup(pbe_oid));

   const std::string pbe = request.algo_name();

#if defined(BOTAN_HAS_PBE_PKCS_V15)
   if(pbe == "PBE-PKCS5v15")
      {
      if(request.arg_count() != 2)
         throw Invalid_Algorithm_Name(request.as_string());

      std::string digest_name = request.arg(0);
      const std::string cipher = request.arg(1);

      std::vector<std::string> cipher_spec = split_on(cipher, '/');
      if(cipher_spec.size() != 2)
         throw Invalid_Argument("PBE: Invalid cipher spec " + cipher);

      const std::string cipher_algo = global_state().deref_alias(cipher_spec[0]);
      const std::string cipher_mode = cipher_spec[1];

      if(cipher_mode != "CBC")
         throw Invalid_Argument("PBE: Invalid cipher mode " + cipher);

      Algorithm_Factory& af = global_state().algorithm_factory();

      const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_algo);
      if(!block_cipher)
         throw Algorithm_Not_Found(cipher_algo);

      const HashFunction* hash_function =
         af.prototype_hash_function(digest_name);

      if(!hash_function)
         throw Algorithm_Not_Found(digest_name);

      return new PBE_PKCS5v15(block_cipher->clone(),
                              hash_function->clone(),
                              params,
                              passphrase);
      }
#endif

#if defined(BOTAN_HAS_PBE_PKCS_V20)
   if(pbe == "PBE-PKCS5v20")
      return new PBE_PKCS5v20(params, passphrase);
#endif

   throw Algorithm_Not_Found(pbe_oid.as_string());
   }

}