1 /**
2 * Buffered Computation
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 
12 module botan.algo_base.buf_comp;
13 
14 import memutils.vector;
15 import botan.utils.get_byte;
16 import botan.utils.types;
17 
18 /**
19 * This class represents any kind of computation which uses an internal
20 * state, such as hash functions or MACs
21 */
22 interface BufferedComputation
23 {
24 public:
25 
26     /**
27     * Add new input to process.
28     * 
29     * Params:
30     *  input = the input to process as a ubyte array
31     */
32     final void update(in ubyte[] input) { addData(input.ptr, input.length); }
33 
34     /**
35     * Add new input to process.
36     * 
37     * Params:
38     *  input = the input to process as a ubyte array
39     *  length = of param in in bytes
40     */
41     final void update(const(ubyte)* input, size_t length) { addData(input, length); }
42 
43     /**
44     * Add new input to process.
45     * Params:
46     *  input = the input to process as a reference type
47     */
48     final void update(T, ALLOC)(auto const ref RefCounted!(Vector!(T, ALLOC)) input)
49     {
50         addData(input.ptr, input.length);
51     }
52 
53     /**
54     * Add new input to process.
55     * 
56     * Params:
57     *  input = the input to process as a $(D Vector)
58     */
59     final void update(T, ALLOC)(auto const ref Vector!(T, ALLOC) input)
60     {
61         addData(input.ptr, input.length);
62     }
63 
64     /**
65     * Add an integer in big-endian order
66     * 
67     * Params:
68     *  input = the value
69     */
70     final void updateBigEndian(T)(in T input)
71     {
72         foreach (size_t i; 0 .. T.sizeof)
73         {
74             ubyte b = get_byte(i, input);
75             addData(&b, 1);
76         }
77     }
78 
79     /**
80     * Add new input to process.
81     * 
82     * Params:
83     *  str = The input to process as a string. 
84     * 
85     * Notes: Will be interpreted as a ubyte array based on the strings encoding.
86     */
87     final void update(in string str)
88     {
89         addData(str.ptr, str.length);
90     }
91 
92     /**
93     * Process a single ubyte.
94     * 
95     * Params:
96     *  input = the ubyte to process
97     */
98     final void update(ubyte input) { addData(&input, 1); }
99 
100     /**
101     * Complete the computation and retrieve the final result.
102     * 
103     * Params:
104     *  output = The ubyte array to be filled with the result.
105     * 
106     * Notes: Must be of length outputLength()
107     */
108     final void flushInto(ref ubyte[] output) 
109     in { assert(output.length == outputLength); }
110     body { finalResult(output.ptr); }
111 
112     /**
113     * Complete the computation and retrieve the
114     * final result.
115     * 
116     * Params:
117     *  output = The ubyte array to be filled with the result.
118     * 
119     * Notes: Must be of length outputLength()
120     */
121     final void flushInto(ubyte* output) { finalResult(output); }
122 
123     /**
124     * Complete the computation and retrieve the final result.
125     * 
126     * Returns: $(D SecureVector) holding the result
127     */
128     final SecureVector!ubyte finished()
129     {
130         SecureVector!ubyte output = SecureVector!ubyte(outputLength());
131         finalResult(output.ptr);
132         return output.move;
133     }
134 
135     /**
136     * Update and finalize computation. Does the same as calling $(D update())
137     * and $(D finished()) consecutively.
138     * 
139     * Params:
140     *  input = the input to process as a ubyte array
141     * 
142     * Returns: The result of the call to $(D finished())
143     */
144     final SecureVector!ubyte process(in ubyte[] input)
145     {
146         addData(input.ptr, input.length);
147         return finished();
148     }
149 
150     /**
151     * Update and finalize computation. Does the same as calling $(D update())
152     * and $(D finished()) consecutively.
153     * 
154     * Params:
155     *  input = the input to process as a ubyte array
156     *  length = the length of the ubyte array
157     * 
158     * Returns: The result of the call to $(D finished())
159     */
160     final SecureVector!ubyte process(const(ubyte)* input, size_t length)
161     {
162         addData(input, length);
163         return finished();
164     }
165 
166     /**
167     * Update and finalize computation. Does the same as calling $(D update())
168     * and $(D finished()) consecutively.
169     * Params:
170     *  input = the input to process
171     * 
172     * Returns: The result of the call to $(D finished())
173     */
174     final SecureVector!ubyte process(ALLOC)(auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) input)
175     {
176         addData(input.ptr, input.length);
177         return finished();
178     }
179 
180     /**
181     * Update and finalize computation. Does the same as calling $(D update())
182     * and $(D finished()) consecutively.
183     * Params:
184     *  input = the input to process
185     * 
186     * Returns: The result of the call to $(D finished())
187     */
188     final SecureVector!ubyte process(ALLOC)(auto const ref Vector!(ubyte, ALLOC) input)
189     {
190         addData(input.ptr, input.length);
191         return finished();
192     }
193 
194     /**
195     * Update and finalize computation. Does the same as calling $(D update())
196     * and $(D finished()) consecutively.
197     * Params:
198     *  input = the input to process as a string
199     * 
200     * Returns: The result of the call to $(D finished())
201     */
202     final SecureVector!ubyte process(in string input)
203     {
204         update(input);
205         return finished();
206     }
207 
208     final void addData(T)(in T input, size_t length) {
209         addData(cast(const(ubyte)*)input, length);
210     }
211 
212     /**
213     * Returns: Length of the output of this function in bytes
214     */
215     abstract @property size_t outputLength() const;
216 
217 protected:
218     /**
219     * Add more data to the computation
220     * 
221     * Params:
222     *  input = is an input buffer
223     *  length = is the length of input in bytes
224     */
225     abstract void addData(const(ubyte)* input, size_t length);
226 
227     /**
228     * Write the final output to out
229     * 
230     * Params:
231     *  output = An output buffer of size $(D outputLength())
232     */
233     abstract void finalResult(ubyte* output);
234 }