Annotation of embedaddon/strongswan/src/libstrongswan/utils/chunk.h, revision 1.1
1.1 ! misho 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 replacing 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_ @}*/
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>