sendme_cell.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. /* sendme_cell.c -- generated by Trunnel v1.5.3.
  2. * https://gitweb.torproject.org/trunnel.git
  3. * You probably shouldn't edit this file.
  4. */
  5. #include <stdlib.h>
  6. #include "trunnel-impl.h"
  7. #include "sendme_cell.h"
  8. #define TRUNNEL_SET_ERROR_CODE(obj) \
  9. do { \
  10. (obj)->trunnel_error_code_ = 1; \
  11. } while (0)
  12. #if defined(__COVERITY__) || defined(__clang_analyzer__)
  13. /* If we're running a static analysis tool, we don't want it to complain
  14. * that some of our remaining-bytes checks are dead-code. */
  15. int sendmecell_deadcode_dummy__ = 0;
  16. #define OR_DEADCODE_DUMMY || sendmecell_deadcode_dummy__
  17. #else
  18. #define OR_DEADCODE_DUMMY
  19. #endif
  20. #define CHECK_REMAINING(nbytes, label) \
  21. do { \
  22. if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
  23. goto label; \
  24. } \
  25. } while (0)
  26. sendme_cell_t *
  27. sendme_cell_new(void)
  28. {
  29. sendme_cell_t *val = trunnel_calloc(1, sizeof(sendme_cell_t));
  30. if (NULL == val)
  31. return NULL;
  32. return val;
  33. }
  34. /** Release all storage held inside 'obj', but do not free 'obj'.
  35. */
  36. static void
  37. sendme_cell_clear(sendme_cell_t *obj)
  38. {
  39. (void) obj;
  40. }
  41. void
  42. sendme_cell_free(sendme_cell_t *obj)
  43. {
  44. if (obj == NULL)
  45. return;
  46. sendme_cell_clear(obj);
  47. trunnel_memwipe(obj, sizeof(sendme_cell_t));
  48. trunnel_free_(obj);
  49. }
  50. uint8_t
  51. sendme_cell_get_version(const sendme_cell_t *inp)
  52. {
  53. return inp->version;
  54. }
  55. int
  56. sendme_cell_set_version(sendme_cell_t *inp, uint8_t val)
  57. {
  58. if (! ((val == 0 || val == 1))) {
  59. TRUNNEL_SET_ERROR_CODE(inp);
  60. return -1;
  61. }
  62. inp->version = val;
  63. return 0;
  64. }
  65. uint16_t
  66. sendme_cell_get_data_len(const sendme_cell_t *inp)
  67. {
  68. return inp->data_len;
  69. }
  70. int
  71. sendme_cell_set_data_len(sendme_cell_t *inp, uint16_t val)
  72. {
  73. inp->data_len = val;
  74. return 0;
  75. }
  76. size_t
  77. sendme_cell_getlen_data_v1_digest(const sendme_cell_t *inp)
  78. {
  79. (void)inp; return TRUNNEL_SENDME_V1_DIGEST_LEN;
  80. }
  81. uint8_t
  82. sendme_cell_get_data_v1_digest(sendme_cell_t *inp, size_t idx)
  83. {
  84. trunnel_assert(idx < TRUNNEL_SENDME_V1_DIGEST_LEN);
  85. return inp->data_v1_digest[idx];
  86. }
  87. uint8_t
  88. sendme_cell_getconst_data_v1_digest(const sendme_cell_t *inp, size_t idx)
  89. {
  90. return sendme_cell_get_data_v1_digest((sendme_cell_t*)inp, idx);
  91. }
  92. int
  93. sendme_cell_set_data_v1_digest(sendme_cell_t *inp, size_t idx, uint8_t elt)
  94. {
  95. trunnel_assert(idx < TRUNNEL_SENDME_V1_DIGEST_LEN);
  96. inp->data_v1_digest[idx] = elt;
  97. return 0;
  98. }
  99. uint8_t *
  100. sendme_cell_getarray_data_v1_digest(sendme_cell_t *inp)
  101. {
  102. return inp->data_v1_digest;
  103. }
  104. const uint8_t *
  105. sendme_cell_getconstarray_data_v1_digest(const sendme_cell_t *inp)
  106. {
  107. return (const uint8_t *)sendme_cell_getarray_data_v1_digest((sendme_cell_t*)inp);
  108. }
  109. const char *
  110. sendme_cell_check(const sendme_cell_t *obj)
  111. {
  112. if (obj == NULL)
  113. return "Object was NULL";
  114. if (obj->trunnel_error_code_)
  115. return "A set function failed on this object";
  116. if (! (obj->version == 0 || obj->version == 1))
  117. return "Integer out of bounds";
  118. switch (obj->version) {
  119. case 0:
  120. break;
  121. case 1:
  122. break;
  123. default:
  124. return "Bad tag for union";
  125. break;
  126. }
  127. return NULL;
  128. }
  129. ssize_t
  130. sendme_cell_encoded_len(const sendme_cell_t *obj)
  131. {
  132. ssize_t result = 0;
  133. if (NULL != sendme_cell_check(obj))
  134. return -1;
  135. /* Length of u8 version IN [0, 1] */
  136. result += 1;
  137. /* Length of u16 data_len */
  138. result += 2;
  139. switch (obj->version) {
  140. case 0:
  141. break;
  142. case 1:
  143. /* Length of u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */
  144. result += TRUNNEL_SENDME_V1_DIGEST_LEN;
  145. break;
  146. default:
  147. trunnel_assert(0);
  148. break;
  149. }
  150. return result;
  151. }
  152. int
  153. sendme_cell_clear_errors(sendme_cell_t *obj)
  154. {
  155. int r = obj->trunnel_error_code_;
  156. obj->trunnel_error_code_ = 0;
  157. return r;
  158. }
  159. ssize_t
  160. sendme_cell_encode(uint8_t *output, const size_t avail, const sendme_cell_t *obj)
  161. {
  162. ssize_t result = 0;
  163. size_t written = 0;
  164. uint8_t *ptr = output;
  165. const char *msg;
  166. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  167. const ssize_t encoded_len = sendme_cell_encoded_len(obj);
  168. #endif
  169. uint8_t *backptr_data_len = NULL;
  170. if (NULL != (msg = sendme_cell_check(obj)))
  171. goto check_failed;
  172. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  173. trunnel_assert(encoded_len >= 0);
  174. #endif
  175. /* Encode u8 version IN [0, 1] */
  176. trunnel_assert(written <= avail);
  177. if (avail - written < 1)
  178. goto truncated;
  179. trunnel_set_uint8(ptr, (obj->version));
  180. written += 1; ptr += 1;
  181. /* Encode u16 data_len */
  182. backptr_data_len = ptr;
  183. trunnel_assert(written <= avail);
  184. if (avail - written < 2)
  185. goto truncated;
  186. trunnel_set_uint16(ptr, trunnel_htons(obj->data_len));
  187. written += 2; ptr += 2;
  188. {
  189. size_t written_before_union = written;
  190. /* Encode union data[version] */
  191. trunnel_assert(written <= avail);
  192. switch (obj->version) {
  193. case 0:
  194. break;
  195. case 1:
  196. /* Encode u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */
  197. trunnel_assert(written <= avail);
  198. if (avail - written < TRUNNEL_SENDME_V1_DIGEST_LEN)
  199. goto truncated;
  200. memcpy(ptr, obj->data_v1_digest, TRUNNEL_SENDME_V1_DIGEST_LEN);
  201. written += TRUNNEL_SENDME_V1_DIGEST_LEN; ptr += TRUNNEL_SENDME_V1_DIGEST_LEN;
  202. break;
  203. default:
  204. trunnel_assert(0);
  205. break;
  206. }
  207. /* Write the length field back to data_len */
  208. trunnel_assert(written >= written_before_union);
  209. #if UINT16_MAX < SIZE_MAX
  210. if (written - written_before_union > UINT16_MAX)
  211. goto check_failed;
  212. #endif
  213. trunnel_set_uint16(backptr_data_len, trunnel_htons(written - written_before_union));
  214. }
  215. trunnel_assert(ptr == output + written);
  216. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  217. {
  218. trunnel_assert(encoded_len >= 0);
  219. trunnel_assert((size_t)encoded_len == written);
  220. }
  221. #endif
  222. return written;
  223. truncated:
  224. result = -2;
  225. goto fail;
  226. check_failed:
  227. (void)msg;
  228. result = -1;
  229. goto fail;
  230. fail:
  231. trunnel_assert(result < 0);
  232. return result;
  233. }
  234. /** As sendme_cell_parse(), but do not allocate the output object.
  235. */
  236. static ssize_t
  237. sendme_cell_parse_into(sendme_cell_t *obj, const uint8_t *input, const size_t len_in)
  238. {
  239. const uint8_t *ptr = input;
  240. size_t remaining = len_in;
  241. ssize_t result = 0;
  242. (void)result;
  243. /* Parse u8 version IN [0, 1] */
  244. CHECK_REMAINING(1, truncated);
  245. obj->version = (trunnel_get_uint8(ptr));
  246. remaining -= 1; ptr += 1;
  247. if (! (obj->version == 0 || obj->version == 1))
  248. goto fail;
  249. /* Parse u16 data_len */
  250. CHECK_REMAINING(2, truncated);
  251. obj->data_len = trunnel_ntohs(trunnel_get_uint16(ptr));
  252. remaining -= 2; ptr += 2;
  253. {
  254. size_t remaining_after;
  255. CHECK_REMAINING(obj->data_len, truncated);
  256. remaining_after = remaining - obj->data_len;
  257. remaining = obj->data_len;
  258. /* Parse union data[version] */
  259. switch (obj->version) {
  260. case 0:
  261. /* Skip to end of union */
  262. ptr += remaining; remaining = 0;
  263. break;
  264. case 1:
  265. /* Parse u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */
  266. CHECK_REMAINING(TRUNNEL_SENDME_V1_DIGEST_LEN, fail);
  267. memcpy(obj->data_v1_digest, ptr, TRUNNEL_SENDME_V1_DIGEST_LEN);
  268. remaining -= TRUNNEL_SENDME_V1_DIGEST_LEN; ptr += TRUNNEL_SENDME_V1_DIGEST_LEN;
  269. break;
  270. default:
  271. goto fail;
  272. break;
  273. }
  274. if (remaining != 0)
  275. goto fail;
  276. remaining = remaining_after;
  277. }
  278. trunnel_assert(ptr + remaining == input + len_in);
  279. return len_in - remaining;
  280. truncated:
  281. return -2;
  282. fail:
  283. result = -1;
  284. return result;
  285. }
  286. ssize_t
  287. sendme_cell_parse(sendme_cell_t **output, const uint8_t *input, const size_t len_in)
  288. {
  289. ssize_t result;
  290. *output = sendme_cell_new();
  291. if (NULL == *output)
  292. return -1;
  293. result = sendme_cell_parse_into(*output, input, len_in);
  294. if (result < 0) {
  295. sendme_cell_free(*output);
  296. *output = NULL;
  297. }
  298. return result;
  299. }