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:
Mon Jun 09 14:57:54 2014 +0000
Revision:
2:527a66d0a1a9
Child:
3:eb324ffffd2b
Change name to MiniTLS and added doc

Who changed what in which revision?

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