chunk: Add helper to copy a chunk left-padded to a certain length
[strongswan.git] / src / libstrongswan / utils / chunk.h
1 /*
2 * Copyright (C) 2008-2019 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * HSR 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 #include <utils/utils.h>
34
35 typedef struct chunk_t chunk_t;
36
37 /**
38 * General purpose pointer/length abstraction.
39 */
40 struct chunk_t {
41 /** Pointer to start of data */
42 u_char *ptr;
43 /** Length of data in bytes */
44 size_t len;
45 };
46
47 #include "utils.h"
48
49 /**
50 * A { NULL, 0 }-chunk handy for initialization.
51 */
52 extern chunk_t chunk_empty;
53
54 /**
55 * Create a new chunk pointing to "ptr" with length "len"
56 */
57 static inline chunk_t chunk_create(u_char *ptr, size_t len)
58 {
59 chunk_t chunk = {ptr, len};
60 return chunk;
61 }
62
63 /**
64 * Create a clone of a chunk pointing to "ptr"
65 */
66 chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk);
67
68 /**
69 * Calculate length of multiple chunks
70 */
71 size_t chunk_length(const char *mode, ...);
72
73 /**
74 * Concatenate chunks into a chunk pointing to "ptr".
75 *
76 * The mode string specifies the number of chunks, and how to handle each of
77 * them with a single character: 'c' for copy (allocate new chunk), 'm' for move
78 * (free given chunk) or 's' for sensitive-move (clear given chunk, then free).
79 */
80 chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...);
81
82 /**
83 * Split up a chunk into parts, "mode" is a string of "a" (alloc),
84 * "c" (copy) and "m" (move). Each letter say for the corresponding chunk if
85 * it should get allocated on heap, copied into existing chunk, or the chunk
86 * should point into "chunk". The length of each part is an argument before
87 * each target chunk. E.g.:
88 * chunk_split(chunk, "mcac", 3, &a, 7, &b, 5, &c, d.len, &d);
89 */
90 void chunk_split(chunk_t chunk, const char *mode, ...);
91
92 /**
93 * Write the binary contents of a chunk_t to a file
94 *
95 * If the write fails, errno is set appropriately.
96 *
97 * @param chunk contents to write to file
98 * @param path path where file is written to
99 * @param mask file mode creation mask
100 * @param force overwrite existing file by force
101 * @return TRUE if write operation was successful
102 */
103 bool chunk_write(chunk_t chunk, char *path, mode_t mask, bool force);
104
105 /**
106 * Store data read from FD into a chunk
107 *
108 * On error, errno is set appropriately.
109 *
110 * @param fd file descriptor to read from
111 * @param chunk chunk receiving allocated buffer
112 * @return TRUE if successful, FALSE on failure
113 */
114 bool chunk_from_fd(int fd, chunk_t *chunk);
115
116 /**
117 * mmap() a file to a chunk
118 *
119 * The returned chunk structure is allocated from heap, but it must be freed
120 * through chunk_unmap(). A user may alter the chunk ptr or len, but must pass
121 * the chunk pointer returned from chunk_map() to chunk_unmap() after use.
122 *
123 * On error, errno is set appropriately.
124 *
125 * @param path path of file to map
126 * @param wr TRUE to sync writes to disk
127 * @return mapped chunk, NULL on error
128 */
129 chunk_t *chunk_map(char *path, bool wr);
130
131 /**
132 * munmap() a chunk previously mapped with chunk_map()
133 *
134 * When unmapping a writeable map, the return value should be checked to
135 * ensure changes landed on disk.
136 *
137 * @param chunk pointer returned from chunk_map()
138 * @return TRUE of changes written back to file
139 */
140 bool chunk_unmap(chunk_t *chunk);
141
142 /**
143 * Convert a chunk of data to hex encoding.
144 *
145 * The resulting string is '\\0' terminated, but the chunk does not include
146 * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 2 + 1).
147 *
148 * @param chunk data to convert to hex encoding
149 * @param buf buffer to write to, NULL to malloc
150 * @param uppercase TRUE to use uppercase letters
151 * @return chunk of encoded data
152 */
153 chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase);
154
155 /**
156 * Convert a hex encoded in a binary chunk.
157 *
158 * If buf is supplied, it must hold at least (hex.len / 2) + (hex.len % 2)
159 * bytes. It is filled by the right to give correct values for short inputs.
160 *
161 * @param hex hex encoded input data
162 * @param buf buffer to write decoded data, NULL to malloc
163 * @return converted data
164 */
165 chunk_t chunk_from_hex(chunk_t hex, char *buf);
166
167 /**
168 * Convert a chunk of data to its base64 encoding.
169 *
170 * The resulting string is '\\0' terminated, but the chunk does not include
171 * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 4 / 3 + 1).
172 *
173 * @param chunk data to convert
174 * @param buf buffer to write to, NULL to malloc
175 * @return chunk of encoded data
176 */
177 chunk_t chunk_to_base64(chunk_t chunk, char *buf);
178
179 /**
180 * Convert a base64 in a binary chunk.
181 *
182 * If buf is supplied, it must hold at least (base64.len / 4 * 3).
183 *
184 * @param base64 base64 encoded input data
185 * @param buf buffer to write decoded data, NULL to malloc
186 * @return converted data
187 */
188 chunk_t chunk_from_base64(chunk_t base64, char *buf);
189
190 /**
191 * Convert a chunk of data to its base32 encoding.
192 *
193 * The resulting string is '\\0' terminated, but the chunk does not include
194 * the '\\0'. If buf is supplied, it must hold (chunk.len * 8 / 5 + 1) bytes.
195 *
196 * @param chunk data to convert
197 * @param buf buffer to write to, NULL to malloc
198 * @return chunk of encoded data
199 */
200 chunk_t chunk_to_base32(chunk_t chunk, char *buf);
201
202 /**
203 * Free contents of a chunk
204 */
205 static inline void chunk_free(chunk_t *chunk)
206 {
207 free(chunk->ptr);
208 *chunk = chunk_empty;
209 }
210
211 /**
212 * Overwrite the contents of a chunk and free it
213 */
214 static inline void chunk_clear(chunk_t *chunk)
215 {
216 if (chunk->ptr)
217 {
218 memwipe(chunk->ptr, chunk->len);
219 chunk_free(chunk);
220 }
221 }
222
223 /**
224 * Initialize a chunk using a char array
225 */
226 #define chunk_from_chars(...) ((chunk_t){(u_char[]){__VA_ARGS__}, sizeof((u_char[]){__VA_ARGS__})})
227
228 /**
229 * Initialize a chunk to point to a thing
230 */
231 #define chunk_from_thing(thing) chunk_create((u_char*)&(thing), sizeof(thing))
232
233 /**
234 * Initialize a chunk from a string, not containing 0-terminator
235 */
236 #define chunk_from_str(str) ({char *x = (str); chunk_create((u_char*)x, strlen(x));})
237
238 /**
239 * Allocate a chunk on the heap
240 */
241 #define chunk_alloc(bytes) ({size_t x = (bytes); chunk_create(x ? malloc(x) : NULL, x);})
242
243 /**
244 * Allocate a chunk on the stack
245 */
246 #define chunk_alloca(bytes) ({size_t x = (bytes); chunk_create(x ? alloca(x) : NULL, x);})
247
248 /**
249 * Clone a chunk on heap
250 */
251 #define chunk_clone(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? malloc(x.len) : NULL, x);})
252
253 /**
254 * Clone a chunk on stack
255 */
256 #define chunk_clonea(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? alloca(x.len) : NULL, x);})
257
258 /**
259 * Concatenate chunks into a chunk on heap
260 */
261 #define chunk_cat(mode, ...) chunk_create_cat(malloc(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
262
263 /**
264 * Concatenate chunks into a chunk on stack
265 */
266 #define chunk_cata(mode, ...) chunk_create_cat(alloca(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
267
268 /**
269 * Skip n bytes in chunk (forward pointer, shorten length)
270 */
271 static inline chunk_t chunk_skip(chunk_t chunk, size_t bytes)
272 {
273 if (chunk.len > bytes)
274 {
275 chunk.ptr += bytes;
276 chunk.len -= bytes;
277 return chunk;
278 }
279 return chunk_empty;
280 }
281
282 /**
283 * Skip any leading zero-valued bytes
284 */
285 static inline chunk_t chunk_skip_zero(chunk_t chunk)
286 {
287 while (chunk.len > 1 && *chunk.ptr == 0x00)
288 {
289 chunk.ptr++;
290 chunk.len--;
291 }
292 return chunk;
293 }
294
295 /**
296 * Copy the data from src to dst, left-padded with chr if dst is longer,
297 * otherwise data is copied truncated on the left.
298 *
299 * @param dst data is copied here
300 * @param src data is copied from here
301 * @param chr value to use for padding if necessary
302 * @return the destination chunk
303 */
304 chunk_t chunk_copy_pad(chunk_t dst, chunk_t src, u_char chr);
305
306 /**
307 * Compare two chunks, returns zero if a equals b
308 * or negative/positive if a is small/greater than b
309 */
310 int chunk_compare(chunk_t a, chunk_t b);
311
312 /**
313 * Compare two chunks for equality,
314 * NULL chunks are never equal.
315 */
316 static inline bool chunk_equals(chunk_t a, chunk_t b)
317 {
318 return a.ptr != NULL && b.ptr != NULL &&
319 a.len == b.len && memeq(a.ptr, b.ptr, a.len);
320 }
321
322 /**
323 * Compare two chunks for equality, constant time for cryptographic purposes.
324 *
325 * Note that this function is constant time only for chunks with the same
326 * length, i.e. it does not protect against guessing the length of one of the
327 * chunks.
328 */
329 static inline bool chunk_equals_const(chunk_t a, chunk_t b)
330 {
331 return a.ptr != NULL && b.ptr != NULL &&
332 a.len == b.len && memeq_const(a.ptr, b.ptr, a.len);
333 }
334
335 /**
336 * Compare two chunks (given as pointers) for equality (useful as callback),
337 * NULL chunks are never equal.
338 */
339 static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b)
340 {
341 return a != NULL && b != NULL && chunk_equals(*a, *b);
342 }
343
344 /**
345 * Increment a chunk, as it would represent a network order integer.
346 *
347 * @param chunk chunk to increment
348 * @return TRUE if an overflow occurred
349 */
350 bool chunk_increment(chunk_t chunk);
351
352 /**
353 * Check if a chunk has printable characters only.
354 *
355 * If sane is given, chunk is cloned into sane and all non printable characters
356 * get replaced by "replace".
357 *
358 * @param chunk chunk to check for printability
359 * @param sane pointer where sane version is allocated, or NULL
360 * @param replace character to use for replaceing unprintable characters
361 * @return TRUE if all characters in chunk are printable
362 */
363 bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace);
364
365 /**
366 * Seed initial key for chunk_hash().
367 *
368 * This call should get invoked once during startup. This is usually done
369 * by calling library_init(). Calling it multiple times is safe, it gets
370 * executed just once.
371 */
372 void chunk_hash_seed();
373
374 /**
375 * Computes a 32 bit hash of the given chunk.
376 *
377 * @note The output of this function is randomized, that is, it will only
378 * produce the same output for the same input when calling it from the same
379 * process. For a more predictable hash function use chunk_hash_static()
380 * instead.
381 *
382 * @note This hash is only intended for hash tables not for cryptographic
383 * purposes.
384 *
385 * @param chunk data to hash
386 * @return hash value
387 */
388 uint32_t chunk_hash(chunk_t chunk);
389
390 /**
391 * Incremental version of chunk_hash. Use this to hash two or more chunks.
392 *
393 * @param chunk data to hash
394 * @param hash previous hash value
395 * @return hash value
396 */
397 uint32_t chunk_hash_inc(chunk_t chunk, uint32_t hash);
398
399 /**
400 * Computes a 32 bit hash of the given chunk.
401 *
402 * Compared to chunk_hash() this will always calculate the same output for the
403 * same input. Therefore, it should not be used for hash tables (to prevent
404 * hash flooding).
405 *
406 * @note This hash is not intended for cryptographic purposes.
407 *
408 * @param chunk data to hash
409 * @return hash value
410 */
411 uint32_t chunk_hash_static(chunk_t chunk);
412
413 /**
414 * Incremental version of chunk_hash_static(). Use this to hash two or more
415 * chunks in a predictable way.
416 *
417 * @param chunk data to hash
418 * @param hash previous hash value
419 * @return hash value
420 */
421 uint32_t chunk_hash_static_inc(chunk_t chunk, uint32_t hash);
422
423 /**
424 * Computes a quick MAC from the given chunk and key using SipHash.
425 *
426 * The key must have a length of 128-bit (16 bytes).
427 *
428 * @note While SipHash has strong features using it for cryptographic purposes
429 * is not recommended (in particular because of the rather short output size).
430 *
431 * @param chunk data to process
432 * @param key key to use
433 * @return MAC for given input and key
434 */
435 uint64_t chunk_mac(chunk_t chunk, u_char *key);
436
437 /**
438 * Calculate the Internet Checksum according to RFC 1071 for the given chunk.
439 *
440 * If the result is used with chunk_internet_checksum_inc() and the data length
441 * is not a multiple of 16 bit the checksum bytes have to be swapped to
442 * compensate the even/odd alignment.
443 *
444 * @param data data to process
445 * @return checksum (one's complement, network order)
446 */
447 uint16_t chunk_internet_checksum(chunk_t data);
448
449 /**
450 * Extend the given Internet Checksum (one's complement, in network byte order)
451 * with the given data.
452 *
453 * If data is not a multiple of 16 bits the checksum may have to be swapped to
454 * compensate even/odd alignment (see chunk_internet_checksum()).
455 *
456 * @param data data to process
457 * @param checksum previous checksum (one's complement, network order)
458 * @return checksum (one's complement, network order)
459 */
460 uint16_t chunk_internet_checksum_inc(chunk_t data, uint16_t checksum);
461
462 /**
463 * printf hook function for chunk_t.
464 *
465 * Arguments are:
466 * chunk_t *chunk
467 * Use #-modifier to print a compact version
468 * Use +-modifier to print a compact version without separator
469 */
470 int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
471 const void *const *args);
472
473 #endif /** CHUNK_H_ @}*/