pwbox.c 12 KB

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