pwbox.c 12 KB

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