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