Botan 1.10.17

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
77 Keyed_Filter* get_cipher_mode(const BlockCipher* block_cipher,
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 }
Botan::parse_algorithm_name
std::vector< std::string > parse_algorithm_name(const std::string &namex)
Definition: parsing.cpp:96
Botan::Core_Engine::get_cipher
Keyed_Filter * get_cipher(const std::string &, Cipher_Dir, Algorithm_Factory &)
Definition: core_modes.cpp:181
Botan::StreamCipher_Filter
Definition: filters.h:33
Botan::Algorithm_Factory
Definition: algo_factory.h:34
Botan::Keyed_Filter
Definition: key_filt.h:20
Botan::ENCRYPTION
Definition: sym_algo.h:87
Botan::OFB
Definition: ofb.h:19
Botan::CTR_BE
Definition: ctr.h:19
Botan::BlockCipher::clone
virtual BlockCipher * clone() const =0
Botan::XTS_Encryption
Definition: xts.h:20
Botan::Algorithm_Factory::prototype_block_cipher
const BlockCipher * prototype_block_cipher(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:193
Botan::split_on
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:152
Botan::XTS_Decryption
Definition: xts.h:57
Botan::CTS_Decryption
Definition: cts.h:54
Botan::EAX_Decryption
Definition: eax.h:131
Botan::EAX_Encryption
Definition: eax.h:100
Botan::CTS_Encryption
Definition: cts.h:19
Botan::CBC_Decryption
Definition: cbc.h:61
Botan::CBC_Encryption
Definition: cbc.h:21
Botan::ECB_Decryption
Definition: ecb.h:55
Botan::ECB_Encryption
Definition: ecb.h:21
Botan::StreamCipher
Definition: stream_cipher.h:18
Botan::Lookup_Error
Definition: exceptn.h:35
Botan
Definition: algo_base.h:14
Botan::StreamCipher::clone
virtual StreamCipher * clone() const =0
Botan::Invalid_Algorithm_Name
Definition: exceptn.h:119
Botan::CFB_Decryption
Definition: cfb.h:53
Botan::CFB_Encryption
Definition: cfb.h:19
Botan::Cipher_Dir
Cipher_Dir
Definition: sym_algo.h:87
Botan::Algorithm_Not_Found
Definition: exceptn.h:109
Botan::to_u32bit
u32bit to_u32bit(const std::string &number)
Definition: parsing.cpp:18
Botan::get_cipher_mode
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
Botan::BlockCipher::block_size
virtual size_t block_size() const =0
Botan::Algorithm_Factory::prototype_stream_cipher
const StreamCipher * prototype_stream_cipher(const std::string &algo_spec, const std::string &provider="")
Definition: algo_factory.cpp:204
Botan::BlockCipher
Definition: block_cipher.h:18