80b6237ec54e5b58503ebca68444447406a9b9d6
[strongswan.git] / src / libstrongswan / utils / chunk.h
1 /*
2 * Copyright (C) 2008-2013 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 /**
19 * @defgroup chunk chunk
20 * @{ @ingroup utils
21 */
22
23 #ifndef CHUNK_H_
24 #define CHUNK_H_
25
26 #include <string.h>
27 #include <stdarg.h>
28 #include <sys/types.h>
29 #ifdef HAVE_ALLOCA_H
30 #include <alloca.h>
31 #endif
32
33 typedef struct chunk_t chunk_t;
34
35 /**
36 * General purpose pointer/length abstraction.
37 */
38 struct chunk_t {
39 /** Pointer to start of data */
40 u_char *ptr;
41 /** Length of data in bytes */
42 size_t len;
43 };
44
45 #include "utils.h"
46
47 /**
48 * A { NULL, 0 }-chunk handy for initialization.
49 */
50 extern chunk_t chunk_empty;
51
52 /**
53 * Create a new chunk pointing to "ptr" with length "len"
54 */
55 static inline chunk_t chunk_create(u_char *ptr, size_t len)
56 {
57 chunk_t chunk = {ptr, len};
58 return chunk;
59 }
60
61 /**
62 * Create a clone of a chunk pointing to "ptr"
63 */
64 chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk);
65
66 /**
67 * Calculate length of multiple chunks
68 */
69 size_t chunk_length(const char *mode, ...);
70
71 /**
72 * Concatenate chunks into a chunk pointing to "ptr".
73 *
74 * The mode string specifies the number of chunks, and how to handle each of
75 * them with a single character: 'c' for copy (allocate new chunk), 'm' for move
76 * (free given chunk) or 's' for sensitive-move (clear given chunk, then free).
77 */
78 chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...);
79
80 /**
81 * Split up a chunk into parts, "mode" is a string of "a" (alloc),
82 * "c" (copy) and "m" (move). Each letter say for the corresponding chunk if
83 * it should get allocated on heap, copied into existing chunk, or the chunk
84 * should point into "chunk". The length of each part is an argument before
85 * each target chunk. E.g.:
86 * chunk_split(chunk, "mcac", 3, &a, 7, &b, 5, &c, d.len, &d);
87 */
88 void chunk_split(chunk_t chunk, const char *mode, ...);
89
90 /**
91 * Write the binary contents of a chunk_t to a file
92 *
93 * @param chunk contents to write to file
94 * @param path path where file is written to
95 * @param label label specifying file type
96 * @param mask file mode creation mask
97 * @param force overwrite existing file by force
98 * @return TRUE if write operation was successful
99 */
100 bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force);
101
102 /**
103 * Store data read from FD into a chunk
104 *
105 * @param fd file descriptor to read from
106 * @return chunk or chunk_empty on failure
107 */
108 chunk_t chunk_from_fd(int fd);
109
110 /**
111 * Convert a chunk of data to hex encoding.
112 *
113 * The resulting string is '\\0' terminated, but the chunk does not include
114 * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 2 + 1).
115 *
116 * @param chunk data to convert to hex encoding
117 * @param buf buffer to write to, NULL to malloc
118 * @param uppercase TRUE to use uppercase letters
119 * @return chunk of encoded data
120 */
121 chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase);
122
123 /**
124 * Convert a hex encoded in a binary chunk.
125 *
126 * If buf is supplied, it must hold at least (hex.len / 2) + (hex.len % 2)
127 * bytes. It is filled by the right to give correct values for short inputs.
128 *
129 * @param hex hex encoded input data
130 * @param buf buffer to write decoded data, NULL to malloc
131 * @return converted data
132 */
133 chunk_t chunk_from_hex(chunk_t hex, char *buf);
134
135 /**
136 * Convert a chunk of data to its base64 encoding.
137 *
138 * The resulting string is '\\0' terminated, but the chunk does not include
139 * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 4 / 3 + 1).
140 *
141 * @param chunk data to convert
142 * @param buf buffer to write to, NULL to malloc
143 * @return chunk of encoded data
144 */
145 chunk_t chunk_to_base64(chunk_t chunk, char *buf);
146
147 /**
148 * Convert a base64 in a binary chunk.
149 *
150 * If buf is supplied, it must hold at least (base64.len / 4 * 3).
151 *
152 * @param base64 base64 encoded input data
153 * @param buf buffer to write decoded data, NULL to malloc
154 * @return converted data
155 */
156 chunk_t chunk_from_base64(chunk_t base64, char *buf);
157
158 /**
159 * Convert a chunk of data to its base32 encoding.
160 *
161 * The resulting string is '\\0' terminated, but the chunk does not include
162 * the '\\0'. If buf is supplied, it must hold (chunk.len * 8 / 5 + 1) bytes.
163 *
164 * @param chunk data to convert
165 * @param buf buffer to write to, NULL to malloc
166 * @return chunk of encoded data
167 */
168 chunk_t chunk_to_base32(chunk_t chunk, char *buf);
169
170 /**
171 * Free contents of a chunk
172 */
173 static inline void chunk_free(chunk_t *chunk)
174 {
175 free(chunk->ptr);
176 *chunk = chunk_empty;
177 }
178
179 /**
180 * Overwrite the contents of a chunk and free it
181 */
182 static inline void chunk_clear(chunk_t *chunk)
183 {
184 if (chunk->ptr)
185 {
186 memwipe(chunk->ptr, chunk->len);
187 chunk_free(chunk);
188 }
189 }
190
191 /**
192 * Initialize a chunk using a char array
193 */
194 #define chunk_from_chars(...) ((chunk_t){(u_char[]){__VA_ARGS__}, sizeof((u_char[]){__VA_ARGS__})})
195
196 /**
197 * Initialize a chunk to point to a thing
198 */
199 #define chunk_from_thing(thing) chunk_create((u_char*)&(thing), sizeof(thing))
200
201 /**
202 * Initialize a chunk from a string, not containing 0-terminator
203 */
204 #define chunk_from_str(str) ({char *x = (str); chunk_create((u_char*)x, strlen(x));})
205
206 /**
207 * Allocate a chunk on the heap
208 */
209 #define chunk_alloc(bytes) ({size_t x = (bytes); chunk_create(x ? malloc(x) : NULL, x);})
210
211 /**
212 * Allocate a chunk on the stack
213 */
214 #define chunk_alloca(bytes) ({size_t x = (bytes); chunk_create(x ? alloca(x) : NULL, x);})
215
216 /**
217 * Clone a chunk on heap
218 */
219 #define chunk_clone(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? malloc(x.len) : NULL, x);})
220
221 /**
222 * Clone a chunk on stack
223 */
224 #define chunk_clonea(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? alloca(x.len) : NULL, x);})
225
226 /**
227 * Concatenate chunks into a chunk on heap
228 */
229 #define chunk_cat(mode, ...) chunk_create_cat(malloc(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
230
231 /**
232 * Concatenate chunks into a chunk on stack
233 */
234 #define chunk_cata(mode, ...) chunk_create_cat(alloca(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
235
236 /**
237 * Skip n bytes in chunk (forward pointer, shorten length)
238 */
239 static inline chunk_t chunk_skip(chunk_t chunk, size_t bytes)
240 {
241 if (chunk.len > bytes)
242 {
243 chunk.ptr += bytes;
244 chunk.len -= bytes;
245 return chunk;
246 }
247 return chunk_empty;
248 }
249
250 /**
251 * Skip a leading zero-valued byte
252 */
253 static inline chunk_t chunk_skip_zero(chunk_t chunk)
254 {
255 if (chunk.len > 1 && *chunk.ptr == 0x00)
256 {
257 chunk.ptr++;
258 chunk.len--;
259 }
260 return chunk;
261 }
262
263
264 /**
265 * Compare two chunks, returns zero if a equals b
266 * or negative/positive if a is small/greater than b
267 */
268 int chunk_compare(chunk_t a, chunk_t b);
269
270 /**
271 * Compare two chunks for equality,
272 * NULL chunks are never equal.
273 */
274 static inline bool chunk_equals(chunk_t a, chunk_t b)
275 {
276 return a.ptr != NULL && b.ptr != NULL &&
277 a.len == b.len && memeq(a.ptr, b.ptr, a.len);
278 }
279
280 /**
281 * Compare two chunks (given as pointers) for equality (useful as callback),
282 * NULL chunks are never equal.
283 */
284 static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b)
285 {
286 return a != NULL && b != NULL && chunk_equals(*a, *b);
287 }
288
289 /**
290 * Increment a chunk, as it would reprensent a network order integer.
291 *
292 * @param chunk chunk to increment
293 * @return TRUE if an overflow occurred
294 */
295 bool chunk_increment(chunk_t chunk);
296
297 /**
298 * Check if a chunk has printable characters only.
299 *
300 * If sane is given, chunk is cloned into sane and all non printable characters
301 * get replaced by "replace".
302 *
303 * @param chunk chunk to check for printability
304 * @param sane pointer where sane version is allocated, or NULL
305 * @param replace character to use for replaceing unprintable characters
306 * @return TRUE if all characters in chunk are printable
307 */
308 bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace);
309
310 /**
311 * Computes a 32 bit hash of the given chunk.
312 *
313 * @note The output of this function is randomized, that is, it will only
314 * produce the same output for the same input when calling it from the same
315 * process. For a more predictable hash function use chunk_hash_static()
316 * instead.
317 *
318 * @note This hash is only intended for hash tables not for cryptographic
319 * purposes.
320 *
321 * @param chunk data to hash
322 * @return hash value
323 */
324 u_int32_t chunk_hash(chunk_t chunk);
325
326 /**
327 * Incremental version of chunk_hash. Use this to hash two or more chunks.
328 *
329 * @param chunk data to hash
330 * @param hash previous hash value
331 * @return hash value
332 */
333 u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash);
334
335 /**
336 * Computes a 32 bit hash of the given chunk.
337 *
338 * Compared to chunk_hash() this will always calculate the same output for the
339 * same input. Therefore, it should not be used for hash tables (to prevent
340 * hash flooding).
341 *
342 * @note This hash is not intended for cryptographic purposes.
343 *
344 * @param chunk data to hash
345 * @return hash value
346 */
347 u_int32_t chunk_hash_static(chunk_t chunk);
348
349 /**
350 * Incremental version of chunk_hash_static(). Use this to hash two or more
351 * chunks in a predictable way.
352 *
353 * @param chunk data to hash
354 * @param hash previous hash value
355 * @return hash value
356 */
357 u_int32_t chunk_hash_static_inc(chunk_t chunk, u_int32_t hash);
358
359 /**
360 * Computes a quick MAC from the given chunk and key using SipHash.
361 *
362 * The key must have a length of 128-bit (16 bytes).
363 *
364 * @note While SipHash has strong features using it for cryptographic purposes
365 * is not recommended (in particular because of the rather short output size).
366 *
367 * @param chunk data to process
368 * @param key key to use
369 * @return MAC for given input and key
370 */
371 u_int64_t chunk_mac(chunk_t chunk, u_char *key);
372
373 /**
374 * printf hook function for chunk_t.
375 *
376 * Arguments are:
377 * chunk_t *chunk
378 * Use #-modifier to print a compact version
379 * Use +-modifier to print a compact version without separator
380 */
381 int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
382 const void *const *args);
383
384 #endif /** CHUNK_H_ @}*/