chunk.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  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. * @defgroup chunk chunk
  19. * @{ @ingroup utils
  20. */
  21. #ifndef CHUNK_H_
  22. #define CHUNK_H_
  23. #include <string.h>
  24. #include <stdarg.h>
  25. #include <sys/types.h>
  26. #ifdef HAVE_ALLOCA_H
  27. #include <alloca.h>
  28. #endif
  29. #include <utils/utils.h>
  30. typedef struct chunk_t chunk_t;
  31. /**
  32. * General purpose pointer/length abstraction.
  33. */
  34. struct chunk_t {
  35. /** Pointer to start of data */
  36. u_char *ptr;
  37. /** Length of data in bytes */
  38. size_t len;
  39. };
  40. #include "utils.h"
  41. /**
  42. * A { NULL, 0 }-chunk handy for initialization.
  43. */
  44. extern chunk_t chunk_empty;
  45. /**
  46. * Create a new chunk pointing to "ptr" with length "len"
  47. */
  48. static inline chunk_t chunk_create(u_char *ptr, size_t len)
  49. {
  50. chunk_t chunk = {ptr, len};
  51. return chunk;
  52. }
  53. /**
  54. * Create a clone of a chunk pointing to "ptr"
  55. */
  56. chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk);
  57. /**
  58. * Calculate length of multiple chunks
  59. */
  60. size_t chunk_length(const char *mode, ...);
  61. /**
  62. * Concatenate chunks into a chunk pointing to "ptr".
  63. *
  64. * The mode string specifies the number of chunks, and how to handle each of
  65. * them with a single character: 'c' for copy (allocate new chunk), 'm' for move
  66. * (free given chunk) or 's' for sensitive-move (clear given chunk, then free).
  67. */
  68. chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...);
  69. /**
  70. * Split up a chunk into parts, "mode" is a string of "a" (alloc),
  71. * "c" (copy) and "m" (move). Each letter say for the corresponding chunk if
  72. * it should get allocated on heap, copied into existing chunk, or the chunk
  73. * should point into "chunk". The length of each part is an argument before
  74. * each target chunk. E.g.:
  75. * chunk_split(chunk, "mcac", 3, &a, 7, &b, 5, &c, d.len, &d);
  76. */
  77. void chunk_split(chunk_t chunk, const char *mode, ...);
  78. /**
  79. * Write the binary contents of a chunk_t to a file
  80. *
  81. * If the write fails, errno is set appropriately.
  82. *
  83. * @param chunk contents to write to file
  84. * @param path path where file is written to
  85. * @param mask file mode creation mask
  86. * @param force overwrite existing file by force
  87. * @return TRUE if write operation was successful
  88. */
  89. bool chunk_write(chunk_t chunk, char *path, mode_t mask, bool force);
  90. /**
  91. * Store data read from FD into a chunk
  92. *
  93. * On error, errno is set appropriately.
  94. *
  95. * @param fd file descriptor to read from
  96. * @param chunk chunk receiving allocated buffer
  97. * @return TRUE if successful, FALSE on failure
  98. */
  99. bool chunk_from_fd(int fd, chunk_t *chunk);
  100. /**
  101. * mmap() a file to a chunk
  102. *
  103. * The returned chunk structure is allocated from heap, but it must be freed
  104. * through chunk_unmap(). A user may alter the chunk ptr or len, but must pass
  105. * the chunk pointer returned from chunk_map() to chunk_unmap() after use.
  106. *
  107. * On error, errno is set appropriately.
  108. *
  109. * @param path path of file to map
  110. * @param wr TRUE to sync writes to disk
  111. * @return mapped chunk, NULL on error
  112. */
  113. chunk_t *chunk_map(char *path, bool wr);
  114. /**
  115. * munmap() a chunk previously mapped with chunk_map()
  116. *
  117. * When unmapping a writeable map, the return value should be checked to
  118. * ensure changes landed on disk.
  119. *
  120. * @param chunk pointer returned from chunk_map()
  121. * @return TRUE of changes written back to file
  122. */
  123. bool chunk_unmap(chunk_t *chunk);
  124. /**
  125. * Convert a chunk of data to hex encoding.
  126. *
  127. * The resulting string is '\\0' terminated, but the chunk does not include
  128. * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 2 + 1).
  129. *
  130. * @param chunk data to convert to hex encoding
  131. * @param buf buffer to write to, NULL to malloc
  132. * @param uppercase TRUE to use uppercase letters
  133. * @return chunk of encoded data
  134. */
  135. chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase);
  136. /**
  137. * Convert a hex encoded in a binary chunk.
  138. *
  139. * If buf is supplied, it must hold at least (hex.len / 2) + (hex.len % 2)
  140. * bytes. It is filled by the right to give correct values for short inputs.
  141. *
  142. * @param hex hex encoded input data
  143. * @param buf buffer to write decoded data, NULL to malloc
  144. * @return converted data
  145. */
  146. chunk_t chunk_from_hex(chunk_t hex, char *buf);
  147. /**
  148. * Convert a chunk of data to its base64 encoding.
  149. *
  150. * The resulting string is '\\0' terminated, but the chunk does not include
  151. * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 4 / 3 + 1).
  152. *
  153. * @param chunk data to convert
  154. * @param buf buffer to write to, NULL to malloc
  155. * @return chunk of encoded data
  156. */
  157. chunk_t chunk_to_base64(chunk_t chunk, char *buf);
  158. /**
  159. * Convert a base64 in a binary chunk.
  160. *
  161. * If buf is supplied, it must hold at least (base64.len / 4 * 3).
  162. *
  163. * @param base64 base64 encoded input data
  164. * @param buf buffer to write decoded data, NULL to malloc
  165. * @return converted data
  166. */
  167. chunk_t chunk_from_base64(chunk_t base64, char *buf);
  168. /**
  169. * Convert a chunk of data to its base32 encoding.
  170. *
  171. * The resulting string is '\\0' terminated, but the chunk does not include
  172. * the '\\0'. If buf is supplied, it must hold (chunk.len * 8 / 5 + 1) bytes.
  173. *
  174. * @param chunk data to convert
  175. * @param buf buffer to write to, NULL to malloc
  176. * @return chunk of encoded data
  177. */
  178. chunk_t chunk_to_base32(chunk_t chunk, char *buf);
  179. /**
  180. * Free contents of a chunk
  181. */
  182. static inline void chunk_free(chunk_t *chunk)
  183. {
  184. free(chunk->ptr);
  185. *chunk = chunk_empty;
  186. }
  187. /**
  188. * Overwrite the contents of a chunk and free it
  189. */
  190. static inline void chunk_clear(chunk_t *chunk)
  191. {
  192. if (chunk->ptr)
  193. {
  194. memwipe(chunk->ptr, chunk->len);
  195. chunk_free(chunk);
  196. }
  197. }
  198. /**
  199. * Initialize a chunk using a char array
  200. */
  201. #define chunk_from_chars(...) ((chunk_t){(u_char[]){__VA_ARGS__}, sizeof((u_char[]){__VA_ARGS__})})
  202. /**
  203. * Initialize a chunk to point to a thing
  204. */
  205. #define chunk_from_thing(thing) chunk_create((u_char*)&(thing), sizeof(thing))
  206. /**
  207. * Initialize a chunk from a string, not containing 0-terminator
  208. */
  209. #define chunk_from_str(str) ({char *x = (str); chunk_create((u_char*)x, strlen(x));})
  210. /**
  211. * Allocate a chunk on the heap
  212. */
  213. #define chunk_alloc(bytes) ({size_t x = (bytes); chunk_create(x ? malloc(x) : NULL, x);})
  214. /**
  215. * Allocate a chunk on the stack
  216. */
  217. #define chunk_alloca(bytes) ({size_t x = (bytes); chunk_create(x ? alloca(x) : NULL, x);})
  218. /**
  219. * Clone a chunk on heap
  220. */
  221. #define chunk_clone(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? malloc(x.len) : NULL, x);})
  222. /**
  223. * Clone a chunk on stack
  224. */
  225. #define chunk_clonea(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? alloca(x.len) : NULL, x);})
  226. /**
  227. * Concatenate chunks into a chunk on heap
  228. */
  229. #define chunk_cat(mode, ...) chunk_create_cat(malloc(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
  230. /**
  231. * Concatenate chunks into a chunk on stack
  232. */
  233. #define chunk_cata(mode, ...) chunk_create_cat(alloca(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
  234. /**
  235. * Skip n bytes in chunk (forward pointer, shorten length)
  236. */
  237. static inline chunk_t chunk_skip(chunk_t chunk, size_t bytes)
  238. {
  239. if (chunk.len > bytes)
  240. {
  241. chunk.ptr += bytes;
  242. chunk.len -= bytes;
  243. return chunk;
  244. }
  245. return chunk_empty;
  246. }
  247. /**
  248. * Skip any leading zero-valued bytes
  249. */
  250. static inline chunk_t chunk_skip_zero(chunk_t chunk)
  251. {
  252. while (chunk.len > 1 && *chunk.ptr == 0x00)
  253. {
  254. chunk.ptr++;
  255. chunk.len--;
  256. }
  257. return chunk;
  258. }
  259. /**
  260. * Copy the data from src to dst, left-padded with chr if dst is longer,
  261. * otherwise data is copied truncated on the left.
  262. *
  263. * @param dst data is copied here
  264. * @param src data is copied from here
  265. * @param chr value to use for padding if necessary
  266. * @return the destination chunk
  267. */
  268. chunk_t chunk_copy_pad(chunk_t dst, chunk_t src, u_char chr);
  269. /**
  270. * Compare two chunks, returns zero if a equals b
  271. * or negative/positive if a is small/greater than b
  272. */
  273. int chunk_compare(chunk_t a, chunk_t b);
  274. /**
  275. * Compare two chunks for equality,
  276. * NULL chunks are never equal.
  277. */
  278. static inline bool chunk_equals(chunk_t a, chunk_t b)
  279. {
  280. return a.ptr != NULL && b.ptr != NULL &&
  281. a.len == b.len && memeq(a.ptr, b.ptr, a.len);
  282. }
  283. /**
  284. * Compare two chunks for equality, constant time for cryptographic purposes.
  285. *
  286. * Note that this function is constant time only for chunks with the same
  287. * length, i.e. it does not protect against guessing the length of one of the
  288. * chunks.
  289. */
  290. static inline bool chunk_equals_const(chunk_t a, chunk_t b)
  291. {
  292. return a.ptr != NULL && b.ptr != NULL &&
  293. a.len == b.len && memeq_const(a.ptr, b.ptr, a.len);
  294. }
  295. /**
  296. * Compare two chunks (given as pointers) for equality (useful as callback),
  297. * NULL chunks are never equal.
  298. */
  299. static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b)
  300. {
  301. return a != NULL && b != NULL && chunk_equals(*a, *b);
  302. }
  303. /**
  304. * Increment a chunk, as it would represent a network order integer.
  305. *
  306. * @param chunk chunk to increment
  307. * @return TRUE if an overflow occurred
  308. */
  309. bool chunk_increment(chunk_t chunk);
  310. /**
  311. * Check if a chunk has printable characters only.
  312. *
  313. * If sane is given, chunk is cloned into sane and all non printable characters
  314. * get replaced by "replace".
  315. *
  316. * @param chunk chunk to check for printability
  317. * @param sane pointer where sane version is allocated, or NULL
  318. * @param replace character to use for replaceing unprintable characters
  319. * @return TRUE if all characters in chunk are printable
  320. */
  321. bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace);
  322. /**
  323. * Seed initial key for chunk_hash().
  324. *
  325. * This call should get invoked once during startup. This is usually done
  326. * by calling library_init(). Calling it multiple times is safe, it gets
  327. * executed just once.
  328. */
  329. void chunk_hash_seed();
  330. /**
  331. * Computes a 32 bit hash of the given chunk.
  332. *
  333. * @note The output of this function is randomized, that is, it will only
  334. * produce the same output for the same input when calling it from the same
  335. * process. For a more predictable hash function use chunk_hash_static()
  336. * instead.
  337. *
  338. * @note This hash is only intended for hash tables not for cryptographic
  339. * purposes.
  340. *
  341. * @param chunk data to hash
  342. * @return hash value
  343. */
  344. uint32_t chunk_hash(chunk_t chunk);
  345. /**
  346. * Incremental version of chunk_hash. Use this to hash two or more chunks.
  347. *
  348. * @param chunk data to hash
  349. * @param hash previous hash value
  350. * @return hash value
  351. */
  352. uint32_t chunk_hash_inc(chunk_t chunk, uint32_t hash);
  353. /**
  354. * Computes a 32 bit hash of the given chunk.
  355. *
  356. * Compared to chunk_hash() this will always calculate the same output for the
  357. * same input. Therefore, it should not be used for hash tables (to prevent
  358. * hash flooding).
  359. *
  360. * @note This hash is not intended for cryptographic purposes.
  361. *
  362. * @param chunk data to hash
  363. * @return hash value
  364. */
  365. uint32_t chunk_hash_static(chunk_t chunk);
  366. /**
  367. * Incremental version of chunk_hash_static(). Use this to hash two or more
  368. * chunks in a predictable way.
  369. *
  370. * @param chunk data to hash
  371. * @param hash previous hash value
  372. * @return hash value
  373. */
  374. uint32_t chunk_hash_static_inc(chunk_t chunk, uint32_t hash);
  375. /**
  376. * Computes a quick MAC from the given chunk and key using SipHash.
  377. *
  378. * The key must have a length of 128-bit (16 bytes).
  379. *
  380. * @note While SipHash has strong features using it for cryptographic purposes
  381. * is not recommended (in particular because of the rather short output size).
  382. *
  383. * @param chunk data to process
  384. * @param key key to use
  385. * @return MAC for given input and key
  386. */
  387. uint64_t chunk_mac(chunk_t chunk, u_char *key);
  388. /**
  389. * Calculate the Internet Checksum according to RFC 1071 for the given chunk.
  390. *
  391. * If the result is used with chunk_internet_checksum_inc() and the data length
  392. * is not a multiple of 16 bit the checksum bytes have to be swapped to
  393. * compensate the even/odd alignment.
  394. *
  395. * @param data data to process
  396. * @return checksum (one's complement, network order)
  397. */
  398. uint16_t chunk_internet_checksum(chunk_t data);
  399. /**
  400. * Extend the given Internet Checksum (one's complement, in network byte order)
  401. * with the given data.
  402. *
  403. * If data is not a multiple of 16 bits the checksum may have to be swapped to
  404. * compensate even/odd alignment (see chunk_internet_checksum()).
  405. *
  406. * @param data data to process
  407. * @param checksum previous checksum (one's complement, network order)
  408. * @return checksum (one's complement, network order)
  409. */
  410. uint16_t chunk_internet_checksum_inc(chunk_t data, uint16_t checksum);
  411. /**
  412. * printf hook function for chunk_t.
  413. *
  414. * Arguments are:
  415. * chunk_t *chunk
  416. * Use #-modifier to print a compact version
  417. * Use +-modifier to print a compact version without separator
  418. */
  419. int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
  420. const void *const *args);
  421. #endif /** CHUNK_H_ @}*/