s2n_stuffer.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /*
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License").
  5. * You may not use this file except in compliance with the License.
  6. * A copy of the License is located at
  7. *
  8. * http://aws.amazon.com/apache2.0
  9. *
  10. * or in the "license" file accompanying this file. This file is distributed
  11. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  12. * express or implied. See the License for the specific language governing
  13. * permissions and limitations under the License.
  14. */
  15. #include "stuffer/s2n_stuffer.h"
  16. #include <sys/param.h>
  17. #include "error/s2n_errno.h"
  18. #include "utils/s2n_blob.h"
  19. #include "utils/s2n_mem.h"
  20. #include "utils/s2n_safety.h"
  21. S2N_RESULT s2n_stuffer_validate(const struct s2n_stuffer *stuffer)
  22. {
  23. /**
  24. * Note that we do not assert any properties on the tainted field,
  25. * as any boolean value in that field is valid.
  26. */
  27. RESULT_ENSURE_REF(stuffer);
  28. RESULT_GUARD(s2n_blob_validate(&stuffer->blob));
  29. RESULT_DEBUG_ENSURE(S2N_IMPLIES(stuffer->growable, stuffer->alloced), S2N_ERR_SAFETY);
  30. /* <= is valid because we can have a fully written/read stuffer */
  31. RESULT_DEBUG_ENSURE(stuffer->high_water_mark <= stuffer->blob.size, S2N_ERR_SAFETY);
  32. RESULT_DEBUG_ENSURE(stuffer->write_cursor <= stuffer->high_water_mark, S2N_ERR_SAFETY);
  33. RESULT_DEBUG_ENSURE(stuffer->read_cursor <= stuffer->write_cursor, S2N_ERR_SAFETY);
  34. return S2N_RESULT_OK;
  35. }
  36. S2N_RESULT s2n_stuffer_reservation_validate(const struct s2n_stuffer_reservation *reservation)
  37. {
  38. /**
  39. * Note that we need two dereferences here to decrease proof complexity
  40. * for CBMC (see https://github.com/awslabs/s2n/issues/2290). We can roll back
  41. * this change once CBMC can handle common subexpression elimination.
  42. */
  43. RESULT_ENSURE_REF(reservation);
  44. const struct s2n_stuffer_reservation reserve_obj = *reservation;
  45. RESULT_GUARD(s2n_stuffer_validate(reserve_obj.stuffer));
  46. const struct s2n_stuffer stuffer_obj = *(reserve_obj.stuffer);
  47. RESULT_ENSURE(stuffer_obj.blob.size >= reserve_obj.length, S2N_ERR_SAFETY);
  48. if (reserve_obj.length > 0) {
  49. RESULT_ENSURE(reserve_obj.write_cursor < stuffer_obj.write_cursor, S2N_ERR_SAFETY);
  50. RESULT_ENSURE(S2N_MEM_IS_WRITABLE(stuffer_obj.blob.data + reserve_obj.write_cursor, reserve_obj.length),
  51. S2N_ERR_SAFETY);
  52. }
  53. return S2N_RESULT_OK;
  54. }
  55. int s2n_stuffer_init(struct s2n_stuffer *stuffer, struct s2n_blob *in)
  56. {
  57. POSIX_ENSURE_MUT(stuffer);
  58. POSIX_PRECONDITION(s2n_blob_validate(in));
  59. stuffer->blob = *in;
  60. stuffer->read_cursor = 0;
  61. stuffer->write_cursor = 0;
  62. stuffer->high_water_mark = 0;
  63. stuffer->alloced = 0;
  64. stuffer->growable = 0;
  65. stuffer->tainted = 0;
  66. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  67. return S2N_SUCCESS;
  68. }
  69. int s2n_stuffer_init_written(struct s2n_stuffer *stuffer, struct s2n_blob *in)
  70. {
  71. POSIX_ENSURE_REF(in);
  72. POSIX_GUARD(s2n_stuffer_init(stuffer, in));
  73. POSIX_GUARD(s2n_stuffer_skip_write(stuffer, in->size));
  74. return S2N_SUCCESS;
  75. }
  76. int s2n_stuffer_alloc(struct s2n_stuffer *stuffer, const uint32_t size)
  77. {
  78. POSIX_ENSURE_REF(stuffer);
  79. *stuffer = (struct s2n_stuffer){ 0 };
  80. POSIX_GUARD(s2n_alloc(&stuffer->blob, size));
  81. POSIX_GUARD(s2n_stuffer_init(stuffer, &stuffer->blob));
  82. stuffer->alloced = 1;
  83. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  84. return S2N_SUCCESS;
  85. }
  86. int s2n_stuffer_growable_alloc(struct s2n_stuffer *stuffer, const uint32_t size)
  87. {
  88. POSIX_GUARD(s2n_stuffer_alloc(stuffer, size));
  89. stuffer->growable = 1;
  90. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  91. return S2N_SUCCESS;
  92. }
  93. int s2n_stuffer_free(struct s2n_stuffer *stuffer)
  94. {
  95. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  96. if (stuffer->alloced) {
  97. POSIX_GUARD(s2n_free(&stuffer->blob));
  98. }
  99. *stuffer = (struct s2n_stuffer){ 0 };
  100. return S2N_SUCCESS;
  101. }
  102. int s2n_stuffer_free_without_wipe(struct s2n_stuffer *stuffer)
  103. {
  104. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  105. if (stuffer->alloced) {
  106. POSIX_GUARD(s2n_free_without_wipe(&stuffer->blob));
  107. }
  108. *stuffer = (struct s2n_stuffer){ 0 };
  109. return S2N_SUCCESS;
  110. }
  111. int s2n_stuffer_resize(struct s2n_stuffer *stuffer, const uint32_t size)
  112. {
  113. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  114. POSIX_ENSURE(!stuffer->tainted, S2N_ERR_RESIZE_TAINTED_STUFFER);
  115. POSIX_ENSURE(stuffer->growable, S2N_ERR_RESIZE_STATIC_STUFFER);
  116. if (size == stuffer->blob.size) {
  117. return S2N_SUCCESS;
  118. }
  119. if (size == 0) {
  120. s2n_stuffer_wipe(stuffer);
  121. return s2n_free(&stuffer->blob);
  122. }
  123. if (size < stuffer->blob.size) {
  124. POSIX_CHECKED_MEMSET(stuffer->blob.data + size, S2N_WIPE_PATTERN, (stuffer->blob.size - size));
  125. if (stuffer->read_cursor > size) {
  126. stuffer->read_cursor = size;
  127. }
  128. if (stuffer->write_cursor > size) {
  129. stuffer->write_cursor = size;
  130. }
  131. if (stuffer->high_water_mark > size) {
  132. stuffer->high_water_mark = size;
  133. }
  134. stuffer->blob.size = size;
  135. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  136. return S2N_SUCCESS;
  137. }
  138. POSIX_GUARD(s2n_realloc(&stuffer->blob, size));
  139. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  140. return S2N_SUCCESS;
  141. }
  142. int s2n_stuffer_resize_if_empty(struct s2n_stuffer *stuffer, const uint32_t size)
  143. {
  144. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  145. if (stuffer->blob.data == NULL) {
  146. POSIX_ENSURE(!stuffer->tainted, S2N_ERR_RESIZE_TAINTED_STUFFER);
  147. POSIX_ENSURE(stuffer->growable, S2N_ERR_RESIZE_STATIC_STUFFER);
  148. POSIX_GUARD(s2n_realloc(&stuffer->blob, size));
  149. }
  150. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  151. return S2N_SUCCESS;
  152. }
  153. int s2n_stuffer_rewrite(struct s2n_stuffer *stuffer)
  154. {
  155. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  156. stuffer->write_cursor = 0;
  157. stuffer->read_cursor = 0;
  158. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  159. return S2N_SUCCESS;
  160. }
  161. int s2n_stuffer_rewind_read(struct s2n_stuffer *stuffer, const uint32_t size)
  162. {
  163. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  164. POSIX_ENSURE(stuffer->read_cursor >= size, S2N_ERR_STUFFER_OUT_OF_DATA);
  165. stuffer->read_cursor -= size;
  166. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  167. return S2N_SUCCESS;
  168. }
  169. int s2n_stuffer_reread(struct s2n_stuffer *stuffer)
  170. {
  171. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  172. stuffer->read_cursor = 0;
  173. return S2N_SUCCESS;
  174. }
  175. int s2n_stuffer_wipe_n(struct s2n_stuffer *stuffer, const uint32_t size)
  176. {
  177. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  178. if (size >= stuffer->write_cursor) {
  179. return s2n_stuffer_wipe(stuffer);
  180. }
  181. /* We know that size is now less than write_cursor */
  182. stuffer->write_cursor -= size;
  183. POSIX_CHECKED_MEMSET(stuffer->blob.data + stuffer->write_cursor, S2N_WIPE_PATTERN, size);
  184. stuffer->read_cursor = MIN(stuffer->read_cursor, stuffer->write_cursor);
  185. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  186. return S2N_SUCCESS;
  187. }
  188. bool s2n_stuffer_is_consumed(struct s2n_stuffer *stuffer)
  189. {
  190. return stuffer && (stuffer->read_cursor == stuffer->write_cursor);
  191. }
  192. int s2n_stuffer_wipe(struct s2n_stuffer *stuffer)
  193. {
  194. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  195. if (!s2n_stuffer_is_wiped(stuffer)) {
  196. POSIX_CHECKED_MEMSET(stuffer->blob.data, S2N_WIPE_PATTERN, stuffer->high_water_mark);
  197. }
  198. stuffer->tainted = 0;
  199. stuffer->write_cursor = 0;
  200. stuffer->read_cursor = 0;
  201. stuffer->high_water_mark = 0;
  202. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  203. return S2N_SUCCESS;
  204. }
  205. int s2n_stuffer_skip_read(struct s2n_stuffer *stuffer, uint32_t n)
  206. {
  207. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  208. POSIX_ENSURE(s2n_stuffer_data_available(stuffer) >= n, S2N_ERR_STUFFER_OUT_OF_DATA);
  209. stuffer->read_cursor += n;
  210. return S2N_SUCCESS;
  211. }
  212. void *s2n_stuffer_raw_read(struct s2n_stuffer *stuffer, uint32_t data_len)
  213. {
  214. PTR_GUARD_POSIX(s2n_stuffer_skip_read(stuffer, data_len));
  215. stuffer->tainted = 1;
  216. return (stuffer->blob.data) ? (stuffer->blob.data + stuffer->read_cursor - data_len) : NULL;
  217. }
  218. int s2n_stuffer_read(struct s2n_stuffer *stuffer, struct s2n_blob *out)
  219. {
  220. POSIX_ENSURE_REF(out);
  221. return s2n_stuffer_read_bytes(stuffer, out->data, out->size);
  222. }
  223. int s2n_stuffer_erase_and_read(struct s2n_stuffer *stuffer, struct s2n_blob *out)
  224. {
  225. POSIX_GUARD(s2n_stuffer_skip_read(stuffer, out->size));
  226. void *ptr = (stuffer->blob.data) ? (stuffer->blob.data + stuffer->read_cursor - out->size) : NULL;
  227. POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, out->size), S2N_ERR_NULL);
  228. POSIX_CHECKED_MEMCPY(out->data, ptr, out->size);
  229. POSIX_CHECKED_MEMSET(ptr, 0, out->size);
  230. return S2N_SUCCESS;
  231. }
  232. int s2n_stuffer_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size)
  233. {
  234. POSIX_ENSURE_REF(data);
  235. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  236. POSIX_GUARD(s2n_stuffer_skip_read(stuffer, size));
  237. POSIX_ENSURE_REF(stuffer->blob.data);
  238. void *ptr = stuffer->blob.data + stuffer->read_cursor - size;
  239. POSIX_CHECKED_MEMCPY(data, ptr, size);
  240. return S2N_SUCCESS;
  241. }
  242. int s2n_stuffer_erase_and_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size)
  243. {
  244. POSIX_GUARD(s2n_stuffer_skip_read(stuffer, size));
  245. POSIX_ENSURE_REF(stuffer->blob.data);
  246. void *ptr = stuffer->blob.data + stuffer->read_cursor - size;
  247. POSIX_CHECKED_MEMCPY(data, ptr, size);
  248. POSIX_CHECKED_MEMSET(ptr, 0, size);
  249. return S2N_SUCCESS;
  250. }
  251. int s2n_stuffer_skip_write(struct s2n_stuffer *stuffer, const uint32_t n)
  252. {
  253. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  254. POSIX_GUARD(s2n_stuffer_reserve_space(stuffer, n));
  255. stuffer->write_cursor += n;
  256. stuffer->high_water_mark = MAX(stuffer->write_cursor, stuffer->high_water_mark);
  257. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  258. return S2N_SUCCESS;
  259. }
  260. void *s2n_stuffer_raw_write(struct s2n_stuffer *stuffer, const uint32_t data_len)
  261. {
  262. PTR_GUARD_POSIX(s2n_stuffer_skip_write(stuffer, data_len));
  263. stuffer->tainted = 1;
  264. return (stuffer->blob.data) ? (stuffer->blob.data + stuffer->write_cursor - data_len) : NULL;
  265. }
  266. int s2n_stuffer_write(struct s2n_stuffer *stuffer, const struct s2n_blob *in)
  267. {
  268. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  269. POSIX_PRECONDITION(s2n_blob_validate(in));
  270. return s2n_stuffer_write_bytes(stuffer, in->data, in->size);
  271. }
  272. int s2n_stuffer_write_bytes(struct s2n_stuffer *stuffer, const uint8_t *data, const uint32_t size)
  273. {
  274. POSIX_ENSURE(S2N_MEM_IS_READABLE(data, size), S2N_ERR_SAFETY);
  275. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  276. POSIX_GUARD(s2n_stuffer_skip_write(stuffer, size));
  277. void *ptr = stuffer->blob.data + stuffer->write_cursor - size;
  278. POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, size), S2N_ERR_NULL);
  279. if (ptr == data) {
  280. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  281. return S2N_SUCCESS;
  282. }
  283. POSIX_CHECKED_MEMCPY(ptr, data, size);
  284. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  285. return S2N_SUCCESS;
  286. }
  287. int s2n_stuffer_writev_bytes(struct s2n_stuffer *stuffer, const struct iovec *iov, size_t iov_count, uint32_t offs,
  288. uint32_t size)
  289. {
  290. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  291. POSIX_ENSURE_REF(iov);
  292. void *ptr = s2n_stuffer_raw_write(stuffer, size);
  293. POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, size), S2N_ERR_NULL);
  294. size_t size_left = size, to_skip = offs;
  295. for (size_t i = 0; i < iov_count; i++) {
  296. if (to_skip >= iov[i].iov_len) {
  297. to_skip -= iov[i].iov_len;
  298. continue;
  299. }
  300. size_t iov_len_op = iov[i].iov_len - to_skip;
  301. POSIX_ENSURE_LTE(iov_len_op, UINT32_MAX);
  302. uint32_t iov_len = (uint32_t) iov_len_op;
  303. uint32_t iov_size_to_take = MIN(size_left, iov_len);
  304. POSIX_ENSURE_REF(iov[i].iov_base);
  305. POSIX_ENSURE_LT(to_skip, iov[i].iov_len);
  306. POSIX_CHECKED_MEMCPY(ptr, ((uint8_t *) (iov[i].iov_base)) + to_skip, iov_size_to_take);
  307. size_left -= iov_size_to_take;
  308. if (size_left == 0) {
  309. break;
  310. }
  311. ptr = (void *) ((uint8_t *) ptr + iov_size_to_take);
  312. to_skip = 0;
  313. }
  314. return S2N_SUCCESS;
  315. }
  316. static int s2n_stuffer_copy_impl(struct s2n_stuffer *from, struct s2n_stuffer *to, const uint32_t len)
  317. {
  318. POSIX_GUARD(s2n_stuffer_skip_read(from, len));
  319. POSIX_GUARD(s2n_stuffer_skip_write(to, len));
  320. uint8_t *from_ptr = (from->blob.data) ? (from->blob.data + from->read_cursor - len) : NULL;
  321. uint8_t *to_ptr = (to->blob.data) ? (to->blob.data + to->write_cursor - len) : NULL;
  322. POSIX_CHECKED_MEMCPY(to_ptr, from_ptr, len);
  323. return S2N_SUCCESS;
  324. }
  325. int s2n_stuffer_reserve_space(struct s2n_stuffer *stuffer, uint32_t n)
  326. {
  327. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  328. if (s2n_stuffer_space_remaining(stuffer) < n) {
  329. POSIX_ENSURE(stuffer->growable, S2N_ERR_STUFFER_IS_FULL);
  330. /* Always grow a stuffer by at least 1k */
  331. const uint32_t growth = MAX(n - s2n_stuffer_space_remaining(stuffer), S2N_MIN_STUFFER_GROWTH_IN_BYTES);
  332. uint32_t new_size = 0;
  333. POSIX_GUARD(s2n_add_overflow(stuffer->blob.size, growth, &new_size));
  334. POSIX_GUARD(s2n_stuffer_resize(stuffer, new_size));
  335. }
  336. POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
  337. return S2N_SUCCESS;
  338. }
  339. /* Copies "len" bytes from "from" to "to".
  340. * If the copy cannot succeed (i.e. there are either not enough bytes available, or there is not enough space to write them
  341. * restore the old value of the stuffer */
  342. int s2n_stuffer_copy(struct s2n_stuffer *from, struct s2n_stuffer *to, const uint32_t len)
  343. {
  344. const uint32_t orig_read_cursor = from->read_cursor;
  345. const uint32_t orig_write_cursor = to->write_cursor;
  346. if (s2n_stuffer_copy_impl(from, to, len) < 0) {
  347. from->read_cursor = orig_read_cursor;
  348. to->write_cursor = orig_write_cursor;
  349. S2N_ERROR_PRESERVE_ERRNO();
  350. }
  351. return S2N_SUCCESS;
  352. }
  353. int s2n_stuffer_extract_blob(struct s2n_stuffer *stuffer, struct s2n_blob *out)
  354. {
  355. POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
  356. POSIX_ENSURE_REF(out);
  357. POSIX_GUARD(s2n_realloc(out, s2n_stuffer_data_available(stuffer)));
  358. if (s2n_stuffer_data_available(stuffer) > 0) {
  359. POSIX_CHECKED_MEMCPY(out->data, stuffer->blob.data + stuffer->read_cursor, s2n_stuffer_data_available(stuffer));
  360. }
  361. POSIX_POSTCONDITION(s2n_blob_validate(out));
  362. return S2N_SUCCESS;
  363. }