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