1 /*
2  * Copyright (c) 2017-2020, [Ribose Inc](https://www.ribose.com).
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *
11  * 2.  Redistributions in binary form must reproduce the above copyright notice,
12  *     this list of conditions and the following disclaimer in the documentation
13  *     and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #ifndef STREAM_COMMON_H_
28 #define STREAM_COMMON_H_
29 
30 #include <stdint.h>
31 #include <stdbool.h>
32 #include <sys/types.h>
33 #include "types.h"
34 
35 #define PGP_INPUT_CACHE_SIZE 32768
36 #define PGP_OUTPUT_CACHE_SIZE 32768
37 
38 #define PGP_PARTIAL_PKT_FIRST_PART_MIN_SIZE 512
39 
40 typedef enum {
41     PGP_STREAM_NULL,
42     PGP_STREAM_FILE,
43     PGP_STREAM_MEMORY,
44     PGP_STREAM_STDIN,
45     PGP_STREAM_STDOUT,
46     PGP_STREAM_PACKET,
47     PGP_STREAM_PARLEN_PACKET,
48     PGP_STREAM_LITERAL,
49     PGP_STREAM_COMPRESSED,
50     PGP_STREAM_ENCRYPTED,
51     PGP_STREAM_SIGNED,
52     PGP_STREAM_ARMORED,
53     PGP_STREAM_CLEARTEXT
54 } pgp_stream_type_t;
55 
56 typedef struct pgp_source_t pgp_source_t;
57 typedef struct pgp_dest_t   pgp_dest_t;
58 
59 typedef bool pgp_source_read_func_t(pgp_source_t *src, void *buf, size_t len, size_t *read);
60 typedef rnp_result_t pgp_source_finish_func_t(pgp_source_t *src);
61 typedef void         pgp_source_close_func_t(pgp_source_t *src);
62 
63 typedef rnp_result_t pgp_dest_write_func_t(pgp_dest_t *dst, const void *buf, size_t len);
64 typedef rnp_result_t pgp_dest_finish_func_t(pgp_dest_t *src);
65 typedef void         pgp_dest_close_func_t(pgp_dest_t *dst, bool discard);
66 
67 /* statically preallocated cache for sources */
68 typedef struct pgp_source_cache_t {
69     uint8_t  buf[PGP_INPUT_CACHE_SIZE];
70     unsigned pos;       /* current position in cache */
71     unsigned len;       /* number of bytes available in cache */
72     bool     readahead; /* whether read-ahead with larger chunks allowed */
73 } pgp_source_cache_t;
74 
75 typedef struct pgp_source_t {
76     pgp_source_read_func_t *  read;
77     pgp_source_finish_func_t *finish;
78     pgp_source_close_func_t * close;
79     pgp_stream_type_t         type;
80 
81     uint64_t size;  /* size of the data if available, see knownsize */
82     uint64_t readb; /* number of bytes read from the stream via src_read. Do not confuse with
83                        number of bytes as returned via the read since data may be cached */
84     pgp_source_cache_t *cache; /* cache if used */
85     void *              param; /* source-specific additional data */
86 
87     unsigned eof : 1;       /* end of data as reported by read and empty cache */
88     unsigned knownsize : 1; /* whether size of the data is known */
89     unsigned error : 1;     /* there were reading error */
90 } pgp_source_t;
91 
92 /** @brief helper function to allocate memory for source's cache and param
93  *         Also fills src and param with zeroes
94  *  @param src pointer to the source structure
95  *  @param paramsize number of bytes required for src->param
96  *  @return true on success or false if memory allocation failed.
97  **/
98 bool init_src_common(pgp_source_t *src, size_t paramsize);
99 
100 /** @brief read up to len bytes from the source
101  *  While this function tries to read as much bytes as possible however it may return
102  *  less then len bytes. Then src->eof can be checked if it's end of data.
103  *
104  *  @param src source structure
105  *  @param buf preallocated buffer which can store up to len bytes
106  *  @param len number of bytes to read
107  *  @param read number of read bytes will be stored here. Cannot be NULL.
108  *  @return true on success or false otherwise
109  **/
110 bool src_read(pgp_source_t *src, void *buf, size_t len, size_t *read);
111 
112 /** @brief shortcut to read exactly len bytes from source. See src_read for parameters.
113  *  @return true if len bytes were read or false otherwise (i.e. less then len were read or
114  *          read error occurred) */
115 bool src_read_eq(pgp_source_t *src, void *buf, size_t len);
116 
117 /** @brief read up to len bytes and keep them in the cache/do not process
118  *  Works only for streams with cache
119  *  @param src source structure
120  *  @param buf preallocated buffer which can store up to len bytes, or NULL if data should be
121  *             discarded, just making sure that needed input is available in source
122  *  @param len number of bytes to read. Must be less then PGP_INPUT_CACHE_SIZE.
123  *  @param read number of bytes read will be stored here. Cannot be NULL.
124  *  @return true on success or false otherwise
125  **/
126 bool src_peek(pgp_source_t *src, void *buf, size_t len, size_t *read);
127 
128 /** @brief shortcut to read exactly len bytes and keep them in the cache/do not process
129  *         Works only for streams with cache
130  *  @return true if len bytes were read or false otherwise (i.e. less then len were read or
131  *          read error occurred) */
132 bool src_peek_eq(pgp_source_t *src, void *buf, size_t len);
133 
134 /** @brief skip up to len bytes.
135  *         Note: use src_read() if you want to check error condition/get number of bytes
136  *skipped.
137  *  @param src source structure
138  *  @param len number of bytes to skip
139  **/
140 void src_skip(pgp_source_t *src, size_t len);
141 
142 /** @brief notify source that all reading is done, so final data processing may be started,
143  * i.e. signature reading and verification and so on. Do not misuse with src_close.
144  *  @param src allocated and initialized source structure
145  *  @return RNP_SUCCESS or error code. If source doesn't have finish handler then also
146  * RNP_SUCCESS is returned
147  */
148 rnp_result_t src_finish(pgp_source_t *src);
149 
150 /** @brief check whether there were reading error on source
151  *  @param allocated and initialized source structure
152  *  @return true if there were reading error or false otherwise
153  */
154 bool src_error(const pgp_source_t *src);
155 
156 /** @brief check whether there is no more input on source
157  *  @param src allocated and initialized source structure
158  *  @return true if there is no more input or false otherwise.
159  *          On read error false will be returned.
160  */
161 bool src_eof(pgp_source_t *src);
162 
163 /** @brief close the source and deallocate all internal resources if any
164  */
165 void src_close(pgp_source_t *src);
166 
167 /** @brief skip end of line on the source (\r\n or \n, depending on input)
168  *  @param src allocated and initialized source
169  *  @return true if eol was found and skipped or false otherwise
170  */
171 bool src_skip_eol(pgp_source_t *src);
172 
173 /** @brief peek the line on the source
174  *  @param src allocated and initialized source with data
175  *  @param buf preallocated buffer to store the result. Result include NULL character and
176  *             doesn't include the end of line sequence.
177  *  @param len maximum length of data to store in buf, including terminating NULL
178  *  @param read on success here will be stored number of bytes in the string, without the NULL
179  * character.
180  *  @return true on success
181  *          false is returned if there were eof, read error or eol was not found within the
182  * len. Supported eol sequences are \r\n and \n
183  */
184 bool src_peek_line(pgp_source_t *src, char *buf, size_t len, size_t *read);
185 
186 /** @brief init file source
187  *  @param src pre-allocated source structure
188  *  @param path path to the file
189  *  @return RNP_SUCCESS or error code
190  **/
191 rnp_result_t init_file_src(pgp_source_t *src, const char *path);
192 
193 /** @brief init stdin source
194  *  @param src pre-allocated source structure
195  *  @return RNP_SUCCESS or error code
196  **/
197 rnp_result_t init_stdin_src(pgp_source_t *src);
198 
199 /** @brief init memory source
200  *  @param src pre-allocated source structure
201  *  @param mem memory to read from
202  *  @param len number of bytes in input
203  *  @param free free the memory pointer on stream close or not
204  *  @return RNP_SUCCESS or error code
205  **/
206 rnp_result_t init_mem_src(pgp_source_t *src, const void *mem, size_t len, bool free);
207 
208 /** @brief init NULL source, which doesn't allow to read anything and always returns an error.
209  *  @param src pre-allocated source structure
210  *  @return always RNP_SUCCESS
211  **/
212 rnp_result_t init_null_src(pgp_source_t *src);
213 
214 /** @brief init memory source with contents of other source
215  *  @param src pre-allocated source structure
216  *  @param readsrc opened source with data
217  *  @return RNP_SUCCESS or error code
218  **/
219 rnp_result_t read_mem_src(pgp_source_t *src, pgp_source_t *readsrc);
220 
221 /** @brief init memory source with contents of the specified file
222  *  @param src pre-allocated source structure
223  *  @param filename name of the file
224  *  @return RNP_SUCCESS or error code
225  **/
226 rnp_result_t file_to_mem_src(pgp_source_t *src, const char *filename);
227 
228 /** @brief get memory from the memory source
229  *  @param src initialized memory source
230  *  @return pointer to the memory or NULL if it is not a memory source
231  **/
232 const void *mem_src_get_memory(pgp_source_t *src);
233 
234 typedef struct pgp_dest_t {
235     pgp_dest_write_func_t * write;
236     pgp_dest_finish_func_t *finish;
237     pgp_dest_close_func_t * close;
238     pgp_stream_type_t       type;
239     rnp_result_t            werr; /* write function may set this to some error code */
240 
241     size_t   writeb;   /* number of bytes written */
242     void *   param;    /* source-specific additional data */
243     bool     no_cache; /* disable write caching */
244     uint8_t  cache[PGP_OUTPUT_CACHE_SIZE];
245     unsigned clen;     /* number of bytes in cache */
246     bool     finished; /* whether dst_finish was called on dest or not */
247 } pgp_dest_t;
248 
249 /** @brief helper function to allocate memory for dest's param.
250  *         Initializes dst and param with zeroes as well.
251  *  @param dst dest structure
252  *  @param paramsize number of bytes required for dst->param
253  *  @return true on success, or false if memory allocation failed
254  **/
255 bool init_dst_common(pgp_dest_t *dst, size_t paramsize);
256 
257 /** @brief write buffer to the destination
258  *
259  *  @param dst destination structure
260  *  @param buf buffer with data
261  *  @param len number of bytes to write
262  *  @return true on success or false otherwise
263  **/
264 void dst_write(pgp_dest_t *dst, const void *buf, size_t len);
265 
266 /** @brief printf formatted string to the destination
267  *
268  *  @param dst destination structure
269  *  @param format format string, which is the same as printf() uses
270  *  @param ... additional arguments
271  */
272 void dst_printf(pgp_dest_t *dst, const char *format, ...);
273 
274 /** @brief do all finalization tasks after all writing is done, i.e. calculate and write
275  *  mdc, signatures and so on. Do not misuse with dst_close. If was not called then will be
276  *  called from the dst_close
277  *
278  *  @param dst destination structure
279  *  @return RNP_SUCCESS or error code if something went wrong
280  **/
281 rnp_result_t dst_finish(pgp_dest_t *dst);
282 
283 /** @brief close the destination
284  *
285  *  @param dst destination structure to be closed
286  *  @param discard if this is true then all produced output should be discarded
287  *  @return void
288  **/
289 void dst_close(pgp_dest_t *dst, bool discard);
290 
291 /** @brief flush cached data if any. dst_write caches small writes, so data does not
292  *         immediately go to stream write function.
293  *
294  *  @param dst destination structure
295  *  @return void
296  **/
297 void dst_flush(pgp_dest_t *dst);
298 
299 /** @brief init file destination
300  *  @param dst pre-allocated dest structure
301  *  @param path path to the file
302  *  @param overwrite overwrite existing file
303  *  @return RNP_SUCCESS or error code
304  **/
305 rnp_result_t init_file_dest(pgp_dest_t *dst, const char *path, bool overwrite);
306 
307 /** @brief init file destination, using the temporary file name, based on path.
308  *         Once writing is over, dst_finish() will attempt to rename to the desired name.
309  *  @param dst pre-allocated dest structure
310  *  @param path path to the file
311  *  @param overwrite overwrite existing file on rename
312  *  @return RNP_SUCCESS or error code
313  **/
314 rnp_result_t init_tmpfile_dest(pgp_dest_t *dst, const char *path, bool overwrite);
315 
316 /** @brief init stdout destination
317  *  @param dst pre-allocated dest structure
318  *  @return RNP_SUCCESS or error code
319  **/
320 rnp_result_t init_stdout_dest(pgp_dest_t *dst);
321 
322 /** @brief init memory destination
323  *  @param dst pre-allocated dest structure
324  *  @param mem pointer to the pre-allocated memory buffer, or NULL if it should be allocated
325  *  @param len number of bytes which mem can keep, or maximum amount of memory to allocate if
326  *         mem is NULL. If len is zero in later case then allocation is not limited.
327  *  @return RNP_SUCCESS or error code
328  **/
329 rnp_result_t init_mem_dest(pgp_dest_t *dst, void *mem, unsigned len);
330 
331 /** @brief set whether to silently discard bytes which overflow memory of the dst.
332  *  @param dst pre-allocated and initialized memory dest
333  *  @param discard true to discard or false to return an error on overflow.
334  **/
335 void mem_dest_discard_overflow(pgp_dest_t *dst, bool discard);
336 
337 /** @brief get the pointer to the memory where data is written.
338  *  Do not retain the result, it may change between calls due to realloc
339  *  @param dst pre-allocated and initialized memory dest
340  *  @return pointer to the memory area or NULL if memory was not allocated
341  **/
342 void *mem_dest_get_memory(pgp_dest_t *dst);
343 
344 /** @brief get ownership on the memory dest's contents. This must be called only before
345  *         closing the dest
346  *  @param dst pre-allocated and initialized memory dest
347  *  @return pointer to the memory area or NULL if memory was not allocated (i.e. nothing was
348  *          written to the destination). Also NULL will be returned on possible (re-)allocation
349  *          failure, this case can be identified by non-zero dst->writeb.
350  **/
351 void *mem_dest_own_memory(pgp_dest_t *dst);
352 
353 /** @brief init null destination which silently discards all the output
354  *  @param dst pre-allocated dest structure
355  *  @return RNP_SUCCESS or error code
356  **/
357 rnp_result_t init_null_dest(pgp_dest_t *dst);
358 
359 /** @brief reads from source and writes to destination
360  *  @param src initialized source
361  *  @param dst initialized destination
362  *  @param limit sets the maximum amount of bytes to be read,
363  *         returning an error if the source hasn't come to eof after that amount
364  *         if 0, no limit is imposed
365  *  @return RNP_SUCCESS or error code
366  **/
367 rnp_result_t dst_write_src(pgp_source_t *src, pgp_dest_t *dst, uint64_t limit = 0);
368 
369 #endif
370