Botan  2.1.0
Crypto and TLS for C++11
cipher_mode.cpp
Go to the documentation of this file.
1 /*
2 * Cipher Modes
3 * (C) 2015 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/cipher_mode.h>
9 #include <botan/stream_mode.h>
10 #include <botan/scan_name.h>
11 #include <sstream>
12 
13 #if defined(BOTAN_HAS_BLOCK_CIPHER)
14  #include <botan/block_cipher.h>
15 #endif
16 
17 #if defined(BOTAN_HAS_AEAD_MODES)
18  #include <botan/aead.h>
19 #endif
20 
21 #if defined(BOTAN_HAS_MODE_CBC)
22  #include <botan/cbc.h>
23 #endif
24 
25 #if defined(BOTAN_HAS_MODE_CFB)
26  #include <botan/cfb.h>
27 #endif
28 
29 #if defined(BOTAN_HAS_MODE_XTS)
30  #include <botan/xts.h>
31 #endif
32 
33 #if defined(BOTAN_HAS_MODE_XTS)
34  #include <botan/xts.h>
35 #endif
36 
37 namespace Botan {
38 
39 Cipher_Mode* get_cipher_mode(const std::string& algo, Cipher_Dir direction)
40  {
41  if(auto sc = StreamCipher::create(algo))
42  {
43  return new Stream_Cipher_Mode(sc.release());
44  }
45 
46 #if defined(BOTAN_HAS_AEAD_MODES)
47  if(auto aead = get_aead(algo, direction))
48  {
49  return aead;
50  }
51 #endif
52 
53  if(algo.find('/') != std::string::npos)
54  {
55  const std::vector<std::string> algo_parts = split_on(algo, '/');
56  const std::string cipher_name = algo_parts[0];
57  const std::vector<std::string> mode_info = parse_algorithm_name(algo_parts[1]);
58 
59  if(mode_info.empty())
60  return nullptr;
61 
62  std::ostringstream alg_args;
63 
64  alg_args << '(' << cipher_name;
65  for(size_t i = 1; i < mode_info.size(); ++i)
66  alg_args << ',' << mode_info[i];
67  for(size_t i = 2; i < algo_parts.size(); ++i)
68  alg_args << ',' << algo_parts[i];
69  alg_args << ')';
70 
71  const std::string mode_name = mode_info[0] + alg_args.str();
72  return get_cipher_mode(mode_name, direction);
73  }
74 
75 #if defined(BOTAN_HAS_BLOCK_CIPHER)
76 
77  SCAN_Name spec(algo);
78 
79  if(spec.arg_count() == 0)
80  {
81  return nullptr;
82  }
83 
84  std::unique_ptr<BlockCipher> bc(BlockCipher::create(spec.arg(0)));
85 
86  if(!bc)
87  {
88  return nullptr;
89  }
90 
91 #if defined(BOTAN_HAS_MODE_CBC)
92  if(spec.algo_name() == "CBC")
93  {
94  const std::string padding = spec.arg(1, "PKCS7");
95 
96  if(padding == "CTS")
97  {
98  if(direction == ENCRYPTION)
99  return new CTS_Encryption(bc.release());
100  else
101  return new CTS_Decryption(bc.release());
102  }
103  else
104  {
105  std::unique_ptr<BlockCipherModePaddingMethod> pad(get_bc_pad(padding));
106 
107  if(pad)
108  {
109  if(direction == ENCRYPTION)
110  return new CBC_Encryption(bc.release(), pad.release());
111  else
112  return new CBC_Decryption(bc.release(), pad.release());
113  }
114  }
115  }
116 #endif
117 
118 #if defined(BOTAN_HAS_MODE_XTS)
119  if(spec.algo_name() == "XTS")
120  {
121  if(direction == ENCRYPTION)
122  return new XTS_Encryption(bc.release());
123  else
124  return new XTS_Decryption(bc.release());
125  }
126 #endif
127 
128 #if defined(BOTAN_HAS_MODE_CFB)
129  if(spec.algo_name() == "CFB")
130  {
131  const size_t feedback_bits = spec.arg_as_integer(1, 8*bc->block_size());
132  if(direction == ENCRYPTION)
133  return new CFB_Encryption(bc.release(), feedback_bits);
134  else
135  return new CFB_Decryption(bc.release(), feedback_bits);
136  }
137 #endif
138 
139 #endif
140 
141  return nullptr;
142  }
143 
144 }
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition: parsing.cpp:85
std::string arg(size_t i) const
Definition: scan_name.cpp:122
BlockCipherModePaddingMethod * get_bc_pad(const std::string &algo_spec)
Definition: mode_pad.cpp:18
Cipher_Mode * get_cipher_mode(const std::string &algo, Cipher_Dir direction)
Definition: cipher_mode.cpp:39
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:138
size_t arg_count() const
Definition: scan_name.h:50
size_t arg_as_integer(size_t i, size_t def_value) const
Definition: scan_name.cpp:137
AEAD_Mode * get_aead(const std::string &algo, Cipher_Dir dir)
Definition: aead.cpp:41
Definition: alg_id.cpp:13
static std::unique_ptr< BlockCipher > create(const std::string &algo_spec, const std::string &provider="")
const std::string & algo_name() const
Definition: scan_name.h:45
static std::unique_ptr< StreamCipher > create(const std::string &algo_spec, const std::string &provider="")