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