pwbox.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /* pwbox.c -- generated by Trunnel v1.5.2.
  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 "pwbox.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 pwbox_deadcode_dummy__ = 0;
  16. #define OR_DEADCODE_DUMMY || pwbox_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. pwbox_encoded_t *
  27. pwbox_encoded_new(void)
  28. {
  29. pwbox_encoded_t *val = trunnel_calloc(1, sizeof(pwbox_encoded_t));
  30. if (NULL == val)
  31. return NULL;
  32. val->fixedbytes0 = PWBOX0_CONST0;
  33. val->fixedbytes1 = PWBOX0_CONST1;
  34. return val;
  35. }
  36. /** Release all storage held inside 'obj', but do not free 'obj'.
  37. */
  38. static void
  39. pwbox_encoded_clear(pwbox_encoded_t *obj)
  40. {
  41. (void) obj;
  42. TRUNNEL_DYNARRAY_WIPE(&obj->skey_header);
  43. TRUNNEL_DYNARRAY_CLEAR(&obj->skey_header);
  44. TRUNNEL_DYNARRAY_WIPE(&obj->data);
  45. TRUNNEL_DYNARRAY_CLEAR(&obj->data);
  46. }
  47. void
  48. pwbox_encoded_free(pwbox_encoded_t *obj)
  49. {
  50. if (obj == NULL)
  51. return;
  52. pwbox_encoded_clear(obj);
  53. trunnel_memwipe(obj, sizeof(pwbox_encoded_t));
  54. trunnel_free_(obj);
  55. }
  56. uint32_t
  57. pwbox_encoded_get_fixedbytes0(const pwbox_encoded_t *inp)
  58. {
  59. return inp->fixedbytes0;
  60. }
  61. int
  62. pwbox_encoded_set_fixedbytes0(pwbox_encoded_t *inp, uint32_t val)
  63. {
  64. if (! ((val == PWBOX0_CONST0))) {
  65. TRUNNEL_SET_ERROR_CODE(inp);
  66. return -1;
  67. }
  68. inp->fixedbytes0 = val;
  69. return 0;
  70. }
  71. uint32_t
  72. pwbox_encoded_get_fixedbytes1(const pwbox_encoded_t *inp)
  73. {
  74. return inp->fixedbytes1;
  75. }
  76. int
  77. pwbox_encoded_set_fixedbytes1(pwbox_encoded_t *inp, uint32_t val)
  78. {
  79. if (! ((val == PWBOX0_CONST1))) {
  80. TRUNNEL_SET_ERROR_CODE(inp);
  81. return -1;
  82. }
  83. inp->fixedbytes1 = val;
  84. return 0;
  85. }
  86. uint8_t
  87. pwbox_encoded_get_header_len(const pwbox_encoded_t *inp)
  88. {
  89. return inp->header_len;
  90. }
  91. int
  92. pwbox_encoded_set_header_len(pwbox_encoded_t *inp, uint8_t val)
  93. {
  94. inp->header_len = val;
  95. return 0;
  96. }
  97. size_t
  98. pwbox_encoded_getlen_skey_header(const pwbox_encoded_t *inp)
  99. {
  100. return TRUNNEL_DYNARRAY_LEN(&inp->skey_header);
  101. }
  102. uint8_t
  103. pwbox_encoded_get_skey_header(pwbox_encoded_t *inp, size_t idx)
  104. {
  105. return TRUNNEL_DYNARRAY_GET(&inp->skey_header, idx);
  106. }
  107. uint8_t
  108. pwbox_encoded_getconst_skey_header(const pwbox_encoded_t *inp, size_t idx)
  109. {
  110. return pwbox_encoded_get_skey_header((pwbox_encoded_t*)inp, idx);
  111. }
  112. int
  113. pwbox_encoded_set_skey_header(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
  114. {
  115. TRUNNEL_DYNARRAY_SET(&inp->skey_header, idx, elt);
  116. return 0;
  117. }
  118. int
  119. pwbox_encoded_add_skey_header(pwbox_encoded_t *inp, uint8_t elt)
  120. {
  121. #if SIZE_MAX >= UINT8_MAX
  122. if (inp->skey_header.n_ == UINT8_MAX)
  123. goto trunnel_alloc_failed;
  124. #endif
  125. TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->skey_header, elt, {});
  126. return 0;
  127. trunnel_alloc_failed:
  128. TRUNNEL_SET_ERROR_CODE(inp);
  129. return -1;
  130. }
  131. uint8_t *
  132. pwbox_encoded_getarray_skey_header(pwbox_encoded_t *inp)
  133. {
  134. return inp->skey_header.elts_;
  135. }
  136. const uint8_t *
  137. pwbox_encoded_getconstarray_skey_header(const pwbox_encoded_t *inp)
  138. {
  139. return (const uint8_t *)pwbox_encoded_getarray_skey_header((pwbox_encoded_t*)inp);
  140. }
  141. int
  142. pwbox_encoded_setlen_skey_header(pwbox_encoded_t *inp, size_t newlen)
  143. {
  144. uint8_t *newptr;
  145. #if UINT8_MAX < SIZE_MAX
  146. if (newlen > UINT8_MAX)
  147. goto trunnel_alloc_failed;
  148. #endif
  149. newptr = trunnel_dynarray_setlen(&inp->skey_header.allocated_,
  150. &inp->skey_header.n_, inp->skey_header.elts_, newlen,
  151. sizeof(inp->skey_header.elts_[0]), (trunnel_free_fn_t) NULL,
  152. &inp->trunnel_error_code_);
  153. if (newlen != 0 && newptr == NULL)
  154. goto trunnel_alloc_failed;
  155. inp->skey_header.elts_ = newptr;
  156. return 0;
  157. trunnel_alloc_failed:
  158. TRUNNEL_SET_ERROR_CODE(inp);
  159. return -1;
  160. }
  161. size_t
  162. pwbox_encoded_getlen_iv(const pwbox_encoded_t *inp)
  163. {
  164. (void)inp; return 16;
  165. }
  166. uint8_t
  167. pwbox_encoded_get_iv(pwbox_encoded_t *inp, size_t idx)
  168. {
  169. trunnel_assert(idx < 16);
  170. return inp->iv[idx];
  171. }
  172. uint8_t
  173. pwbox_encoded_getconst_iv(const pwbox_encoded_t *inp, size_t idx)
  174. {
  175. return pwbox_encoded_get_iv((pwbox_encoded_t*)inp, idx);
  176. }
  177. int
  178. pwbox_encoded_set_iv(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
  179. {
  180. trunnel_assert(idx < 16);
  181. inp->iv[idx] = elt;
  182. return 0;
  183. }
  184. uint8_t *
  185. pwbox_encoded_getarray_iv(pwbox_encoded_t *inp)
  186. {
  187. return inp->iv;
  188. }
  189. const uint8_t *
  190. pwbox_encoded_getconstarray_iv(const pwbox_encoded_t *inp)
  191. {
  192. return (const uint8_t *)pwbox_encoded_getarray_iv((pwbox_encoded_t*)inp);
  193. }
  194. size_t
  195. pwbox_encoded_getlen_data(const pwbox_encoded_t *inp)
  196. {
  197. return TRUNNEL_DYNARRAY_LEN(&inp->data);
  198. }
  199. uint8_t
  200. pwbox_encoded_get_data(pwbox_encoded_t *inp, size_t idx)
  201. {
  202. return TRUNNEL_DYNARRAY_GET(&inp->data, idx);
  203. }
  204. uint8_t
  205. pwbox_encoded_getconst_data(const pwbox_encoded_t *inp, size_t idx)
  206. {
  207. return pwbox_encoded_get_data((pwbox_encoded_t*)inp, idx);
  208. }
  209. int
  210. pwbox_encoded_set_data(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
  211. {
  212. TRUNNEL_DYNARRAY_SET(&inp->data, idx, elt);
  213. return 0;
  214. }
  215. int
  216. pwbox_encoded_add_data(pwbox_encoded_t *inp, uint8_t elt)
  217. {
  218. TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->data, elt, {});
  219. return 0;
  220. trunnel_alloc_failed:
  221. TRUNNEL_SET_ERROR_CODE(inp);
  222. return -1;
  223. }
  224. uint8_t *
  225. pwbox_encoded_getarray_data(pwbox_encoded_t *inp)
  226. {
  227. return inp->data.elts_;
  228. }
  229. const uint8_t *
  230. pwbox_encoded_getconstarray_data(const pwbox_encoded_t *inp)
  231. {
  232. return (const uint8_t *)pwbox_encoded_getarray_data((pwbox_encoded_t*)inp);
  233. }
  234. int
  235. pwbox_encoded_setlen_data(pwbox_encoded_t *inp, size_t newlen)
  236. {
  237. uint8_t *newptr;
  238. newptr = trunnel_dynarray_setlen(&inp->data.allocated_,
  239. &inp->data.n_, inp->data.elts_, newlen,
  240. sizeof(inp->data.elts_[0]), (trunnel_free_fn_t) NULL,
  241. &inp->trunnel_error_code_);
  242. if (newlen != 0 && newptr == NULL)
  243. goto trunnel_alloc_failed;
  244. inp->data.elts_ = newptr;
  245. return 0;
  246. trunnel_alloc_failed:
  247. TRUNNEL_SET_ERROR_CODE(inp);
  248. return -1;
  249. }
  250. size_t
  251. pwbox_encoded_getlen_hmac(const pwbox_encoded_t *inp)
  252. {
  253. (void)inp; return 32;
  254. }
  255. uint8_t
  256. pwbox_encoded_get_hmac(pwbox_encoded_t *inp, size_t idx)
  257. {
  258. trunnel_assert(idx < 32);
  259. return inp->hmac[idx];
  260. }
  261. uint8_t
  262. pwbox_encoded_getconst_hmac(const pwbox_encoded_t *inp, size_t idx)
  263. {
  264. return pwbox_encoded_get_hmac((pwbox_encoded_t*)inp, idx);
  265. }
  266. int
  267. pwbox_encoded_set_hmac(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
  268. {
  269. trunnel_assert(idx < 32);
  270. inp->hmac[idx] = elt;
  271. return 0;
  272. }
  273. uint8_t *
  274. pwbox_encoded_getarray_hmac(pwbox_encoded_t *inp)
  275. {
  276. return inp->hmac;
  277. }
  278. const uint8_t *
  279. pwbox_encoded_getconstarray_hmac(const pwbox_encoded_t *inp)
  280. {
  281. return (const uint8_t *)pwbox_encoded_getarray_hmac((pwbox_encoded_t*)inp);
  282. }
  283. const char *
  284. pwbox_encoded_check(const pwbox_encoded_t *obj)
  285. {
  286. if (obj == NULL)
  287. return "Object was NULL";
  288. if (obj->trunnel_error_code_)
  289. return "A set function failed on this object";
  290. if (! (obj->fixedbytes0 == PWBOX0_CONST0))
  291. return "Integer out of bounds";
  292. if (! (obj->fixedbytes1 == PWBOX0_CONST1))
  293. return "Integer out of bounds";
  294. if (TRUNNEL_DYNARRAY_LEN(&obj->skey_header) != obj->header_len)
  295. return "Length mismatch for skey_header";
  296. return NULL;
  297. }
  298. ssize_t
  299. pwbox_encoded_encoded_len(const pwbox_encoded_t *obj)
  300. {
  301. ssize_t result = 0;
  302. if (NULL != pwbox_encoded_check(obj))
  303. return -1;
  304. /* Length of u32 fixedbytes0 IN [PWBOX0_CONST0] */
  305. result += 4;
  306. /* Length of u32 fixedbytes1 IN [PWBOX0_CONST1] */
  307. result += 4;
  308. /* Length of u8 header_len */
  309. result += 1;
  310. /* Length of u8 skey_header[header_len] */
  311. result += TRUNNEL_DYNARRAY_LEN(&obj->skey_header);
  312. /* Length of u8 iv[16] */
  313. result += 16;
  314. /* Length of u8 data[] */
  315. result += TRUNNEL_DYNARRAY_LEN(&obj->data);
  316. /* Length of u8 hmac[32] */
  317. result += 32;
  318. return result;
  319. }
  320. int
  321. pwbox_encoded_clear_errors(pwbox_encoded_t *obj)
  322. {
  323. int r = obj->trunnel_error_code_;
  324. obj->trunnel_error_code_ = 0;
  325. return r;
  326. }
  327. ssize_t
  328. pwbox_encoded_encode(uint8_t *output, size_t avail, const pwbox_encoded_t *obj)
  329. {
  330. ssize_t result = 0;
  331. size_t written = 0;
  332. uint8_t *ptr = output;
  333. const char *msg;
  334. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  335. const ssize_t encoded_len = pwbox_encoded_encoded_len(obj);
  336. #endif
  337. int enforce_avail = 0;
  338. const size_t avail_orig = avail;
  339. if (NULL != (msg = pwbox_encoded_check(obj)))
  340. goto check_failed;
  341. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  342. trunnel_assert(encoded_len >= 0);
  343. #endif
  344. /* Encode u32 fixedbytes0 IN [PWBOX0_CONST0] */
  345. trunnel_assert(written <= avail);
  346. if (avail - written < 4)
  347. goto truncated;
  348. trunnel_set_uint32(ptr, trunnel_htonl(obj->fixedbytes0));
  349. written += 4; ptr += 4;
  350. /* Encode u32 fixedbytes1 IN [PWBOX0_CONST1] */
  351. trunnel_assert(written <= avail);
  352. if (avail - written < 4)
  353. goto truncated;
  354. trunnel_set_uint32(ptr, trunnel_htonl(obj->fixedbytes1));
  355. written += 4; ptr += 4;
  356. /* Encode u8 header_len */
  357. trunnel_assert(written <= avail);
  358. if (avail - written < 1)
  359. goto truncated;
  360. trunnel_set_uint8(ptr, (obj->header_len));
  361. written += 1; ptr += 1;
  362. /* Encode u8 skey_header[header_len] */
  363. {
  364. size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->skey_header);
  365. trunnel_assert(obj->header_len == elt_len);
  366. trunnel_assert(written <= avail);
  367. if (avail - written < elt_len)
  368. goto truncated;
  369. if (elt_len)
  370. memcpy(ptr, obj->skey_header.elts_, elt_len);
  371. written += elt_len; ptr += elt_len;
  372. }
  373. /* Encode u8 iv[16] */
  374. trunnel_assert(written <= avail);
  375. if (avail - written < 16)
  376. goto truncated;
  377. memcpy(ptr, obj->iv, 16);
  378. written += 16; ptr += 16;
  379. {
  380. /* Encode u8 data[] */
  381. {
  382. size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->data);
  383. trunnel_assert(written <= avail);
  384. if (avail - written < elt_len)
  385. goto truncated;
  386. if (elt_len)
  387. memcpy(ptr, obj->data.elts_, elt_len);
  388. written += elt_len; ptr += elt_len;
  389. }
  390. trunnel_assert(written <= avail);
  391. if (avail - written < 32)
  392. goto truncated;
  393. avail = written + 32;
  394. enforce_avail = 1;
  395. }
  396. /* Encode u8 hmac[32] */
  397. trunnel_assert(written <= avail);
  398. if (avail - written < 32) {
  399. if (avail_orig - written < 32)
  400. goto truncated;
  401. else
  402. goto check_failed;
  403. }
  404. memcpy(ptr, obj->hmac, 32);
  405. written += 32; ptr += 32;
  406. trunnel_assert(ptr == output + written);
  407. if (enforce_avail && avail != written)
  408. goto check_failed;
  409. #ifdef TRUNNEL_CHECK_ENCODED_LEN
  410. {
  411. trunnel_assert(encoded_len >= 0);
  412. trunnel_assert((size_t)encoded_len == written);
  413. }
  414. #endif
  415. return written;
  416. truncated:
  417. result = -2;
  418. goto fail;
  419. check_failed:
  420. (void)msg;
  421. result = -1;
  422. goto fail;
  423. fail:
  424. trunnel_assert(result < 0);
  425. return result;
  426. }
  427. /** As pwbox_encoded_parse(), but do not allocate the output object.
  428. */
  429. static ssize_t
  430. pwbox_encoded_parse_into(pwbox_encoded_t *obj, const uint8_t *input, const size_t len_in)
  431. {
  432. const uint8_t *ptr = input;
  433. size_t remaining = len_in;
  434. ssize_t result = 0;
  435. (void)result;
  436. /* Parse u32 fixedbytes0 IN [PWBOX0_CONST0] */
  437. CHECK_REMAINING(4, truncated);
  438. obj->fixedbytes0 = trunnel_ntohl(trunnel_get_uint32(ptr));
  439. remaining -= 4; ptr += 4;
  440. if (! (obj->fixedbytes0 == PWBOX0_CONST0))
  441. goto fail;
  442. /* Parse u32 fixedbytes1 IN [PWBOX0_CONST1] */
  443. CHECK_REMAINING(4, truncated);
  444. obj->fixedbytes1 = trunnel_ntohl(trunnel_get_uint32(ptr));
  445. remaining -= 4; ptr += 4;
  446. if (! (obj->fixedbytes1 == PWBOX0_CONST1))
  447. goto fail;
  448. /* Parse u8 header_len */
  449. CHECK_REMAINING(1, truncated);
  450. obj->header_len = (trunnel_get_uint8(ptr));
  451. remaining -= 1; ptr += 1;
  452. /* Parse u8 skey_header[header_len] */
  453. CHECK_REMAINING(obj->header_len, truncated);
  454. TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->skey_header, obj->header_len, {});
  455. obj->skey_header.n_ = obj->header_len;
  456. if (obj->header_len)
  457. memcpy(obj->skey_header.elts_, ptr, obj->header_len);
  458. ptr += obj->header_len; remaining -= obj->header_len;
  459. /* Parse u8 iv[16] */
  460. CHECK_REMAINING(16, truncated);
  461. memcpy(obj->iv, ptr, 16);
  462. remaining -= 16; ptr += 16;
  463. {
  464. size_t remaining_after;
  465. CHECK_REMAINING(32, truncated);
  466. remaining_after = 32;
  467. remaining = remaining - 32;
  468. /* Parse u8 data[] */
  469. TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->data, remaining, {});
  470. obj->data.n_ = remaining;
  471. if (remaining)
  472. memcpy(obj->data.elts_, ptr, remaining);
  473. ptr += remaining; remaining -= remaining;
  474. if (remaining != 0)
  475. goto fail;
  476. remaining = remaining_after;
  477. }
  478. /* Parse u8 hmac[32] */
  479. CHECK_REMAINING(32, truncated);
  480. memcpy(obj->hmac, ptr, 32);
  481. remaining -= 32; ptr += 32;
  482. trunnel_assert(ptr + remaining == input + len_in);
  483. return len_in - remaining;
  484. truncated:
  485. return -2;
  486. trunnel_alloc_failed:
  487. return -1;
  488. fail:
  489. result = -1;
  490. return result;
  491. }
  492. ssize_t
  493. pwbox_encoded_parse(pwbox_encoded_t **output, const uint8_t *input, const size_t len_in)
  494. {
  495. ssize_t result;
  496. *output = pwbox_encoded_new();
  497. if (NULL == *output)
  498. return -1;
  499. result = pwbox_encoded_parse_into(*output, input, len_in);
  500. if (result < 0) {
  501. pwbox_encoded_free(*output);
  502. *output = NULL;
  503. }
  504. return result;
  505. }