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>