1 /**
2 * Filters
3 * 
4 * Copyright:
5 * (C) 1999-2007 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.filters.filters;
12 
13 public import botan.filters.filter;
14 public import botan.filters.pipe;
15 public import botan.filters.basefilt;
16 public import botan.filters.key_filt;
17 import botan.algo_factory.algo_factory;
18 import botan.block.block_cipher;
19 import botan.stream.stream_cipher;
20 import botan.hash.hash;
21 import botan.mac.mac;
22 
23 import botan.libstate.libstate;
24 import botan.algo_base.scan_token;
25 
26 import botan.constants;
27 static if (BOTAN_HAS_CODEC_FILTERS) {
28   import botan.filters.b64_filt;
29   import botan.filters.hex_filt;
30 }
31 
32 import std.algorithm;
33 
34 /**
35 * Stream Cipher Filter
36 */
37 final class StreamCipherFilter : KeyedFilter, Filterable
38 {
39 public:
40 
41     override @property string name() const { return m_cipher.name; }
42 
43     /**
44     * Write input data
45     * Params:
46     *  input = data
47     *  length = length of input in bytes
48     */
49     override void write(const(ubyte)* input, size_t length)
50     {
51         while (length)
52         {
53             size_t copied = std.algorithm.min(length, m_buffer.length);
54             m_cipher.cipher(input, m_buffer.ptr, copied);
55             send(m_buffer, copied);
56             input += copied;
57             length -= copied;
58         }
59     }
60 
61     override bool validIvLength(size_t iv_len) const
62     { return m_cipher.validIvLength(iv_len); }
63 
64     /**
65     * Set the initialization vector for this filter.
66     *
67     * Params:
68     *  iv = the initialization vector to set
69     */
70     override void setIv(in InitializationVector iv)
71     {
72         m_cipher.setIv(iv.ptr, iv.length);
73     }
74 
75 
76     /**
77     * Set the key of this filter.
78     *
79     * Params:
80     *  key = the key to set
81     */
82     override void setKey(in SymmetricKey key) { m_cipher.setKey(key); }
83 
84     override KeyLengthSpecification keySpec() const { return m_cipher.keySpec(); }
85 
86     /**
87     * Construct a stream cipher filter.
88     *
89     * Params:
90     *  stream_cipher = a cipher object to use
91     */
92     this(StreamCipher stream_cipher)
93     {
94         m_buffer = SecureVector!ubyte(DEFAULT_BUFFERSIZE);
95         m_cipher = stream_cipher;
96     }
97 
98     /**
99     * Construct a stream cipher filter.
100     *
101     * Params:
102     *  stream_cipher = a cipher object to use
103     *  key = the key to use inside this filter
104     */
105     this(StreamCipher stream_cipher, in SymmetricKey key)
106     {
107         m_buffer = SecureVector!ubyte(DEFAULT_BUFFERSIZE);
108         m_cipher = stream_cipher;
109         m_cipher.setKey(key);
110     }
111 
112     /**
113     * Construct a stream cipher filter.
114     *
115     * Params:
116     *  sc_name = the name of the desired cipher
117     */
118     this(in string sc_name)
119         
120     {
121         m_buffer = SecureVector!ubyte(DEFAULT_BUFFERSIZE);
122         AlgorithmFactory af = globalState().algorithmFactory();
123         m_cipher = af.makeStreamCipher(sc_name);
124     }
125 
126     /**
127     * Construct a stream cipher filter.
128     *
129     * Params:
130     *  sc_name = the name of the desired cipher
131     *  key = the key to use inside this filter
132     */
133     this(in string sc_name, in SymmetricKey key)
134     {
135         m_buffer = SecureVector!ubyte(DEFAULT_BUFFERSIZE);
136         AlgorithmFactory af = globalState().algorithmFactory();
137         m_cipher = af.makeStreamCipher(sc_name);
138         m_cipher.setKey(key);
139     }
140 
141     // Interface fallthrough
142     override bool attachable() { return super.attachable(); }
143     override void startMsg() { super.startMsg(); }
144     override void endMsg() { super.endMsg(); }
145     override void setNext(Filter* filters, size_t sz) { super.setNext(filters, sz); }
146 private:
147     SecureVector!ubyte m_buffer;
148     Unique!StreamCipher m_cipher;
149 }
150 
151 /**
152 * Hash Filter.
153 */
154 final class HashFilter : Filter, Filterable
155 {
156 public:
157     override void write(const(ubyte)* input, size_t len) { m_hash.update(input, len); }
158 
159     /*
160     * Complete a calculation by a HashFilter
161     */
162     override void endMsg()
163     {
164         SecureVector!ubyte output = m_hash.finished();
165         if (m_OUTPUT_LENGTH)
166             send(output, std.algorithm.min(m_OUTPUT_LENGTH, output.length));
167         else
168             send(output);
169     }
170 
171     override @property string name() const { return m_hash.name; }
172 
173     /**
174     * Construct a hash filter.
175     *
176     * Params:
177     *  hash_fun = the hash function to use
178     *  len = the output length of this filter. Leave the default
179     * value 0 if you want to use the full output of the hashfunction
180     * hash. Otherwise, specify a smaller value here so that the
181     * output of the hash algorithm will be cut off.
182     */
183     this(HashFunction hash_fun, size_t len = 0)
184     {
185         m_OUTPUT_LENGTH = len;
186         m_hash = hash_fun;
187     }
188 
189     /**
190     * Construct a hash filter.
191     *
192     * Params:
193     *  algo_spec = the name of the hash algorithm to use
194     *  len = the output length of this filter. Leave the default
195     * value 0 if you want to use the full output of the hashfunction
196     * hash. Otherwise, specify a smaller value here so that the
197     * output of the hash algorithm will be cut off.
198     */
199     this(in string algo_spec, size_t len = 0)
200     {
201         m_OUTPUT_LENGTH = len;
202         AlgorithmFactory af = globalState().algorithmFactory();
203         m_hash = af.makeHashFunction(algo_spec);
204     }
205 
206     ~this() { }
207 
208     // Interface fallthrough
209     override bool attachable() { return super.attachable(); }
210     override void startMsg() { super.startMsg(); }
211     override void setNext(Filter* filters, size_t sz) { super.setNext(filters, sz); }
212 private:
213     const size_t m_OUTPUT_LENGTH;
214     Unique!HashFunction m_hash;
215 }
216 
217 /**
218 * MessageAuthenticationCode Filter.
219 */
220 final class MACFilter : KeyedFilter, Filterable
221 {
222 public:
223     override void write(const(ubyte)* input, size_t len) { m_mac.update(input, len); }
224 
225     /*
226     * Complete a calculation by a MACFilter
227     */
228     override void endMsg()
229     {
230         SecureVector!ubyte output = m_mac.finished();
231         if (m_OUTPUT_LENGTH)
232             send(output, std.algorithm.min(m_OUTPUT_LENGTH, output.length));
233         else
234             send(output);
235     }
236 
237     override @property string name() const { return m_mac.name; }
238 
239     /**
240     * Set the key of this filter.
241     *
242     * Params:
243     *  key = the key to set
244     */
245     override void setKey(in SymmetricKey key) { m_mac.setKey(key); }
246 
247     override KeyLengthSpecification keySpec() const { return m_mac.keySpec(); }
248 
249     override bool validIvLength(size_t length) const { return length == 0; }
250 
251     /**
252     * Construct a MAC filter. The MAC key will be left empty.
253     *
254     * Params:
255     *  mac_obj = the MAC to use
256     *  out_len = the output length of this filter. Leave the default
257     * value 0 if you want to use the full output of the
258     * MAC. Otherwise, specify a smaller value here so that the
259     * output of the MAC will be cut off.
260     */
261     this(MessageAuthenticationCode mac_obj, size_t out_len = 0) 
262     {
263         m_OUTPUT_LENGTH = out_len;
264         m_mac = mac_obj;
265     }
266 
267     /**
268     * Construct a MAC filter.
269     *
270     * Params:
271     *  mac_obj = the MAC to use
272     *  key = the MAC key to use
273     *  out_len = the output length of this filter. Leave the default
274     * value 0 if you want to use the full output of the
275     * MAC. Otherwise, specify a smaller value here so that the
276     * output of the MAC will be cut off.
277     */
278     this(MessageAuthenticationCode mac_obj, in SymmetricKey key, size_t out_len = 0)
279     {
280         m_OUTPUT_LENGTH = out_len;
281         m_mac = mac_obj;
282         m_mac.setKey(key);
283     }
284 
285     /**
286     * Construct a MAC filter. The MAC key will be left empty.
287     *
288     * Params:
289     *  mac_name = the name of the MAC to use
290     *  len = the output length of this filter. Leave the default
291     * value 0 if you want to use the full output of the
292     * MAC. Otherwise, specify a smaller value here so that the
293     * output of the MAC will be cut off.
294     */
295     this(in string mac_name, size_t len = 0)
296     {
297         m_OUTPUT_LENGTH = len;
298         AlgorithmFactory af = globalState().algorithmFactory();
299         m_mac = af.makeMac(mac_name);
300     }
301 
302     /**
303     * Construct a MAC filter.
304     *
305     * Params:
306     *  mac_name = the name of the MAC to use
307     *  key = the MAC key to use
308     *  len = the output length of this filter. Leave the default
309     * value 0 if you want to use the full output of the
310     * MAC. Otherwise, specify a smaller value here so that the
311     * output of the MAC will be cut off.
312     */
313     this(in string mac_name, in SymmetricKey key, size_t len = 0)
314     {
315         m_OUTPUT_LENGTH = len;
316         AlgorithmFactory af = globalState().algorithmFactory();
317         m_mac = af.makeMac(mac_name);
318         m_mac.setKey(key);
319     }
320 
321     ~this() { }
322 
323     // Interface fallthrough
324     override bool attachable() { return super.attachable(); }
325     override void startMsg() { super.startMsg(); }
326     override void setNext(Filter* filters, size_t sz) { super.setNext(filters, sz); }
327 private:
328     const size_t m_OUTPUT_LENGTH;
329     Unique!MessageAuthenticationCode m_mac;
330 }