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>