diff options
Diffstat (limited to 'src/libstrongswan/utils/chunk.h')
-rw-r--r-- | src/libstrongswan/utils/chunk.h | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h new file mode 100644 index 000000000..67848eec1 --- /dev/null +++ b/src/libstrongswan/utils/chunk.h @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2008-2009 Tobias Brunner + * Copyright (C) 2005-2008 Martin Willi + * Copyright (C) 2005 Jan Hutter + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup chunk chunk + * @{ @ingroup utils + */ + +#ifndef CHUNK_H_ +#define CHUNK_H_ + +#include <string.h> +#include <stdarg.h> +#include <sys/types.h> +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif + +typedef struct chunk_t chunk_t; + +/** + * General purpose pointer/length abstraction. + */ +struct chunk_t { + /** Pointer to start of data */ + u_char *ptr; + /** Length of data in bytes */ + size_t len; +}; + +#include "utils.h" + +/** + * A { NULL, 0 }-chunk handy for initialization. + */ +extern chunk_t chunk_empty; + +/** + * Create a new chunk pointing to "ptr" with length "len" + */ +static inline chunk_t chunk_create(u_char *ptr, size_t len) +{ + chunk_t chunk = {ptr, len}; + return chunk; +} + +/** + * Create a clone of a chunk pointing to "ptr" + */ +chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk); + +/** + * Calculate length of multiple chunks + */ +size_t chunk_length(const char *mode, ...); + +/** + * Concatenate chunks into a chunk pointing to "ptr". + * + * The mode string specifies the number of chunks, and how to handle each of + * them with a single character: 'c' for copy (allocate new chunk), 'm' for move + * (free given chunk) or 's' for sensitive-move (clear given chunk, then free). + */ +chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...); + +/** + * Split up a chunk into parts, "mode" is a string of "a" (alloc), + * "c" (copy) and "m" (move). Each letter say for the corresponding chunk if + * it should get allocated on heap, copied into existing chunk, or the chunk + * should point into "chunk". The length of each part is an argument before + * each target chunk. E.g.: + * chunk_split(chunk, "mcac", 3, &a, 7, &b, 5, &c, d.len, &d); + */ +void chunk_split(chunk_t chunk, const char *mode, ...); + +/** + * Write the binary contents of a chunk_t to a file + * + * @param chunk contents to write to file + * @param path path where file is written to + * @param label label specifying file type + * @param mask file mode creation mask + * @param force overwrite existing file by force + * @return TRUE if write operation was successful + */ +bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force); + +/** + * Convert a chunk of data to hex encoding. + * + * The resulting string is '\\0' terminated, but the chunk does not include + * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 2 + 1). + * + * @param chunk data to convert to hex encoding + * @param buf buffer to write to, NULL to malloc + * @param uppercase TRUE to use uppercase letters + * @return chunk of encoded data + */ +chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase); + +/** + * Convert a hex encoded in a binary chunk. + * + * If buf is supplied, it must hold at least (hex.len / 2) + (hex.len % 2) + * bytes. It is filled by the right to give correct values for short inputs. + * + * @param hex hex encoded input data + * @param buf buffer to write decoded data, NULL to malloc + * @return converted data + */ +chunk_t chunk_from_hex(chunk_t hex, char *buf); + +/** + * Convert a chunk of data to its base64 encoding. + * + * The resulting string is '\\0' terminated, but the chunk does not include + * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 4 / 3 + 1). + * + * @param chunk data to convert + * @param buf buffer to write to, NULL to malloc + * @return chunk of encoded data + */ +chunk_t chunk_to_base64(chunk_t chunk, char *buf); + +/** + * Convert a base64 in a binary chunk. + * + * If buf is supplied, it must hold at least (base64.len / 4 * 3). + * + * @param base64 base64 encoded input data + * @param buf buffer to write decoded data, NULL to malloc + * @return converted data + */ +chunk_t chunk_from_base64(chunk_t base64, char *buf); + +/** + * Convert a chunk of data to its base32 encoding. + * + * The resulting string is '\\0' terminated, but the chunk does not include + * the '\\0'. If buf is supplied, it must hold (chunk.len * 8 / 5 + 1) bytes. + * + * @param chunk data to convert + * @param buf buffer to write to, NULL to malloc + * @return chunk of encoded data + */ +chunk_t chunk_to_base32(chunk_t chunk, char *buf); + +/** + * Free contents of a chunk + */ +static inline void chunk_free(chunk_t *chunk) +{ + free(chunk->ptr); + *chunk = chunk_empty; +} + +/** + * Overwrite the contents of a chunk and free it + */ +static inline void chunk_clear(chunk_t *chunk) +{ + if (chunk->ptr) + { + memwipe(chunk->ptr, chunk->len); + chunk_free(chunk); + } +} + +/** + * Initialize a chunk using a char array + */ +#define chunk_from_chars(...) ((chunk_t){(char[]){__VA_ARGS__}, sizeof((char[]){__VA_ARGS__})}) + +/** + * Initialize a chunk to point to a thing + */ +#define chunk_from_thing(thing) chunk_create((char*)&(thing), sizeof(thing)) + +/** + * Allocate a chunk on the heap + */ +#define chunk_alloc(bytes) ({size_t x = (bytes); chunk_create(x ? malloc(x) : NULL, x);}) + +/** + * Allocate a chunk on the stack + */ +#define chunk_alloca(bytes) ({size_t x = (bytes); chunk_create(x ? alloca(x) : NULL, x);}) + +/** + * Clone a chunk on heap + */ +#define chunk_clone(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? malloc(x.len) : NULL, x);}) + +/** + * Clone a chunk on stack + */ +#define chunk_clonea(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? alloca(x.len) : NULL, x);}) + +/** + * Concatenate chunks into a chunk on heap + */ +#define chunk_cat(mode, ...) chunk_create_cat(malloc(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__) + +/** + * Concatenate chunks into a chunk on stack + */ +#define chunk_cata(mode, ...) chunk_create_cat(alloca(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__) + +/** + * Skip n bytes in chunk (forward pointer, shorten length) + */ +static inline chunk_t chunk_skip(chunk_t chunk, size_t bytes) +{ + if (chunk.len > bytes) + { + chunk.ptr += bytes; + chunk.len -= bytes; + return chunk; + } + return chunk_empty; +} + +/** + * Skip a leading zero-valued byte + */ +static inline chunk_t chunk_skip_zero(chunk_t chunk) +{ + if (chunk.len > 1 && *chunk.ptr == 0x00) + { + chunk.ptr++; + chunk.len--; + } + return chunk; +} + + +/** + * Compare two chunks, returns zero if a equals b + * or negative/positive if a is small/greater than b + */ +int chunk_compare(chunk_t a, chunk_t b); + +/** + * Compare two chunks for equality, + * NULL chunks are never equal. + */ +static inline bool chunk_equals(chunk_t a, chunk_t b) +{ + return a.ptr != NULL && b.ptr != NULL && + a.len == b.len && memeq(a.ptr, b.ptr, a.len); +} + +/** + * Compare two chunks (given as pointers) for equality (useful as callback), + * NULL chunks are never equal. + */ +static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b) +{ + return a != NULL && b != NULL && chunk_equals(*a, *b); +} + +/** + * Increment a chunk, as it would reprensent a network order integer. + * + * @param chunk chunk to increment + * @return TRUE if an overflow occurred + */ +bool chunk_increment(chunk_t chunk); + +/** + * Check if a chunk has printable characters only. + * + * If sane is given, chunk is cloned into sane and all non printable characters + * get replaced by "replace". + * + * @param chunk chunk to check for printability + * @param sane pointer where sane version is allocated, or NULL + * @param replace character to use for replaceing unprintable characters + * @return TRUE if all characters in chunk are printable + */ +bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace); + +/** + * Computes a 32 bit hash of the given chunk. + * Note: This hash is only intended for hash tables not for cryptographic purposes. + */ +u_int32_t chunk_hash(chunk_t chunk); + +/** + * Incremental version of chunk_hash. Use this to hash two or more chunks. + */ +u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash); + +/** + * printf hook function for chunk_t. + * + * Arguments are: + * chunk_t *chunk + * Use #-modifier to print a compact version + */ +int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, + const void *const *args); + +#endif /** CHUNK_H_ @}*/ |