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