pwbox.c 11 KB

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