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.
tls/tls_record.c@0:35aa5be3b78d, 2014-06-06 (annotated)
- Committer:
- MiniTLS
- Date:
- Fri Jun 06 10:49:02 2014 +0000
- Revision:
- 0:35aa5be3b78d
Initial commit
Who changed what in which revision?
User | Revision | Line number | New 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 |