s2n_stuffer.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. #pragma once
  16. #include <limits.h>
  17. #include <stdint.h>
  18. #include <stdlib.h>
  19. #include <sys/uio.h>
  20. #include "utils/s2n_blob.h"
  21. #include "utils/s2n_result.h"
  22. #define S2N_MIN_STUFFER_GROWTH_IN_BYTES 1024
  23. /* Using a non-zero value
  24. * (a) makes wiped data easy to see in the debugger
  25. * (b) makes use of wiped data obvious since this is unlikely to be a valid bit pattern
  26. */
  27. #define S2N_WIPE_PATTERN 'w'
  28. #define SIZEOF_IN_BITS(t) (sizeof(t) * CHAR_BIT)
  29. #define SIZEOF_UINT24 3
  30. struct s2n_stuffer {
  31. /* The data for the s2n_stuffer */
  32. struct s2n_blob blob;
  33. /* Cursors to the current read/write position in the s2n_stuffer */
  34. uint32_t read_cursor;
  35. uint32_t write_cursor;
  36. uint32_t high_water_mark;
  37. /* Was this stuffer alloc()'d ? */
  38. unsigned int alloced : 1;
  39. /* Is this stuffer growable? */
  40. unsigned int growable : 1;
  41. /* Can this stuffer be safely resized?
  42. * A growable stuffer can be temporarily tainted by a raw read/write,
  43. * preventing it from resizing. */
  44. unsigned int tainted : 1;
  45. };
  46. #define s2n_stuffer_data_available(s) ((s)->write_cursor - (s)->read_cursor)
  47. #define s2n_stuffer_space_remaining(s) ((s)->blob.size - (s)->write_cursor)
  48. #define s2n_stuffer_is_wiped(s) ((s)->high_water_mark == 0)
  49. #define s2n_stuffer_is_freed(s) ((s)->blob.data == NULL)
  50. /* Check basic validity constraints on the stuffer: e.g. that cursors point within the blob */
  51. S2N_RESULT s2n_stuffer_validate(const struct s2n_stuffer *stuffer);
  52. /* Initialize and destroying stuffers */
  53. int s2n_stuffer_init(struct s2n_stuffer *stuffer, struct s2n_blob *in);
  54. int s2n_stuffer_init_written(struct s2n_stuffer *stuffer, struct s2n_blob *in);
  55. int s2n_stuffer_alloc(struct s2n_stuffer *stuffer, const uint32_t size);
  56. int s2n_stuffer_growable_alloc(struct s2n_stuffer *stuffer, const uint32_t size);
  57. int s2n_stuffer_free(struct s2n_stuffer *stuffer);
  58. /**
  59. * Frees the stuffer without zeroizing the contained data.
  60. *
  61. * This should only be used in scenarios where the data is encrypted or has been
  62. * cleared with `s2n_stuffer_erase_and_read`. In most cases, prefer `s2n_stuffer_free`.
  63. */
  64. int s2n_stuffer_free_without_wipe(struct s2n_stuffer *stuffer);
  65. int s2n_stuffer_resize(struct s2n_stuffer *stuffer, const uint32_t size);
  66. int s2n_stuffer_resize_if_empty(struct s2n_stuffer *stuffer, const uint32_t size);
  67. int s2n_stuffer_rewind_read(struct s2n_stuffer *stuffer, const uint32_t size);
  68. int s2n_stuffer_reread(struct s2n_stuffer *stuffer);
  69. int s2n_stuffer_rewrite(struct s2n_stuffer *stuffer);
  70. int s2n_stuffer_wipe(struct s2n_stuffer *stuffer);
  71. int s2n_stuffer_wipe_n(struct s2n_stuffer *stuffer, const uint32_t n);
  72. bool s2n_stuffer_is_consumed(struct s2n_stuffer *stuffer);
  73. /* Basic read and write */
  74. int s2n_stuffer_read(struct s2n_stuffer *stuffer, struct s2n_blob *out);
  75. int s2n_stuffer_erase_and_read(struct s2n_stuffer *stuffer, struct s2n_blob *out);
  76. int s2n_stuffer_write(struct s2n_stuffer *stuffer, const struct s2n_blob *in);
  77. int s2n_stuffer_read_bytes(struct s2n_stuffer *stuffer, uint8_t *out, uint32_t n);
  78. int s2n_stuffer_erase_and_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size);
  79. int s2n_stuffer_write_bytes(struct s2n_stuffer *stuffer, const uint8_t *in, const uint32_t n);
  80. int s2n_stuffer_writev_bytes(struct s2n_stuffer *stuffer, const struct iovec *iov, size_t iov_count,
  81. uint32_t offs, uint32_t size);
  82. int s2n_stuffer_skip_read(struct s2n_stuffer *stuffer, uint32_t n);
  83. int s2n_stuffer_skip_write(struct s2n_stuffer *stuffer, const uint32_t n);
  84. /* Tries to reserve enough space to write n additional bytes into the stuffer.*/
  85. int s2n_stuffer_reserve_space(struct s2n_stuffer *stuffer, uint32_t n);
  86. /* Raw read/write move the cursor along and give you a pointer you can
  87. * read/write data_len bytes from/to in-place.
  88. */
  89. void *s2n_stuffer_raw_write(struct s2n_stuffer *stuffer, const uint32_t data_len);
  90. void *s2n_stuffer_raw_read(struct s2n_stuffer *stuffer, uint32_t data_len);
  91. /* Send/receive stuffer to/from a file descriptor */
  92. int s2n_stuffer_recv_from_fd(struct s2n_stuffer *stuffer, const int rfd, const uint32_t len,
  93. uint32_t *bytes_written);
  94. int s2n_stuffer_send_to_fd(struct s2n_stuffer *stuffer, const int wfd, const uint32_t len, uint32_t *bytes_sent);
  95. /* Read and write integers in network order */
  96. int s2n_stuffer_read_uint8(struct s2n_stuffer *stuffer, uint8_t *u);
  97. int s2n_stuffer_read_uint16(struct s2n_stuffer *stuffer, uint16_t *u);
  98. int s2n_stuffer_read_uint24(struct s2n_stuffer *stuffer, uint32_t *u);
  99. int s2n_stuffer_read_uint32(struct s2n_stuffer *stuffer, uint32_t *u);
  100. int s2n_stuffer_read_uint64(struct s2n_stuffer *stuffer, uint64_t *u);
  101. int s2n_stuffer_write_uint8(struct s2n_stuffer *stuffer, const uint8_t u);
  102. int s2n_stuffer_write_uint16(struct s2n_stuffer *stuffer, const uint16_t u);
  103. int s2n_stuffer_write_uint24(struct s2n_stuffer *stuffer, const uint32_t u);
  104. int s2n_stuffer_write_uint32(struct s2n_stuffer *stuffer, const uint32_t u);
  105. int s2n_stuffer_write_uint64(struct s2n_stuffer *stuffer, const uint64_t u);
  106. /* Allocate space now for network order integers that will be written later.
  107. * These are primarily intended to handle the vector type defined in the RFC:
  108. * https://tools.ietf.org/html/rfc8446#section-3.4 */
  109. struct s2n_stuffer_reservation {
  110. struct s2n_stuffer *stuffer;
  111. uint32_t write_cursor;
  112. uint8_t length;
  113. };
  114. /* Check basic validity constraints on the s2n_stuffer_reservation: e.g. stuffer validity. */
  115. S2N_RESULT s2n_stuffer_reservation_validate(const struct s2n_stuffer_reservation *reservation);
  116. int s2n_stuffer_reserve_uint8(struct s2n_stuffer *stuffer, struct s2n_stuffer_reservation *reservation);
  117. int s2n_stuffer_reserve_uint16(struct s2n_stuffer *stuffer, struct s2n_stuffer_reservation *reservation);
  118. int s2n_stuffer_reserve_uint24(struct s2n_stuffer *stuffer, struct s2n_stuffer_reservation *reservation);
  119. int s2n_stuffer_write_vector_size(struct s2n_stuffer_reservation *reservation);
  120. /* Copy one stuffer to another */
  121. int s2n_stuffer_copy(struct s2n_stuffer *from, struct s2n_stuffer *to, uint32_t len);
  122. /* Read and write base64 */
  123. int s2n_stuffer_read_base64(struct s2n_stuffer *stuffer, struct s2n_stuffer *out);
  124. int s2n_stuffer_write_base64(struct s2n_stuffer *stuffer, struct s2n_stuffer *in);
  125. /* Useful for text manipulation ... */
  126. #define s2n_stuffer_write_char(stuffer, c) s2n_stuffer_write_uint8((stuffer), (uint8_t) (c))
  127. #define s2n_stuffer_read_char(stuffer, c) s2n_stuffer_read_uint8((stuffer), (uint8_t *) (c))
  128. #define s2n_stuffer_write_str(stuffer, c) s2n_stuffer_write_bytes((stuffer), (const uint8_t *) (c), strlen((c)))
  129. #define s2n_stuffer_write_text(stuffer, c, n) s2n_stuffer_write_bytes((stuffer), (const uint8_t *) (c), (n))
  130. #define s2n_stuffer_read_text(stuffer, c, n) s2n_stuffer_read_bytes((stuffer), (uint8_t *) (c), (n))
  131. int s2n_stuffer_read_expected_str(struct s2n_stuffer *stuffer, const char *expected);
  132. int s2n_stuffer_peek_char(struct s2n_stuffer *stuffer, char *c);
  133. int s2n_stuffer_read_token(struct s2n_stuffer *stuffer, struct s2n_stuffer *token, char delim);
  134. int s2n_stuffer_read_line(struct s2n_stuffer *stuffer, struct s2n_stuffer *token);
  135. int s2n_stuffer_peek_check_for_str(struct s2n_stuffer *s2n_stuffer, const char *expected);
  136. int s2n_stuffer_skip_whitespace(struct s2n_stuffer *stuffer, uint32_t *skipped);
  137. int s2n_stuffer_skip_to_char(struct s2n_stuffer *stuffer, char target);
  138. int s2n_stuffer_skip_expected_char(struct s2n_stuffer *stuffer, const char expected, const uint32_t min,
  139. const uint32_t max, uint32_t *skipped);
  140. int s2n_stuffer_skip_read_until(struct s2n_stuffer *stuffer, const char *target);
  141. int s2n_stuffer_alloc_ro_from_string(struct s2n_stuffer *stuffer, const char *str);
  142. int s2n_stuffer_init_ro_from_string(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t length);
  143. /* Read a private key from a PEM encoded stuffer to an ASN1/DER encoded one */
  144. int s2n_stuffer_private_key_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1, int *type);
  145. /* Read a certificate from a PEM encoded stuffer to an ASN1/DER encoded one */
  146. int s2n_stuffer_certificate_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1);
  147. /* Read a CRL from a PEM encoded stuffer to an ASN1/DER encoded one */
  148. int s2n_stuffer_crl_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1);
  149. /* Read DH parameters om a PEM encoded stuffer to a PKCS3 encoded one */
  150. int s2n_stuffer_dhparams_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *pkcs3);
  151. bool s2n_is_base64_char(unsigned char c);
  152. /* Copies all valid data from "stuffer" into "out".
  153. * The old blob "out" pointed to is freed.
  154. * It is the responsibility of the caller to free the free "out".
  155. */
  156. int s2n_stuffer_extract_blob(struct s2n_stuffer *stuffer, struct s2n_blob *out);