A super trimmed down TLS stack, GPL licensed

Dependents:   MiniTLS-HTTPS-Example

MiniTLS - A super trimmed down TLS/SSL Library for embedded devices Author: Donatien Garnier Copyright (C) 2013-2014 AppNearMe Ltd

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

Committer:
MiniTLS
Date:
Fri Jun 06 10:49:02 2014 +0000
Revision:
0:35aa5be3b78d
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MiniTLS 0:35aa5be3b78d 1 /*
MiniTLS 0:35aa5be3b78d 2 MuTLS - A super trimmed down TLS/SSL Library for embedded devices
MiniTLS 0:35aa5be3b78d 3 Author: Donatien Garnier
MiniTLS 0:35aa5be3b78d 4 Copyright (C) 2013-2014 AppNearMe Ltd
MiniTLS 0:35aa5be3b78d 5
MiniTLS 0:35aa5be3b78d 6 This program is free software; you can redistribute it and/or
MiniTLS 0:35aa5be3b78d 7 modify it under the terms of the GNU General Public License
MiniTLS 0:35aa5be3b78d 8 as published by the Free Software Foundation; either version 2
MiniTLS 0:35aa5be3b78d 9 of the License, or (at your option) any later version.
MiniTLS 0:35aa5be3b78d 10
MiniTLS 0:35aa5be3b78d 11 This program is distributed in the hope that it will be useful,
MiniTLS 0:35aa5be3b78d 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
MiniTLS 0:35aa5be3b78d 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MiniTLS 0:35aa5be3b78d 14 GNU General Public License for more details.
MiniTLS 0:35aa5be3b78d 15
MiniTLS 0:35aa5be3b78d 16 You should have received a copy of the GNU General Public License
MiniTLS 0:35aa5be3b78d 17 along with this program; if not, write to the Free Software
MiniTLS 0:35aa5be3b78d 18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
MiniTLS 0:35aa5be3b78d 19 *//**
MiniTLS 0:35aa5be3b78d 20 * \file tls_record.c
MiniTLS 0:35aa5be3b78d 21 * \copyright Copyright (c) AppNearMe Ltd 2013
MiniTLS 0:35aa5be3b78d 22 * \author Donatien Garnier
MiniTLS 0:35aa5be3b78d 23 */
MiniTLS 0:35aa5be3b78d 24
MiniTLS 0:35aa5be3b78d 25 #define __DEBUG__ 0
MiniTLS 0:35aa5be3b78d 26 #ifndef __MODULE__
MiniTLS 0:35aa5be3b78d 27 #define __MODULE__ "tls_record.c"
MiniTLS 0:35aa5be3b78d 28 #endif
MiniTLS 0:35aa5be3b78d 29
MiniTLS 0:35aa5be3b78d 30 #include "core/fwk.h"
MiniTLS 0:35aa5be3b78d 31 #include "inc/mutls_config.h"
MiniTLS 0:35aa5be3b78d 32 #include "inc/mutls_errors.h"
MiniTLS 0:35aa5be3b78d 33 #include "tls_record.h"
MiniTLS 0:35aa5be3b78d 34 #include "tls_alert.h"
MiniTLS 0:35aa5be3b78d 35
MiniTLS 0:35aa5be3b78d 36 #include "tls_handshake.h"
MiniTLS 0:35aa5be3b78d 37 #include "tls_socket.h"
MiniTLS 0:35aa5be3b78d 38
MiniTLS 0:35aa5be3b78d 39 #include "socket/socket.h"
MiniTLS 0:35aa5be3b78d 40
MiniTLS 0:35aa5be3b78d 41 #include "crypto/crypto_aes_128_cbc.h"
MiniTLS 0:35aa5be3b78d 42 #include "crypto/crypto_hmac_sha1.h"
MiniTLS 0:35aa5be3b78d 43
MiniTLS 0:35aa5be3b78d 44 static mutls_err_t record_wait_readable(tls_record_t* record);
MiniTLS 0:35aa5be3b78d 45 static mutls_err_t record_wait_writeable(tls_record_t* record);
MiniTLS 0:35aa5be3b78d 46
MiniTLS 0:35aa5be3b78d 47 static mutls_err_t record_socket_read(tls_record_t* record, size_t size);
MiniTLS 0:35aa5be3b78d 48 static mutls_err_t record_socket_write(tls_record_t* record, buffer_t* data);
MiniTLS 0:35aa5be3b78d 49
MiniTLS 0:35aa5be3b78d 50 static mutls_err_t tls_mac_append( const uint8_t* key, tls_content_type_t content_type, tls_protocol_version_t version,
MiniTLS 0:35aa5be3b78d 51 uint64_t sequence_number, buffer_t* buffer );
MiniTLS 0:35aa5be3b78d 52 static mutls_err_t tls_mac_check( const uint8_t* key, tls_content_type_t content_type, tls_protocol_version_t version,
MiniTLS 0:35aa5be3b78d 53 uint64_t sequence_number, buffer_t* buffer );
MiniTLS 0:35aa5be3b78d 54
MiniTLS 0:35aa5be3b78d 55 typedef struct __tls_fragment_header
MiniTLS 0:35aa5be3b78d 56 {
MiniTLS 0:35aa5be3b78d 57 tls_content_type_t type;
MiniTLS 0:35aa5be3b78d 58 tls_protocol_version_t version;
MiniTLS 0:35aa5be3b78d 59 uint16_t length; //(MAX 2^14 + 2048 = 18432)
MiniTLS 0:35aa5be3b78d 60 } tls_fragment_header_t;
MiniTLS 0:35aa5be3b78d 61
MiniTLS 0:35aa5be3b78d 62 #define FRAGMENT_HEADER_SIZE 5
MiniTLS 0:35aa5be3b78d 63
MiniTLS 0:35aa5be3b78d 64 #define DEFAULT_READ_TIMEOUT 20000
MiniTLS 0:35aa5be3b78d 65 #define DEFAULT_WRITE_TIMEOUT 20000
MiniTLS 0:35aa5be3b78d 66
MiniTLS 0:35aa5be3b78d 67 mutls_err_t tls_record_init(tls_record_t* record, tls_socket_t* sock, uint8_t* buf, size_t buf_size)
MiniTLS 0:35aa5be3b78d 68 {
MiniTLS 0:35aa5be3b78d 69
MiniTLS 0:35aa5be3b78d 70 record->handshake_done = false;
MiniTLS 0:35aa5be3b78d 71
MiniTLS 0:35aa5be3b78d 72 //Open BSD socket
MiniTLS 0:35aa5be3b78d 73 record->socket_fd = socket_socket();
MiniTLS 0:35aa5be3b78d 74 if(record->socket_fd < 0)
MiniTLS 0:35aa5be3b78d 75 {
MiniTLS 0:35aa5be3b78d 76 ERR("Could not create socket descriptor");
MiniTLS 0:35aa5be3b78d 77 return MUTLS_ERR_SOCKET_ERROR;
MiniTLS 0:35aa5be3b78d 78 }
MiniTLS 0:35aa5be3b78d 79
MiniTLS 0:35aa5be3b78d 80 record->read_timeout = DEFAULT_READ_TIMEOUT;
MiniTLS 0:35aa5be3b78d 81 record->write_timeout = DEFAULT_WRITE_TIMEOUT;
MiniTLS 0:35aa5be3b78d 82
MiniTLS 0:35aa5be3b78d 83 if(buf_size >= TLS_DEFAULT_MAX_FRAGMENT_SIZE)
MiniTLS 0:35aa5be3b78d 84 {
MiniTLS 0:35aa5be3b78d 85 record->max_fragment_size = TLS_DEFAULT_MAX_FRAGMENT_SIZE;
MiniTLS 0:35aa5be3b78d 86 }
MiniTLS 0:35aa5be3b78d 87 else if( buf_size >= 4096 + TLS_ENCRYPTION_MAX_OVERHEAD )
MiniTLS 0:35aa5be3b78d 88 {
MiniTLS 0:35aa5be3b78d 89 record->max_fragment_size = 4096;
MiniTLS 0:35aa5be3b78d 90 }
MiniTLS 0:35aa5be3b78d 91 else if( buf_size >= 2048 + TLS_ENCRYPTION_MAX_OVERHEAD )
MiniTLS 0:35aa5be3b78d 92 {
MiniTLS 0:35aa5be3b78d 93 record->max_fragment_size = 2048;
MiniTLS 0:35aa5be3b78d 94 }
MiniTLS 0:35aa5be3b78d 95 else if( buf_size >= 1024 + TLS_ENCRYPTION_MAX_OVERHEAD )
MiniTLS 0:35aa5be3b78d 96 {
MiniTLS 0:35aa5be3b78d 97 record->max_fragment_size = 1024;
MiniTLS 0:35aa5be3b78d 98 }
MiniTLS 0:35aa5be3b78d 99 else if( buf_size >= 512 + TLS_ENCRYPTION_MAX_OVERHEAD )
MiniTLS 0:35aa5be3b78d 100 {
MiniTLS 0:35aa5be3b78d 101 record->max_fragment_size = 512;
MiniTLS 0:35aa5be3b78d 102 }
MiniTLS 0:35aa5be3b78d 103 else
MiniTLS 0:35aa5be3b78d 104 {
MiniTLS 0:35aa5be3b78d 105 ERR("Buffer is too small");
MiniTLS 0:35aa5be3b78d 106 return MUTLS_ERR_BUFFER_TOO_SMALL;
MiniTLS 0:35aa5be3b78d 107 }
MiniTLS 0:35aa5be3b78d 108
MiniTLS 0:35aa5be3b78d 109 DBG("Max fragment size: %d bytes", record->max_fragment_size);
MiniTLS 0:35aa5be3b78d 110
MiniTLS 0:35aa5be3b78d 111 if( (buf_size != TLS_DEFAULT_MAX_FRAGMENT_SIZE)
MiniTLS 0:35aa5be3b78d 112 && (buf_size != (record->max_fragment_size + TLS_ENCRYPTION_MAX_OVERHEAD)) )
MiniTLS 0:35aa5be3b78d 113 {
MiniTLS 0:35aa5be3b78d 114 WARN("Buffer size is not optimum");
MiniTLS 0:35aa5be3b78d 115 }
MiniTLS 0:35aa5be3b78d 116
MiniTLS 0:35aa5be3b78d 117 //Initialize with oldest protocol version by default (as recommended by RFC 5246's Annex E)
MiniTLS 0:35aa5be3b78d 118 #if MUTLS_CFG_PROTOCOL_SSL_3
MiniTLS 0:35aa5be3b78d 119 record->version.major = SSL_3_VERSION_MAJOR;
MiniTLS 0:35aa5be3b78d 120 record->version.minor = SSL_3_VERSION_MINOR;
MiniTLS 0:35aa5be3b78d 121 #elif MUTLS_CFG_PROTOCOL_TLS_1_0
MiniTLS 0:35aa5be3b78d 122 record->version.major = TLS_1_0_VERSION_MAJOR;
MiniTLS 0:35aa5be3b78d 123 record->version.minor = TLS_1_0_VERSION_MINOR;
MiniTLS 0:35aa5be3b78d 124 #elif MUTLS_CFG_PROTOCOL_TLS_1_1
MiniTLS 0:35aa5be3b78d 125 record->version.major = TLS_1_1_VERSION_MAJOR;
MiniTLS 0:35aa5be3b78d 126 record->version.minor = TLS_1_1_VERSION_MINOR;
MiniTLS 0:35aa5be3b78d 127 #elif MUTLS_CFG_PROTOCOL_TLS_1_2
MiniTLS 0:35aa5be3b78d 128 record->version.major = TLS_1_2_VERSION_MAJOR;
MiniTLS 0:35aa5be3b78d 129 record->version.minor = TLS_1_2_VERSION_MINOR;
MiniTLS 0:35aa5be3b78d 130 #else
MiniTLS 0:35aa5be3b78d 131 #error No SSL/TLS protocol version enabled
MiniTLS 0:35aa5be3b78d 132 #endif
MiniTLS 0:35aa5be3b78d 133
MiniTLS 0:35aa5be3b78d 134 buffer_init(&record->buffer, buf, buf_size);
MiniTLS 0:35aa5be3b78d 135
MiniTLS 0:35aa5be3b78d 136 record->tls_socket = sock;
MiniTLS 0:35aa5be3b78d 137
MiniTLS 0:35aa5be3b78d 138 //Init security
MiniTLS 0:35aa5be3b78d 139 record->security_rx_state = TLS_SECURITY_NONE;
MiniTLS 0:35aa5be3b78d 140 record->security_tx_state = TLS_SECURITY_NONE;
MiniTLS 0:35aa5be3b78d 141
MiniTLS 0:35aa5be3b78d 142 //Memset keys
MiniTLS 0:35aa5be3b78d 143 memset(&record->client_write_mac_key, 0, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 0:35aa5be3b78d 144 memset(&record->server_write_mac_key, 0, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 0:35aa5be3b78d 145 memset(&record->client_write_cipher_key, 0, AES_128_KEY_SIZE);
MiniTLS 0:35aa5be3b78d 146 memset(&record->server_write_cipher_key, 0, AES_128_KEY_SIZE);
MiniTLS 0:35aa5be3b78d 147
MiniTLS 0:35aa5be3b78d 148 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 149 }
MiniTLS 0:35aa5be3b78d 150
MiniTLS 0:35aa5be3b78d 151 void tls_record_set_protocol_version(tls_record_t* record, uint8_t major, uint8_t minor)
MiniTLS 0:35aa5be3b78d 152 {
MiniTLS 0:35aa5be3b78d 153 record->version.major = major;
MiniTLS 0:35aa5be3b78d 154 record->version.minor = minor;
MiniTLS 0:35aa5be3b78d 155 }
MiniTLS 0:35aa5be3b78d 156
MiniTLS 0:35aa5be3b78d 157 void tls_record_get_protocol_version(tls_record_t* record, uint8_t* major, uint8_t* minor)
MiniTLS 0:35aa5be3b78d 158 {
MiniTLS 0:35aa5be3b78d 159 *major = record->version.major;
MiniTLS 0:35aa5be3b78d 160 *minor = record->version.minor;
MiniTLS 0:35aa5be3b78d 161 }
MiniTLS 0:35aa5be3b78d 162
MiniTLS 0:35aa5be3b78d 163 mutls_err_t tls_record_change_cipher_spec(tls_record_t* record, bool tx_nrx)
MiniTLS 0:35aa5be3b78d 164 {
MiniTLS 0:35aa5be3b78d 165 if(tx_nrx)
MiniTLS 0:35aa5be3b78d 166 {
MiniTLS 0:35aa5be3b78d 167 if(record->security_tx_state == TLS_SECURITY_INTIALIZED)
MiniTLS 0:35aa5be3b78d 168 {
MiniTLS 0:35aa5be3b78d 169 record->security_tx_state = TLS_SECURITY_ACTIVE;
MiniTLS 0:35aa5be3b78d 170 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 171 }
MiniTLS 0:35aa5be3b78d 172 else
MiniTLS 0:35aa5be3b78d 173 {
MiniTLS 0:35aa5be3b78d 174 return MUTLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 0:35aa5be3b78d 175 }
MiniTLS 0:35aa5be3b78d 176 }
MiniTLS 0:35aa5be3b78d 177 else
MiniTLS 0:35aa5be3b78d 178 {
MiniTLS 0:35aa5be3b78d 179 if(record->security_rx_state == TLS_SECURITY_INTIALIZED)
MiniTLS 0:35aa5be3b78d 180 {
MiniTLS 0:35aa5be3b78d 181 record->security_rx_state = TLS_SECURITY_ACTIVE;
MiniTLS 0:35aa5be3b78d 182 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 183 }
MiniTLS 0:35aa5be3b78d 184 else
MiniTLS 0:35aa5be3b78d 185 {
MiniTLS 0:35aa5be3b78d 186 return MUTLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 0:35aa5be3b78d 187 }
MiniTLS 0:35aa5be3b78d 188 }
MiniTLS 0:35aa5be3b78d 189 }
MiniTLS 0:35aa5be3b78d 190
MiniTLS 0:35aa5be3b78d 191 bool tls_record_is_secure(tls_record_t* record)
MiniTLS 0:35aa5be3b78d 192 {
MiniTLS 0:35aa5be3b78d 193 if( record->security_tx_state != TLS_SECURITY_ACTIVE )
MiniTLS 0:35aa5be3b78d 194 {
MiniTLS 0:35aa5be3b78d 195 return false;
MiniTLS 0:35aa5be3b78d 196 }
MiniTLS 0:35aa5be3b78d 197 if( record->security_rx_state != TLS_SECURITY_ACTIVE )
MiniTLS 0:35aa5be3b78d 198 {
MiniTLS 0:35aa5be3b78d 199 return false;
MiniTLS 0:35aa5be3b78d 200 }
MiniTLS 0:35aa5be3b78d 201 return true;
MiniTLS 0:35aa5be3b78d 202 }
MiniTLS 0:35aa5be3b78d 203
MiniTLS 0:35aa5be3b78d 204 mutls_err_t tls_record_connect(tls_record_t* record, const char* hostname, uint16_t port)
MiniTLS 0:35aa5be3b78d 205 {
MiniTLS 0:35aa5be3b78d 206 DBG("Trying to connect to %s:%d", hostname, port);
MiniTLS 0:35aa5be3b78d 207
MiniTLS 0:35aa5be3b78d 208 int r = socket_connect(record->socket_fd, hostname, port);
MiniTLS 0:35aa5be3b78d 209 if(r < 0)
MiniTLS 0:35aa5be3b78d 210 {
MiniTLS 0:35aa5be3b78d 211 socket_close(record->socket_fd);
MiniTLS 0:35aa5be3b78d 212 record->socket_fd = -1;
MiniTLS 0:35aa5be3b78d 213 return MUTLS_ERR_SOCKET_ERROR;
MiniTLS 0:35aa5be3b78d 214 }
MiniTLS 0:35aa5be3b78d 215
MiniTLS 0:35aa5be3b78d 216 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 217 }
MiniTLS 0:35aa5be3b78d 218
MiniTLS 0:35aa5be3b78d 219 mutls_err_t tls_record_process(tls_record_t* record)
MiniTLS 0:35aa5be3b78d 220 {
MiniTLS 0:35aa5be3b78d 221 //Reset buffer length
MiniTLS 0:35aa5be3b78d 222 buffer_reset(&record->buffer);
MiniTLS 0:35aa5be3b78d 223
MiniTLS 0:35aa5be3b78d 224 //Read header
MiniTLS 0:35aa5be3b78d 225 mutls_err_t ret = record_socket_read(record, FRAGMENT_HEADER_SIZE);
MiniTLS 0:35aa5be3b78d 226 if(ret == MUTLS_ERR_SOCKET_CLOSED)
MiniTLS 0:35aa5be3b78d 227 {
MiniTLS 0:35aa5be3b78d 228 return MUTLS_ERR_SOCKET_CLOSED;
MiniTLS 0:35aa5be3b78d 229 }
MiniTLS 0:35aa5be3b78d 230 else if(ret)
MiniTLS 0:35aa5be3b78d 231 {
MiniTLS 0:35aa5be3b78d 232 ERR("Socket err %d", ret);
MiniTLS 0:35aa5be3b78d 233 tls_alert_send( record, TLS_ALERT_FATAL, INTERNAL_ERROR, &record->buffer);
MiniTLS 0:35aa5be3b78d 234 return ret;
MiniTLS 0:35aa5be3b78d 235 }
MiniTLS 0:35aa5be3b78d 236
MiniTLS 0:35aa5be3b78d 237 //Read version
MiniTLS 0:35aa5be3b78d 238 tls_fragment_header_t header;
MiniTLS 0:35aa5be3b78d 239
MiniTLS 0:35aa5be3b78d 240 header.type = buffer_nu8_read(&record->buffer);
MiniTLS 0:35aa5be3b78d 241 header.version.major = buffer_nu8_read(&record->buffer);
MiniTLS 0:35aa5be3b78d 242 header.version.minor = buffer_nu8_read(&record->buffer);
MiniTLS 0:35aa5be3b78d 243 header.length = buffer_nu16_read(&record->buffer);
MiniTLS 0:35aa5be3b78d 244
MiniTLS 0:35aa5be3b78d 245 #if 1 //TODO how to relax this?
MiniTLS 0:35aa5be3b78d 246 if( (header.version.major != record->version.major) || (header.version.minor != record->version.minor) )
MiniTLS 0:35aa5be3b78d 247 {
MiniTLS 0:35aa5be3b78d 248 ERR("Version mismatch");
MiniTLS 0:35aa5be3b78d 249 tls_alert_send( record, TLS_ALERT_FATAL, PROTOCOL_VERSION, &record->buffer);
MiniTLS 0:35aa5be3b78d 250 return MUTLS_ERR_PROTOCOL_VERSION;
MiniTLS 0:35aa5be3b78d 251 }
MiniTLS 0:35aa5be3b78d 252 #endif
MiniTLS 0:35aa5be3b78d 253 //Check content type
MiniTLS 0:35aa5be3b78d 254 //Check that encryption level is OK for this content type
MiniTLS 0:35aa5be3b78d 255 switch( header.type )
MiniTLS 0:35aa5be3b78d 256 {
MiniTLS 0:35aa5be3b78d 257 //All of these are OK in plain mode
MiniTLS 0:35aa5be3b78d 258 case TLS_CHANGE_CIPHER_SPEC:
MiniTLS 0:35aa5be3b78d 259 case TLS_ALERT:
MiniTLS 0:35aa5be3b78d 260 case TLS_HANDSHAKE:
MiniTLS 0:35aa5be3b78d 261 break;
MiniTLS 0:35aa5be3b78d 262 //This is only acceptable in ciphered mode:
MiniTLS 0:35aa5be3b78d 263 case TLS_APPLICATION_DATA:
MiniTLS 0:35aa5be3b78d 264 if( (!tls_record_is_secure(record)) || (!record->handshake_done) )
MiniTLS 0:35aa5be3b78d 265 {
MiniTLS 0:35aa5be3b78d 266 tls_alert_send( record, TLS_ALERT_FATAL, INSUFFICIENT_SECURITY, &record->buffer);
MiniTLS 0:35aa5be3b78d 267 return MUTLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 0:35aa5be3b78d 268 }
MiniTLS 0:35aa5be3b78d 269 break;
MiniTLS 0:35aa5be3b78d 270 default:
MiniTLS 0:35aa5be3b78d 271 tls_alert_send( record, TLS_ALERT_FATAL, ILLEGAL_PARAMETER, &record->buffer);
MiniTLS 0:35aa5be3b78d 272 return MUTLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 0:35aa5be3b78d 273 }
MiniTLS 0:35aa5be3b78d 274
MiniTLS 0:35aa5be3b78d 275 //Reset buffer
MiniTLS 0:35aa5be3b78d 276 buffer_reset(&record->buffer);
MiniTLS 0:35aa5be3b78d 277
MiniTLS 0:35aa5be3b78d 278 //Read payload
MiniTLS 0:35aa5be3b78d 279 ret = record_socket_read(record, header.length);
MiniTLS 0:35aa5be3b78d 280 if(ret)
MiniTLS 0:35aa5be3b78d 281 {
MiniTLS 0:35aa5be3b78d 282 ERR("Socket err %d", ret);
MiniTLS 0:35aa5be3b78d 283 tls_alert_send( record, TLS_ALERT_FATAL, INTERNAL_ERROR, &record->buffer);
MiniTLS 0:35aa5be3b78d 284 return ret;
MiniTLS 0:35aa5be3b78d 285 }
MiniTLS 0:35aa5be3b78d 286
MiniTLS 0:35aa5be3b78d 287 if( record->security_rx_state == TLS_SECURITY_ACTIVE )
MiniTLS 0:35aa5be3b78d 288 {
MiniTLS 0:35aa5be3b78d 289 DBG("IV + Ciphertext");
MiniTLS 0:35aa5be3b78d 290 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 0:35aa5be3b78d 291
MiniTLS 0:35aa5be3b78d 292 buffer_t buffer_iv_header;
MiniTLS 0:35aa5be3b78d 293 if( (buffer_length(&record->buffer) < 2*AES_128_BLOCK_SIZE) || ( (buffer_length(&record->buffer) % AES_128_BLOCK_SIZE) != 0 ) )
MiniTLS 0:35aa5be3b78d 294 {
MiniTLS 0:35aa5be3b78d 295 tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer );
MiniTLS 0:35aa5be3b78d 296 return MUTLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 0:35aa5be3b78d 297 }
MiniTLS 0:35aa5be3b78d 298 buffer_byref(&buffer_iv_header, buffer_current_read_position(&record->buffer), AES_128_BLOCK_SIZE); //Extract IV vector
MiniTLS 0:35aa5be3b78d 299 buffer_n_discard(&record->buffer, AES_128_BLOCK_SIZE);
MiniTLS 0:35aa5be3b78d 300
MiniTLS 0:35aa5be3b78d 301 //Decrypt message
MiniTLS 0:35aa5be3b78d 302 ret = crypto_aes_128_cbc_decrypt( &record->cipher_rx, &buffer_iv_header, &record->buffer );
MiniTLS 0:35aa5be3b78d 303 if(ret)
MiniTLS 0:35aa5be3b78d 304 {
MiniTLS 0:35aa5be3b78d 305 ERR("Failed to decipher, ret %d", ret);
MiniTLS 0:35aa5be3b78d 306 tls_alert_send( record, TLS_ALERT_FATAL, DECRYPT_ERROR, &record->buffer );
MiniTLS 0:35aa5be3b78d 307 return ret;
MiniTLS 0:35aa5be3b78d 308 }
MiniTLS 0:35aa5be3b78d 309
MiniTLS 0:35aa5be3b78d 310 DBG("Plaintext + MAC + padding + padding length");
MiniTLS 0:35aa5be3b78d 311 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 0:35aa5be3b78d 312
MiniTLS 0:35aa5be3b78d 313 //Check and remove padding
MiniTLS 0:35aa5be3b78d 314 size_t padding_length = *(buffer_current_write_position(&record->buffer) - 1);
MiniTLS 0:35aa5be3b78d 315
MiniTLS 0:35aa5be3b78d 316 if( padding_length + 1 > buffer_length(&record->buffer) )
MiniTLS 0:35aa5be3b78d 317 {
MiniTLS 0:35aa5be3b78d 318 ERR("Wrong padding length");
MiniTLS 0:35aa5be3b78d 319 tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer );
MiniTLS 0:35aa5be3b78d 320 return MUTLS_ERR_CRYPTO;
MiniTLS 0:35aa5be3b78d 321 }
MiniTLS 0:35aa5be3b78d 322
MiniTLS 0:35aa5be3b78d 323 int p;
MiniTLS 0:35aa5be3b78d 324 //Check each padding byte
MiniTLS 0:35aa5be3b78d 325 for(p = 0; p < padding_length; p++)
MiniTLS 0:35aa5be3b78d 326 {
MiniTLS 0:35aa5be3b78d 327 if( *(buffer_current_write_position(&record->buffer) - 1 - p) != padding_length )
MiniTLS 0:35aa5be3b78d 328 {
MiniTLS 0:35aa5be3b78d 329 ERR("Wrong padding");
MiniTLS 0:35aa5be3b78d 330 tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer );
MiniTLS 0:35aa5be3b78d 331 return MUTLS_ERR_CRYPTO;
MiniTLS 0:35aa5be3b78d 332 }
MiniTLS 0:35aa5be3b78d 333 }
MiniTLS 0:35aa5be3b78d 334
MiniTLS 0:35aa5be3b78d 335 //Remove trailing padding + padding length
MiniTLS 0:35aa5be3b78d 336 buffer_set_length(&record->buffer, buffer_length(&record->buffer) - 1 - padding_length);
MiniTLS 0:35aa5be3b78d 337
MiniTLS 0:35aa5be3b78d 338 DBG("Plaintext + MAC");
MiniTLS 0:35aa5be3b78d 339 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 0:35aa5be3b78d 340
MiniTLS 0:35aa5be3b78d 341 //Check MAC
MiniTLS 0:35aa5be3b78d 342 ret = tls_mac_check( record->server_write_mac_key, header.type, header.version, record->sequence_number_rx, &record->buffer );
MiniTLS 0:35aa5be3b78d 343 if(ret)
MiniTLS 0:35aa5be3b78d 344 {
MiniTLS 0:35aa5be3b78d 345 ERR("MAC Check failed, ret %d", ret);
MiniTLS 0:35aa5be3b78d 346 tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer );
MiniTLS 0:35aa5be3b78d 347 return ret;
MiniTLS 0:35aa5be3b78d 348 }
MiniTLS 0:35aa5be3b78d 349
MiniTLS 0:35aa5be3b78d 350 DBG("Plaintext");
MiniTLS 0:35aa5be3b78d 351 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 0:35aa5be3b78d 352
MiniTLS 0:35aa5be3b78d 353 //Increment seq number
MiniTLS 0:35aa5be3b78d 354 record->sequence_number_rx++;
MiniTLS 0:35aa5be3b78d 355 }
MiniTLS 0:35aa5be3b78d 356 else
MiniTLS 0:35aa5be3b78d 357 {
MiniTLS 0:35aa5be3b78d 358 //No security
MiniTLS 0:35aa5be3b78d 359 }
MiniTLS 0:35aa5be3b78d 360
MiniTLS 0:35aa5be3b78d 361 //Now dispatch depending on content type
MiniTLS 0:35aa5be3b78d 362 switch( header.type )
MiniTLS 0:35aa5be3b78d 363 {
MiniTLS 0:35aa5be3b78d 364 case TLS_CHANGE_CIPHER_SPEC:
MiniTLS 0:35aa5be3b78d 365 ret = tls_record_change_cipher_spec(record, false);
MiniTLS 0:35aa5be3b78d 366 if(ret)
MiniTLS 0:35aa5be3b78d 367 {
MiniTLS 0:35aa5be3b78d 368 ERR("Invalid change cipher spec request, ret %d", ret);
MiniTLS 0:35aa5be3b78d 369 tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer );
MiniTLS 0:35aa5be3b78d 370 return ret;
MiniTLS 0:35aa5be3b78d 371 }
MiniTLS 0:35aa5be3b78d 372 break;
MiniTLS 0:35aa5be3b78d 373 case TLS_ALERT:
MiniTLS 0:35aa5be3b78d 374 ret = tls_alert_process( record, &record->buffer );
MiniTLS 0:35aa5be3b78d 375 if(ret)
MiniTLS 0:35aa5be3b78d 376 {
MiniTLS 0:35aa5be3b78d 377 tls_record_close(record);
MiniTLS 0:35aa5be3b78d 378 //Close connection in any case
MiniTLS 0:35aa5be3b78d 379 if(ret == MUTLS_ERR_CONNECTION_CLOSED)
MiniTLS 0:35aa5be3b78d 380 {
MiniTLS 0:35aa5be3b78d 381 DBG("Connection closed by remote party");
MiniTLS 0:35aa5be3b78d 382 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 383 }
MiniTLS 0:35aa5be3b78d 384 //FIXME Do something
MiniTLS 0:35aa5be3b78d 385 ERR("Alert received, ret %d", ret);
MiniTLS 0:35aa5be3b78d 386 return ret;
MiniTLS 0:35aa5be3b78d 387 }
MiniTLS 0:35aa5be3b78d 388 break;
MiniTLS 0:35aa5be3b78d 389 case TLS_HANDSHAKE:
MiniTLS 0:35aa5be3b78d 390 if(/*(record->tls_socket->handshake != NULL) &&*/ !tls_handshake_is_done(&record->tls_socket->handshake))
MiniTLS 0:35aa5be3b78d 391 {
MiniTLS 0:35aa5be3b78d 392 ret = tls_handshake_process(&record->tls_socket->handshake, &record->buffer );
MiniTLS 0:35aa5be3b78d 393 if(ret)
MiniTLS 0:35aa5be3b78d 394 {
MiniTLS 0:35aa5be3b78d 395 ERR("Handshake process returned %d", ret);
MiniTLS 0:35aa5be3b78d 396 //TLS alert already sent by handshake function
MiniTLS 0:35aa5be3b78d 397 tls_handshake_clean(&record->tls_socket->handshake); //Cleanup handshake
MiniTLS 0:35aa5be3b78d 398 //record->tls_socket->handshake = NULL;
MiniTLS 0:35aa5be3b78d 399 return ret;
MiniTLS 0:35aa5be3b78d 400 }
MiniTLS 0:35aa5be3b78d 401 if(tls_handshake_is_done(&record->tls_socket->handshake))
MiniTLS 0:35aa5be3b78d 402 {
MiniTLS 0:35aa5be3b78d 403 tls_handshake_clean(&record->tls_socket->handshake); //Cleanup handshake
MiniTLS 0:35aa5be3b78d 404 //record->tls_socket->handshake = NULL;
MiniTLS 0:35aa5be3b78d 405 record->handshake_done = true; //Enable application data layer
MiniTLS 0:35aa5be3b78d 406 }
MiniTLS 0:35aa5be3b78d 407 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 408 }
MiniTLS 0:35aa5be3b78d 409 else
MiniTLS 0:35aa5be3b78d 410 {
MiniTLS 0:35aa5be3b78d 411 ERR("Unexpected handshake message, ret %d", ret);
MiniTLS 0:35aa5be3b78d 412 tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer );
MiniTLS 0:35aa5be3b78d 413 return ret;
MiniTLS 0:35aa5be3b78d 414 }
MiniTLS 0:35aa5be3b78d 415 case TLS_APPLICATION_DATA:
MiniTLS 0:35aa5be3b78d 416 //Pass message to socket layer
MiniTLS 0:35aa5be3b78d 417 return tls_socket_readable_callback(record->tls_socket, &record->buffer);
MiniTLS 0:35aa5be3b78d 418 default:
MiniTLS 0:35aa5be3b78d 419 //Has already been checked above
MiniTLS 0:35aa5be3b78d 420 return MUTLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 0:35aa5be3b78d 421 }
MiniTLS 0:35aa5be3b78d 422
MiniTLS 0:35aa5be3b78d 423 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 424 }
MiniTLS 0:35aa5be3b78d 425
MiniTLS 0:35aa5be3b78d 426 mutls_err_t tls_record_send(tls_record_t* record, tls_content_type_t content_type, buffer_t* payload)
MiniTLS 0:35aa5be3b78d 427 {
MiniTLS 0:35aa5be3b78d 428 mutls_err_t ret;
MiniTLS 0:35aa5be3b78d 429 int padding_item;
MiniTLS 0:35aa5be3b78d 430 /*
MiniTLS 0:35aa5be3b78d 431 struct {
MiniTLS 0:35aa5be3b78d 432 opaque IV[SecurityParameters.record_iv_length];
MiniTLS 0:35aa5be3b78d 433 block-ciphered struct {
MiniTLS 0:35aa5be3b78d 434 opaque content[TLSCompressed.length];
MiniTLS 0:35aa5be3b78d 435 opaque MAC[SecurityParameters.mac_length];
MiniTLS 0:35aa5be3b78d 436 uint8 padding[GenericBlockCipher.padding_length];
MiniTLS 0:35aa5be3b78d 437 uint8 padding_length;
MiniTLS 0:35aa5be3b78d 438 };
MiniTLS 0:35aa5be3b78d 439 } GenericBlockCipher;
MiniTLS 0:35aa5be3b78d 440 */
MiniTLS 0:35aa5be3b78d 441
MiniTLS 0:35aa5be3b78d 442 //Check content type
MiniTLS 0:35aa5be3b78d 443 //Check that encryption level is OK for this content type
MiniTLS 0:35aa5be3b78d 444 switch( content_type )
MiniTLS 0:35aa5be3b78d 445 {
MiniTLS 0:35aa5be3b78d 446 //All of these are OK in plain mode
MiniTLS 0:35aa5be3b78d 447 case TLS_CHANGE_CIPHER_SPEC:
MiniTLS 0:35aa5be3b78d 448 case TLS_ALERT:
MiniTLS 0:35aa5be3b78d 449 case TLS_HANDSHAKE:
MiniTLS 0:35aa5be3b78d 450 break;
MiniTLS 0:35aa5be3b78d 451 //This is only acceptable in ciphered mode:
MiniTLS 0:35aa5be3b78d 452 case TLS_APPLICATION_DATA:
MiniTLS 0:35aa5be3b78d 453 if( (!tls_record_is_secure(record)) || (!record->handshake_done) )
MiniTLS 0:35aa5be3b78d 454 {
MiniTLS 0:35aa5be3b78d 455 tls_alert_send( record, TLS_ALERT_FATAL, INSUFFICIENT_SECURITY, &record->buffer);
MiniTLS 0:35aa5be3b78d 456 return MUTLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 0:35aa5be3b78d 457 }
MiniTLS 0:35aa5be3b78d 458 break;
MiniTLS 0:35aa5be3b78d 459 default:
MiniTLS 0:35aa5be3b78d 460 tls_alert_send( record, TLS_ALERT_FATAL, ILLEGAL_PARAMETER, &record->buffer);
MiniTLS 0:35aa5be3b78d 461 return MUTLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 0:35aa5be3b78d 462 }
MiniTLS 0:35aa5be3b78d 463
MiniTLS 0:35aa5be3b78d 464 //Buffer must have enough space to add IV (head) + MAC (tail) + padding (tail)
MiniTLS 0:35aa5be3b78d 465
MiniTLS 0:35aa5be3b78d 466 buffer_t header_iv;
MiniTLS 0:35aa5be3b78d 467 uint8_t header_iv_data[AES_128_BLOCK_SIZE];
MiniTLS 0:35aa5be3b78d 468 if( record->security_tx_state == TLS_SECURITY_ACTIVE )
MiniTLS 0:35aa5be3b78d 469 {
MiniTLS 0:35aa5be3b78d 470 //FIXME generate a random IV
MiniTLS 0:35aa5be3b78d 471
MiniTLS 0:35aa5be3b78d 472 DBG("Plaintext");
MiniTLS 0:35aa5be3b78d 473 DBG_BLOCK(buffer_dump(payload);)
MiniTLS 0:35aa5be3b78d 474
MiniTLS 0:35aa5be3b78d 475 //Compute & append MAC
MiniTLS 0:35aa5be3b78d 476 DBG("Sequence number: %d", record->sequence_number_tx);
MiniTLS 0:35aa5be3b78d 477 ret = tls_mac_append( record->client_write_mac_key, content_type, record->version, record->sequence_number_tx, payload );
MiniTLS 0:35aa5be3b78d 478 if(ret)
MiniTLS 0:35aa5be3b78d 479 {
MiniTLS 0:35aa5be3b78d 480 ERR("Could not append MAC, ret %d", ret);
MiniTLS 0:35aa5be3b78d 481 return ret;
MiniTLS 0:35aa5be3b78d 482 }
MiniTLS 0:35aa5be3b78d 483
MiniTLS 0:35aa5be3b78d 484 //Increment sequence number
MiniTLS 0:35aa5be3b78d 485 record->sequence_number_tx++;
MiniTLS 0:35aa5be3b78d 486
MiniTLS 0:35aa5be3b78d 487 DBG("Plaintext + MAC");
MiniTLS 0:35aa5be3b78d 488 DBG_BLOCK(buffer_dump(payload);)
MiniTLS 0:35aa5be3b78d 489
MiniTLS 0:35aa5be3b78d 490 //Add padding
MiniTLS 0:35aa5be3b78d 491 size_t padding_length = AES_128_BLOCK_SIZE - (buffer_length(payload) % AES_128_BLOCK_SIZE) - 1;
MiniTLS 0:35aa5be3b78d 492 if(buffer_space(payload) < padding_length)
MiniTLS 0:35aa5be3b78d 493 {
MiniTLS 0:35aa5be3b78d 494 return MUTLS_ERR_BUFFER_TOO_SMALL;
MiniTLS 0:35aa5be3b78d 495 }
MiniTLS 0:35aa5be3b78d 496
MiniTLS 0:35aa5be3b78d 497 for(padding_item = 0; padding_item < padding_length; padding_item++)
MiniTLS 0:35aa5be3b78d 498 {
MiniTLS 0:35aa5be3b78d 499 buffer_nu8_write(payload, padding_length);
MiniTLS 0:35aa5be3b78d 500 }
MiniTLS 0:35aa5be3b78d 501
MiniTLS 0:35aa5be3b78d 502 buffer_nu8_write(payload, padding_length);
MiniTLS 0:35aa5be3b78d 503
MiniTLS 0:35aa5be3b78d 504 DBG("Plaintext + MAC + Padding + Padding Length");
MiniTLS 0:35aa5be3b78d 505 DBG_BLOCK(buffer_dump(payload);)
MiniTLS 0:35aa5be3b78d 506
MiniTLS 0:35aa5be3b78d 507 buffer_init( &header_iv, header_iv_data, AES_128_BLOCK_SIZE );
MiniTLS 0:35aa5be3b78d 508
MiniTLS 0:35aa5be3b78d 509 crypto_prng_get(record->tls_socket->mutls->prng, buffer_current_write_position(&header_iv), AES_128_BLOCK_SIZE);
MiniTLS 0:35aa5be3b78d 510 buffer_n_skip(&header_iv, AES_128_BLOCK_SIZE);
MiniTLS 0:35aa5be3b78d 511
MiniTLS 0:35aa5be3b78d 512 //Encrypt message
MiniTLS 0:35aa5be3b78d 513 ret = crypto_aes_128_cbc_encrypt( &record->cipher_tx, &header_iv, payload );
MiniTLS 0:35aa5be3b78d 514 if(ret)
MiniTLS 0:35aa5be3b78d 515 {
MiniTLS 0:35aa5be3b78d 516 ERR("Failed to encipher, ret %d", ret);
MiniTLS 0:35aa5be3b78d 517 return ret;
MiniTLS 0:35aa5be3b78d 518 }
MiniTLS 0:35aa5be3b78d 519
MiniTLS 0:35aa5be3b78d 520 DBG("Ciphertext");
MiniTLS 0:35aa5be3b78d 521 DBG_BLOCK(buffer_dump(payload);)
MiniTLS 0:35aa5be3b78d 522 }
MiniTLS 0:35aa5be3b78d 523 else
MiniTLS 0:35aa5be3b78d 524 {
MiniTLS 0:35aa5be3b78d 525 buffer_init( &header_iv, NULL, 0 ); //0 Length
MiniTLS 0:35aa5be3b78d 526 }
MiniTLS 0:35aa5be3b78d 527
MiniTLS 0:35aa5be3b78d 528 //Now send message header
MiniTLS 0:35aa5be3b78d 529 tls_fragment_header_t header;
MiniTLS 0:35aa5be3b78d 530 header.type = content_type;
MiniTLS 0:35aa5be3b78d 531 header.version.major = record->version.major;
MiniTLS 0:35aa5be3b78d 532 header.version.minor = record->version.minor;
MiniTLS 0:35aa5be3b78d 533 header.length = buffer_length( &header_iv ) + buffer_length(payload);
MiniTLS 0:35aa5be3b78d 534
MiniTLS 0:35aa5be3b78d 535 buffer_t header_fragment;
MiniTLS 0:35aa5be3b78d 536 uint8_t header_fragment_data[FRAGMENT_HEADER_SIZE];
MiniTLS 0:35aa5be3b78d 537
MiniTLS 0:35aa5be3b78d 538 buffer_init( &header_fragment, header_fragment_data, FRAGMENT_HEADER_SIZE );
MiniTLS 0:35aa5be3b78d 539
MiniTLS 0:35aa5be3b78d 540 buffer_nu8_write(&header_fragment, header.type);
MiniTLS 0:35aa5be3b78d 541 buffer_nu8_write(&header_fragment, header.version.major);
MiniTLS 0:35aa5be3b78d 542 buffer_nu8_write(&header_fragment, header.version.minor);
MiniTLS 0:35aa5be3b78d 543 buffer_nu16_write(&header_fragment, header.length);
MiniTLS 0:35aa5be3b78d 544
MiniTLS 0:35aa5be3b78d 545 //Send fragment header
MiniTLS 0:35aa5be3b78d 546 ret = record_socket_write(record, &header_fragment);
MiniTLS 0:35aa5be3b78d 547 if(ret)
MiniTLS 0:35aa5be3b78d 548 {
MiniTLS 0:35aa5be3b78d 549 return ret;
MiniTLS 0:35aa5be3b78d 550 }
MiniTLS 0:35aa5be3b78d 551
MiniTLS 0:35aa5be3b78d 552 //Send IV
MiniTLS 0:35aa5be3b78d 553 ret = record_socket_write(record, &header_iv);
MiniTLS 0:35aa5be3b78d 554 if(ret)
MiniTLS 0:35aa5be3b78d 555 {
MiniTLS 0:35aa5be3b78d 556 return ret;
MiniTLS 0:35aa5be3b78d 557 }
MiniTLS 0:35aa5be3b78d 558
MiniTLS 0:35aa5be3b78d 559 //Send payload
MiniTLS 0:35aa5be3b78d 560 ret = record_socket_write(record, payload);
MiniTLS 0:35aa5be3b78d 561 if(ret)
MiniTLS 0:35aa5be3b78d 562 {
MiniTLS 0:35aa5be3b78d 563 return ret;
MiniTLS 0:35aa5be3b78d 564 }
MiniTLS 0:35aa5be3b78d 565
MiniTLS 0:35aa5be3b78d 566 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 567 }
MiniTLS 0:35aa5be3b78d 568
MiniTLS 0:35aa5be3b78d 569 mutls_err_t tls_record_set_keys(tls_record_t* record, tls_security_type_t security, const uint8_t* client_write_mac_key, const uint8_t* server_write_mac_key,
MiniTLS 0:35aa5be3b78d 570 const uint8_t* client_write_cipher_key, const uint8_t* server_write_cipher_key)
MiniTLS 0:35aa5be3b78d 571 {
MiniTLS 0:35aa5be3b78d 572 if(security != TLS_SECURITY_TYPE_AES_128_CBC_SHA)
MiniTLS 0:35aa5be3b78d 573 {
MiniTLS 0:35aa5be3b78d 574 return MUTLS_ERR_NOT_IMPLEMENTED;
MiniTLS 0:35aa5be3b78d 575 }
MiniTLS 0:35aa5be3b78d 576
MiniTLS 0:35aa5be3b78d 577 //Copy keys
MiniTLS 0:35aa5be3b78d 578 memcpy(&record->client_write_mac_key, client_write_mac_key, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 0:35aa5be3b78d 579 memcpy(&record->server_write_mac_key, server_write_mac_key, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 0:35aa5be3b78d 580 memcpy(&record->client_write_cipher_key, client_write_cipher_key, AES_128_KEY_SIZE);
MiniTLS 0:35aa5be3b78d 581 memcpy(&record->server_write_cipher_key, server_write_cipher_key, AES_128_KEY_SIZE);
MiniTLS 0:35aa5be3b78d 582
MiniTLS 0:35aa5be3b78d 583 //Intialize cipher
MiniTLS 0:35aa5be3b78d 584
MiniTLS 0:35aa5be3b78d 585 record->sequence_number_tx = 0;
MiniTLS 0:35aa5be3b78d 586 record->sequence_number_rx = 0;
MiniTLS 0:35aa5be3b78d 587
MiniTLS 0:35aa5be3b78d 588 crypto_aes_128_init(&record->cipher_tx, record->client_write_cipher_key, expand_encryption_key);
MiniTLS 0:35aa5be3b78d 589 crypto_aes_128_init(&record->cipher_rx, record->server_write_cipher_key, expand_decryption_key);
MiniTLS 0:35aa5be3b78d 590
MiniTLS 0:35aa5be3b78d 591 record->security_tx_state = TLS_SECURITY_INTIALIZED;
MiniTLS 0:35aa5be3b78d 592 record->security_rx_state = TLS_SECURITY_INTIALIZED;
MiniTLS 0:35aa5be3b78d 593
MiniTLS 0:35aa5be3b78d 594 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 595 }
MiniTLS 0:35aa5be3b78d 596
MiniTLS 0:35aa5be3b78d 597 mutls_err_t tls_record_close(tls_record_t* record)
MiniTLS 0:35aa5be3b78d 598 {
MiniTLS 0:35aa5be3b78d 599 if(record->socket_fd < 0) //Already closed
MiniTLS 0:35aa5be3b78d 600 {
MiniTLS 0:35aa5be3b78d 601 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 602 }
MiniTLS 0:35aa5be3b78d 603
MiniTLS 0:35aa5be3b78d 604 //Don't really care about the return
MiniTLS 0:35aa5be3b78d 605 tls_alert_send(record, TLS_ALERT_WARNING, CLOSE_NOTIFY, &record->buffer);
MiniTLS 0:35aa5be3b78d 606
MiniTLS 0:35aa5be3b78d 607 //Close socket
MiniTLS 0:35aa5be3b78d 608 socket_close(record->socket_fd);
MiniTLS 0:35aa5be3b78d 609 record->socket_fd = -1;
MiniTLS 0:35aa5be3b78d 610
MiniTLS 0:35aa5be3b78d 611 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 612 }
MiniTLS 0:35aa5be3b78d 613
MiniTLS 0:35aa5be3b78d 614 mutls_err_t tls_record_set_read_timeout(tls_record_t* record, int timeout)
MiniTLS 0:35aa5be3b78d 615 {
MiniTLS 0:35aa5be3b78d 616 record->read_timeout = timeout;
MiniTLS 0:35aa5be3b78d 617
MiniTLS 0:35aa5be3b78d 618 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 619 }
MiniTLS 0:35aa5be3b78d 620
MiniTLS 0:35aa5be3b78d 621 mutls_err_t tls_record_set_write_timeout(tls_record_t* record, int timeout)
MiniTLS 0:35aa5be3b78d 622 {
MiniTLS 0:35aa5be3b78d 623 record->write_timeout = timeout;
MiniTLS 0:35aa5be3b78d 624
MiniTLS 0:35aa5be3b78d 625 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 626 }
MiniTLS 0:35aa5be3b78d 627
MiniTLS 0:35aa5be3b78d 628 mutls_err_t record_wait_readable(tls_record_t* record)
MiniTLS 0:35aa5be3b78d 629 {
MiniTLS 0:35aa5be3b78d 630 if(record->socket_fd < 0)
MiniTLS 0:35aa5be3b78d 631 {
MiniTLS 0:35aa5be3b78d 632 return MUTLS_ERR_SOCKET_CLOSED;
MiniTLS 0:35aa5be3b78d 633 }
MiniTLS 0:35aa5be3b78d 634
MiniTLS 0:35aa5be3b78d 635 //Wait for record to be readable
MiniTLS 0:35aa5be3b78d 636 int ret = socket_wait_readable(record->socket_fd, record->read_timeout );
MiniTLS 0:35aa5be3b78d 637 if( ret < 0 )
MiniTLS 0:35aa5be3b78d 638 {
MiniTLS 0:35aa5be3b78d 639 //Timeout
MiniTLS 0:35aa5be3b78d 640 return MUTLS_ERR_TIMEOUT;
MiniTLS 0:35aa5be3b78d 641 }
MiniTLS 0:35aa5be3b78d 642 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 643 }
MiniTLS 0:35aa5be3b78d 644
MiniTLS 0:35aa5be3b78d 645 mutls_err_t record_wait_writeable(tls_record_t* record)
MiniTLS 0:35aa5be3b78d 646 {
MiniTLS 0:35aa5be3b78d 647 if(record->socket_fd < 0)
MiniTLS 0:35aa5be3b78d 648 {
MiniTLS 0:35aa5be3b78d 649 return MUTLS_ERR_SOCKET_CLOSED;
MiniTLS 0:35aa5be3b78d 650 }
MiniTLS 0:35aa5be3b78d 651
MiniTLS 0:35aa5be3b78d 652 //Wait for record to be writeable
MiniTLS 0:35aa5be3b78d 653 int ret = socket_wait_writeable(record->socket_fd, record->write_timeout );
MiniTLS 0:35aa5be3b78d 654 if( ret < 0 )
MiniTLS 0:35aa5be3b78d 655 {
MiniTLS 0:35aa5be3b78d 656 //Timeout
MiniTLS 0:35aa5be3b78d 657 return MUTLS_ERR_TIMEOUT;
MiniTLS 0:35aa5be3b78d 658 }
MiniTLS 0:35aa5be3b78d 659 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 660 }
MiniTLS 0:35aa5be3b78d 661
MiniTLS 0:35aa5be3b78d 662 mutls_err_t record_socket_read(tls_record_t* record, size_t size)
MiniTLS 0:35aa5be3b78d 663 {
MiniTLS 0:35aa5be3b78d 664 mutls_err_t ret;
MiniTLS 0:35aa5be3b78d 665 if(record->socket_fd < 0)
MiniTLS 0:35aa5be3b78d 666 {
MiniTLS 0:35aa5be3b78d 667 return MUTLS_ERR_SOCKET_CLOSED;
MiniTLS 0:35aa5be3b78d 668 }
MiniTLS 0:35aa5be3b78d 669
MiniTLS 0:35aa5be3b78d 670 DBG("Trying to read %d bytes", size);
MiniTLS 0:35aa5be3b78d 671 while(size > 0)
MiniTLS 0:35aa5be3b78d 672 {
MiniTLS 0:35aa5be3b78d 673 //Read Fragment length
MiniTLS 0:35aa5be3b78d 674 if( buffer_space(&record->buffer) < size )
MiniTLS 0:35aa5be3b78d 675 {
MiniTLS 0:35aa5be3b78d 676 ERR("Won't be able to read packet (%d bytes to read - %d bytes of space)", size, buffer_space(&record->buffer));
MiniTLS 0:35aa5be3b78d 677 return MUTLS_ERR_BUFFER_TOO_SMALL;
MiniTLS 0:35aa5be3b78d 678 }
MiniTLS 0:35aa5be3b78d 679
MiniTLS 0:35aa5be3b78d 680 ret = record_wait_readable(record);
MiniTLS 0:35aa5be3b78d 681 if(ret)
MiniTLS 0:35aa5be3b78d 682 {
MiniTLS 0:35aa5be3b78d 683 ERR("Timeout");
MiniTLS 0:35aa5be3b78d 684 return ret;
MiniTLS 0:35aa5be3b78d 685 }
MiniTLS 0:35aa5be3b78d 686
MiniTLS 0:35aa5be3b78d 687 int count = socket_recv(record->socket_fd, buffer_current_write_position(&record->buffer), size - buffer_length(&record->buffer));
MiniTLS 0:35aa5be3b78d 688 if( count > 0 )
MiniTLS 0:35aa5be3b78d 689 {
MiniTLS 0:35aa5be3b78d 690 buffer_n_skip(&record->buffer, count);
MiniTLS 0:35aa5be3b78d 691 size -= count;
MiniTLS 0:35aa5be3b78d 692 }
MiniTLS 0:35aa5be3b78d 693 else if( count == 0 )
MiniTLS 0:35aa5be3b78d 694 {
MiniTLS 0:35aa5be3b78d 695 WARN("Socket closed");
MiniTLS 0:35aa5be3b78d 696 return MUTLS_ERR_SOCKET_CLOSED;
MiniTLS 0:35aa5be3b78d 697 }
MiniTLS 0:35aa5be3b78d 698 else
MiniTLS 0:35aa5be3b78d 699 {
MiniTLS 0:35aa5be3b78d 700 ERR("Error (returned %d)", count);
MiniTLS 0:35aa5be3b78d 701 return MUTLS_ERR_SOCKET_ERROR;
MiniTLS 0:35aa5be3b78d 702 }
MiniTLS 0:35aa5be3b78d 703 }
MiniTLS 0:35aa5be3b78d 704
MiniTLS 0:35aa5be3b78d 705 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 0:35aa5be3b78d 706
MiniTLS 0:35aa5be3b78d 707 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 708 }
MiniTLS 0:35aa5be3b78d 709
MiniTLS 0:35aa5be3b78d 710 mutls_err_t record_socket_write(tls_record_t* record, buffer_t* data)
MiniTLS 0:35aa5be3b78d 711 {
MiniTLS 0:35aa5be3b78d 712 mutls_err_t ret;
MiniTLS 0:35aa5be3b78d 713 if(record->socket_fd < 0)
MiniTLS 0:35aa5be3b78d 714 {
MiniTLS 0:35aa5be3b78d 715 return MUTLS_ERR_SOCKET_CLOSED;
MiniTLS 0:35aa5be3b78d 716 }
MiniTLS 0:35aa5be3b78d 717
MiniTLS 0:35aa5be3b78d 718 DBG("Trying to write %d bytes", buffer_length(data));
MiniTLS 0:35aa5be3b78d 719 DBG_BLOCK(buffer_dump(data);)
MiniTLS 0:35aa5be3b78d 720 while(buffer_length(data) > 0)
MiniTLS 0:35aa5be3b78d 721 {
MiniTLS 0:35aa5be3b78d 722 ret = record_wait_writeable(record);
MiniTLS 0:35aa5be3b78d 723 if(ret)
MiniTLS 0:35aa5be3b78d 724 {
MiniTLS 0:35aa5be3b78d 725 ERR("Timeout");
MiniTLS 0:35aa5be3b78d 726 return ret;
MiniTLS 0:35aa5be3b78d 727 }
MiniTLS 0:35aa5be3b78d 728
MiniTLS 0:35aa5be3b78d 729 int count = socket_send(record->socket_fd, buffer_current_read_position(data), buffer_length(data));
MiniTLS 0:35aa5be3b78d 730 if( count > 0 )
MiniTLS 0:35aa5be3b78d 731 {
MiniTLS 0:35aa5be3b78d 732 buffer_n_discard(data, count);
MiniTLS 0:35aa5be3b78d 733 }
MiniTLS 0:35aa5be3b78d 734 else if( count == 0 )
MiniTLS 0:35aa5be3b78d 735 {
MiniTLS 0:35aa5be3b78d 736 WARN("Socket closed");
MiniTLS 0:35aa5be3b78d 737 return MUTLS_ERR_SOCKET_CLOSED;
MiniTLS 0:35aa5be3b78d 738 }
MiniTLS 0:35aa5be3b78d 739 else
MiniTLS 0:35aa5be3b78d 740 {
MiniTLS 0:35aa5be3b78d 741 ERR("Error (returned %d)", count);
MiniTLS 0:35aa5be3b78d 742 return MUTLS_ERR_SOCKET_ERROR;
MiniTLS 0:35aa5be3b78d 743 }
MiniTLS 0:35aa5be3b78d 744 }
MiniTLS 0:35aa5be3b78d 745 DBG("Done");
MiniTLS 0:35aa5be3b78d 746 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 747 }
MiniTLS 0:35aa5be3b78d 748
MiniTLS 0:35aa5be3b78d 749
MiniTLS 0:35aa5be3b78d 750 mutls_err_t tls_mac_append( const uint8_t* key, tls_content_type_t content_type, tls_protocol_version_t version,
MiniTLS 0:35aa5be3b78d 751 uint64_t sequence_number, buffer_t* buffer )
MiniTLS 0:35aa5be3b78d 752 {
MiniTLS 0:35aa5be3b78d 753 crypto_hmac_sha1_t mac;
MiniTLS 0:35aa5be3b78d 754 crypto_hmac_sha1_init(&mac, key, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 0:35aa5be3b78d 755
MiniTLS 0:35aa5be3b78d 756 if( buffer_space(buffer) < HMAC_SHA1_SIZE )
MiniTLS 0:35aa5be3b78d 757 {
MiniTLS 0:35aa5be3b78d 758 return MUTLS_ERR_BUFFER_TOO_SMALL;
MiniTLS 0:35aa5be3b78d 759 }
MiniTLS 0:35aa5be3b78d 760
MiniTLS 0:35aa5be3b78d 761 uint8_t header_buf[13];
MiniTLS 0:35aa5be3b78d 762 buffer_t header;
MiniTLS 0:35aa5be3b78d 763
MiniTLS 0:35aa5be3b78d 764 buffer_init(&header, header_buf, 13);
MiniTLS 0:35aa5be3b78d 765
MiniTLS 0:35aa5be3b78d 766 buffer_nu64_write(&header, sequence_number);
MiniTLS 0:35aa5be3b78d 767
MiniTLS 0:35aa5be3b78d 768 buffer_nu8_write(&header, content_type);
MiniTLS 0:35aa5be3b78d 769
MiniTLS 0:35aa5be3b78d 770 buffer_nu8_write(&header, version.major);
MiniTLS 0:35aa5be3b78d 771 buffer_nu8_write(&header, version.minor);
MiniTLS 0:35aa5be3b78d 772
MiniTLS 0:35aa5be3b78d 773 buffer_nu16_write(&header, buffer_length(buffer));
MiniTLS 0:35aa5be3b78d 774
MiniTLS 0:35aa5be3b78d 775 crypto_hmac_sha1_update(&mac, header_buf, 13);
MiniTLS 0:35aa5be3b78d 776 crypto_hmac_sha1_update(&mac, buffer_current_read_position(buffer), buffer_length(buffer));
MiniTLS 0:35aa5be3b78d 777 crypto_hmac_sha1_end(&mac, buffer_current_write_position(buffer));
MiniTLS 0:35aa5be3b78d 778 buffer_n_skip(buffer, HMAC_SHA1_SIZE);
MiniTLS 0:35aa5be3b78d 779
MiniTLS 0:35aa5be3b78d 780 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 781 }
MiniTLS 0:35aa5be3b78d 782
MiniTLS 0:35aa5be3b78d 783 mutls_err_t tls_mac_check( const uint8_t* key, tls_content_type_t content_type, tls_protocol_version_t version,
MiniTLS 0:35aa5be3b78d 784 uint64_t sequence_number, buffer_t* buffer )
MiniTLS 0:35aa5be3b78d 785 {
MiniTLS 0:35aa5be3b78d 786 crypto_hmac_sha1_t mac;
MiniTLS 0:35aa5be3b78d 787 crypto_hmac_sha1_init(&mac, key, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 0:35aa5be3b78d 788
MiniTLS 0:35aa5be3b78d 789 if( buffer_length(buffer) < HMAC_SHA1_SIZE )
MiniTLS 0:35aa5be3b78d 790 {
MiniTLS 0:35aa5be3b78d 791 return MUTLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 0:35aa5be3b78d 792 }
MiniTLS 0:35aa5be3b78d 793
MiniTLS 0:35aa5be3b78d 794 size_t data_offset = buffer_get_read_offset(buffer);
MiniTLS 0:35aa5be3b78d 795 size_t data_length = buffer_length(buffer) - HMAC_SHA1_SIZE;
MiniTLS 0:35aa5be3b78d 796
MiniTLS 0:35aa5be3b78d 797 uint8_t check[HMAC_SHA1_SIZE];
MiniTLS 0:35aa5be3b78d 798
MiniTLS 0:35aa5be3b78d 799 uint8_t header_buf[13];
MiniTLS 0:35aa5be3b78d 800 buffer_t header;
MiniTLS 0:35aa5be3b78d 801
MiniTLS 0:35aa5be3b78d 802 buffer_init(&header, header_buf, 13);
MiniTLS 0:35aa5be3b78d 803
MiniTLS 0:35aa5be3b78d 804 buffer_nu64_write(&header, sequence_number);
MiniTLS 0:35aa5be3b78d 805
MiniTLS 0:35aa5be3b78d 806 buffer_nu8_write(&header, content_type);
MiniTLS 0:35aa5be3b78d 807
MiniTLS 0:35aa5be3b78d 808 buffer_nu8_write(&header, version.major);
MiniTLS 0:35aa5be3b78d 809 buffer_nu8_write(&header, version.minor);
MiniTLS 0:35aa5be3b78d 810
MiniTLS 0:35aa5be3b78d 811 buffer_nu16_write(&header, data_length);
MiniTLS 0:35aa5be3b78d 812
MiniTLS 0:35aa5be3b78d 813 crypto_hmac_sha1_update(&mac, header_buf, 13);
MiniTLS 0:35aa5be3b78d 814 crypto_hmac_sha1_update(&mac, buffer_current_read_position(buffer), data_length);
MiniTLS 0:35aa5be3b78d 815 buffer_n_discard(buffer, data_length);
MiniTLS 0:35aa5be3b78d 816 crypto_hmac_sha1_end(&mac, check);
MiniTLS 0:35aa5be3b78d 817
MiniTLS 0:35aa5be3b78d 818 if( memcmp(buffer_current_read_position(buffer), check, HMAC_SHA1_SIZE) != 0 )
MiniTLS 0:35aa5be3b78d 819 {
MiniTLS 0:35aa5be3b78d 820 ERR("MAC differs; computed MAC was:");
MiniTLS 0:35aa5be3b78d 821
MiniTLS 0:35aa5be3b78d 822 buffer_t computed_mac;
MiniTLS 0:35aa5be3b78d 823 buffer_byref(&computed_mac, check, HMAC_SHA1_SIZE);
MiniTLS 0:35aa5be3b78d 824 DBG_BLOCK(buffer_dump(&computed_mac);)
MiniTLS 0:35aa5be3b78d 825
MiniTLS 0:35aa5be3b78d 826 return MUTLS_ERR_WRONG_MAC;
MiniTLS 0:35aa5be3b78d 827 }
MiniTLS 0:35aa5be3b78d 828
MiniTLS 0:35aa5be3b78d 829 //Reset buffer position and discard MAC
MiniTLS 0:35aa5be3b78d 830 buffer_set_read_offset(buffer, data_offset);
MiniTLS 0:35aa5be3b78d 831 buffer_set_length(buffer, data_length);
MiniTLS 0:35aa5be3b78d 832
MiniTLS 0:35aa5be3b78d 833 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 834 }
MiniTLS 0:35aa5be3b78d 835
MiniTLS 0:35aa5be3b78d 836
MiniTLS 0:35aa5be3b78d 837
MiniTLS 0:35aa5be3b78d 838