Annotation of embedaddon/strongswan/src/libstrongswan/utils/chunk.h, revision 1.1.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>