1 /*
2 * Copyright 2014 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 /* Use usleep */
17 #define _XOPEN_SOURCE 500
18 #include <unistd.h>
19
20 #include <errno.h>
21 #include <s2n.h>
22
23 #include "error/s2n_errno.h"
24
25 #include "tls/s2n_connection.h"
26 #include "tls/s2n_handshake.h"
27 #include "tls/s2n_record.h"
28 #include "tls/s2n_alerts.h"
29 #include "tls/s2n_tls.h"
30
31 #include "stuffer/s2n_stuffer.h"
32
33 #include "utils/s2n_safety.h"
34 #include "utils/s2n_blob.h"
35
36 int s2n_read_full_record(struct s2n_connection *conn, uint8_t *record_type, int *isSSLv2)
37 {
38 int r;
39
40 *isSSLv2 = 0;
41
42 /* If the record has already been decrypted, then leave it alone */
43 if (conn->in_status == PLAINTEXT) {
44 /* Only application data packets count as plaintext */
45 *record_type = TLS_APPLICATION_DATA;
46 return 0;
47 }
48
49 /* Read the record until we at least have a header */
50 while (s2n_stuffer_data_available(&conn->header_in) < S2N_TLS_RECORD_HEADER_LENGTH) {
51 r = s2n_stuffer_recv_from_fd(&conn->header_in, conn->readfd, S2N_TLS_RECORD_HEADER_LENGTH - s2n_stuffer_data_available(&conn->header_in));
52 if (r == 0) {
53 return -2;
54 }
55 if (r < 0) {
56 return -1;
57 }
58 conn->wire_bytes_in += r;
59 }
60
61 uint16_t fragment_length;
62
63 /* If the first bit is set then this is an SSLv2 record */
64 if (conn->header_in.blob.data[0] & 0x80) {
65 conn->header_in.blob.data[0] &= 0x7f;
66 *isSSLv2 = 1;
67
68 if (s2n_sslv2_record_header_parse(conn, record_type, &conn->client_protocol_version, &fragment_length) < 0) {
69 conn->closed = 1;
70 GUARD(s2n_connection_wipe(conn));
71 return -1;
72 }
73 } else {
74 if (s2n_record_header_parse(conn, record_type, &fragment_length) < 0) {
75 conn->closed = 1;
76 GUARD(s2n_connection_wipe(conn));
77 return -1;
78 }
79 }
80
81 /* Read enough to have the whole record */
82 while (s2n_stuffer_data_available(&conn->in) < fragment_length) {
83 r = s2n_stuffer_recv_from_fd(&conn->in, conn->readfd, fragment_length - s2n_stuffer_data_available(&conn->in));
84 if (r == 0) {
85 return -2;
86 }
87 if (r < 0) {
88 return -1;
89 }
90 conn->wire_bytes_in += r;
91 }
92
93 if (*isSSLv2) {
94 return 0;
95 }
96
97 /* Decrypt and parse the record */
98 if (s2n_record_parse(conn) < 0) {
99 conn->closed = 1;
100 GUARD(s2n_connection_wipe(conn));
101
102 if (conn->blinding == S2N_BUILT_IN_BLINDING) {
103 int delay;
104 GUARD(delay = s2n_connection_get_delay(conn));
105 GUARD(sleep(delay / 1000000));
106 GUARD(usleep(delay % 1000000));
107 }
108
109 return -1;
110 }
111
112 return 0;
113 }
114
115 ssize_t s2n_recv(struct s2n_connection *conn, void *buf, ssize_t size, int *more)
116 {
117 ssize_t bytes_read = 0;
118 struct s2n_blob out = {.data = (uint8_t *) buf };
119
120 if (conn->closed) {
121 return 0;
122 }
123
124 *more = 1;
125
126 while (size && !conn->closed) {
127 int isSSLv2 = 0;
128 uint8_t record_type;
129 errno = 0;
130 int r = s2n_read_full_record(conn, &record_type, &isSSLv2);
131 if (r < 0) {
132 if (errno == EWOULDBLOCK) {
133 if (bytes_read) {
134 return bytes_read;
135 }
136 return -1;
137 }
138 if (r == -2) {
139 conn->closed = 1;
140 GUARD(s2n_connection_wipe(conn));
141 return bytes_read;
142 }
143 return -1;
144 }
145
146 if (isSSLv2) {
147 S2N_ERROR(S2N_ERR_BAD_MESSAGE);
148 }
149
150 if (record_type != TLS_APPLICATION_DATA) {
151 if (record_type == TLS_ALERT) {
152 GUARD(s2n_process_alert_fragment(conn));
153 GUARD(s2n_flush(conn, more));
154 }
155
156 GUARD(s2n_stuffer_wipe(&conn->header_in));
157 GUARD(s2n_stuffer_wipe(&conn->in));
158 conn->in_status = ENCRYPTED;
159 continue;
160 }
161
162 out.size = size;
163 if (out.size > s2n_stuffer_data_available(&conn->in)) {
164 out.size = s2n_stuffer_data_available(&conn->in);
165 }
166
167 GUARD(s2n_stuffer_erase_and_read(&conn->in, &out));
168 bytes_read += out.size;
169
170 out.data += out.size;
171 size -= out.size;
172
173 /* Are we ready for more encrypted data? */
174 if (s2n_stuffer_data_available(&conn->in) == 0) {
175 GUARD(s2n_stuffer_wipe(&conn->header_in));
176 GUARD(s2n_stuffer_wipe(&conn->in));
177 conn->in_status = ENCRYPTED;
178 }
179
180 /* If we've read some data, return it */
181 if (bytes_read) {
182 break;
183 }
184 }
185
186 if (s2n_stuffer_data_available(&conn->in) == 0) {
187 *more = 0;
188 }
189
190 return bytes_read;
191 }