Botan  1.10.9
core_modes.cpp
Go to the documentation of this file.
1 /*
2 * Core Engine
3 * (C) 1999-2007,2011 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/internal/core_engine.h>
9 #include <botan/parsing.h>
10 #include <botan/filters.h>
11 #include <botan/algo_factory.h>
12 #include <botan/mode_pad.h>
13 #include <memory>
14 
15 #if defined(BOTAN_HAS_ECB)
16  #include <botan/ecb.h>
17 #endif
18 
19 #if defined(BOTAN_HAS_CBC)
20  #include <botan/cbc.h>
21 #endif
22 
23 #if defined(BOTAN_HAS_CTS)
24  #include <botan/cts.h>
25 #endif
26 
27 #if defined(BOTAN_HAS_CFB)
28  #include <botan/cfb.h>
29 #endif
30 
31 #if defined(BOTAN_HAS_OFB)
32  #include <botan/ofb.h>
33 #endif
34 
35 #if defined(BOTAN_HAS_CTR_BE)
36  #include <botan/ctr.h>
37 #endif
38 
39 #if defined(BOTAN_HAS_EAX)
40  #include <botan/eax.h>
41 #endif
42 
43 #if defined(BOTAN_HAS_XTS)
44  #include <botan/xts.h>
45 #endif
46 
47 namespace Botan {
48 
49 namespace {
50 
51 /**
52 * Get a block cipher padding method by name
53 */
54 BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec,
55  const std::string& def_if_empty)
56  {
57 #if defined(BOTAN_HAS_CIPHER_MODE_PADDING)
58  if(algo_spec == "NoPadding" || (algo_spec == "" && def_if_empty == "NoPadding"))
59  return new Null_Padding;
60 
61  if(algo_spec == "PKCS7" || (algo_spec == "" && def_if_empty == "PKCS7"))
62  return new PKCS7_Padding;
63 
64  if(algo_spec == "OneAndZeros")
65  return new OneAndZeros_Padding;
66 
67  if(algo_spec == "X9.23")
68  return new ANSI_X923_Padding;
69 
70 #endif
71 
72  throw Algorithm_Not_Found(algo_spec);
73  }
74 
75 }
76 
78  Cipher_Dir direction,
79  const std::string& mode,
80  const std::string& padding)
81  {
82 #if defined(BOTAN_HAS_OFB)
83  if(mode == "OFB")
84  return new StreamCipher_Filter(new OFB(block_cipher->clone()));
85 #endif
86 
87 #if defined(BOTAN_HAS_CTR_BE)
88  if(mode == "CTR-BE")
89  return new StreamCipher_Filter(new CTR_BE(block_cipher->clone()));
90 #endif
91 
92 #if defined(BOTAN_HAS_ECB)
93  if(mode == "ECB" || mode == "")
94  {
95  if(direction == ENCRYPTION)
96  return new ECB_Encryption(block_cipher->clone(),
97  get_bc_pad(padding, "NoPadding"));
98  else
99  return new ECB_Decryption(block_cipher->clone(),
100  get_bc_pad(padding, "NoPadding"));
101  }
102 #endif
103 
104  if(mode == "CBC")
105  {
106  if(padding == "CTS")
107  {
108 #if defined(BOTAN_HAS_CTS)
109  if(direction == ENCRYPTION)
110  return new CTS_Encryption(block_cipher->clone());
111  else
112  return new CTS_Decryption(block_cipher->clone());
113 #else
114  return 0;
115 #endif
116  }
117 
118 #if defined(BOTAN_HAS_CBC)
119  if(direction == ENCRYPTION)
120  return new CBC_Encryption(block_cipher->clone(),
121  get_bc_pad(padding, "PKCS7"));
122  else
123  return new CBC_Decryption(block_cipher->clone(),
124  get_bc_pad(padding, "PKCS7"));
125 #else
126  return 0;
127 #endif
128  }
129 
130 #if defined(BOTAN_HAS_XTS)
131  if(mode == "XTS")
132  {
133  if(direction == ENCRYPTION)
134  return new XTS_Encryption(block_cipher->clone());
135  else
136  return new XTS_Decryption(block_cipher->clone());
137  }
138 #endif
139 
140  if(mode.find("CFB") != std::string::npos ||
141  mode.find("EAX") != std::string::npos)
142  {
143  size_t bits = 0;
144 
145  std::vector<std::string> algo_info = parse_algorithm_name(mode);
146  std::string mode_name = algo_info[0];
147  if(algo_info.size() == 1)
148  bits = 8 * block_cipher->block_size();
149  else if(algo_info.size() == 2)
150  bits = to_u32bit(algo_info[1]);
151  else
152  return 0;
153 
154 #if defined(BOTAN_HAS_CFB)
155  if(mode_name == "CFB")
156  {
157  if(direction == ENCRYPTION)
158  return new CFB_Encryption(block_cipher->clone(), bits);
159  else
160  return new CFB_Decryption(block_cipher->clone(), bits);
161  }
162 #endif
163 
164 #if defined(BOTAN_HAS_EAX)
165  if(mode_name == "EAX")
166  {
167  if(direction == ENCRYPTION)
168  return new EAX_Encryption(block_cipher->clone(), bits);
169  else
170  return new EAX_Decryption(block_cipher->clone(), bits);
171  }
172 #endif
173  }
174 
175  return 0;
176  }
177 
178 /*
179 * Get a cipher object
180 */
181 Keyed_Filter* Core_Engine::get_cipher(const std::string& algo_spec,
182  Cipher_Dir direction,
183  Algorithm_Factory& af)
184  {
185  std::vector<std::string> algo_parts = split_on(algo_spec, '/');
186  if(algo_parts.empty())
187  throw Invalid_Algorithm_Name(algo_spec);
188 
189  const std::string cipher_name = algo_parts[0];
190 
191  // check if it is a stream cipher first (easy case)
192  const StreamCipher* stream_cipher = af.prototype_stream_cipher(cipher_name);
193  if(stream_cipher)
194  return new StreamCipher_Filter(stream_cipher->clone());
195 
196  const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_name);
197  if(!block_cipher)
198  return 0;
199 
200  if(algo_parts.size() >= 4)
201  return 0; // 4 part mode, not something we know about
202 
203  if(algo_parts.size() < 2)
204  throw Lookup_Error("Cipher specification '" + algo_spec +
205  "' is missing mode identifier");
206 
207  std::string mode = algo_parts[1];
208 
209  std::string padding;
210  if(algo_parts.size() == 3)
211  padding = algo_parts[2];
212  else
213  padding = (mode == "CBC") ? "PKCS7" : "NoPadding";
214 
215  if(mode == "ECB" && padding == "CTS")
216  return 0;
217  else if((mode != "CBC" && mode != "ECB") && padding != "NoPadding")
218  throw Invalid_Algorithm_Name(algo_spec);
219 
220  Keyed_Filter* filt = get_cipher_mode(block_cipher, direction, mode, padding);
221  if(filt)
222  return filt;
223 
224  throw Algorithm_Not_Found(cipher_name + "/" + mode + "/" + padding);
225  }
226 
227 }
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition: parsing.cpp:96
Keyed_Filter * get_cipher(const std::string &, Cipher_Dir, Algorithm_Factory &)
Definition: core_modes.cpp:181
Definition: ofb.h:19
virtual BlockCipher * clone() const =0
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:152
virtual StreamCipher * clone() const =0
std::string cipher_name
Definition: ossl_bc.cpp:42
Cipher_Dir
Definition: sym_algo.h:87
u32bit to_u32bit(const std::string &number)
Definition: parsing.cpp:18
Keyed_Filter * get_cipher_mode(const BlockCipher *block_cipher, Cipher_Dir direction, const std::string &mode, const std::string &padding)
Definition: core_modes.cpp:77
virtual size_t block_size() const =0
const StreamCipher * prototype_stream_cipher(const std::string &algo_spec, const std::string &provider="")