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:
Tue Jun 10 14:22:36 2014 +0000
Revision:
3:eb324ffffd2b
Parent:
2:527a66d0a1a9
Fixes for mbed

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 3:eb324ffffd2b 25 #define __DEBUG__ 4
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 3:eb324ffffd2b 141 record->security_type = TLS_SECURITY_TYPE_NULL_NULL_NULL;
MiniTLS 2:527a66d0a1a9 142
MiniTLS 2:527a66d0a1a9 143 //Memset keys
MiniTLS 2:527a66d0a1a9 144 memset(&record->client_write_mac_key, 0, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 2:527a66d0a1a9 145 memset(&record->server_write_mac_key, 0, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 2:527a66d0a1a9 146 memset(&record->client_write_cipher_key, 0, AES_128_KEY_SIZE);
MiniTLS 2:527a66d0a1a9 147 memset(&record->server_write_cipher_key, 0, AES_128_KEY_SIZE);
MiniTLS 2:527a66d0a1a9 148
MiniTLS 2:527a66d0a1a9 149 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 150 }
MiniTLS 2:527a66d0a1a9 151
MiniTLS 2:527a66d0a1a9 152 void tls_record_set_protocol_version(tls_record_t* record, uint8_t major, uint8_t minor)
MiniTLS 2:527a66d0a1a9 153 {
MiniTLS 2:527a66d0a1a9 154 record->version.major = major;
MiniTLS 2:527a66d0a1a9 155 record->version.minor = minor;
MiniTLS 2:527a66d0a1a9 156 }
MiniTLS 2:527a66d0a1a9 157
MiniTLS 2:527a66d0a1a9 158 void tls_record_get_protocol_version(tls_record_t* record, uint8_t* major, uint8_t* minor)
MiniTLS 2:527a66d0a1a9 159 {
MiniTLS 2:527a66d0a1a9 160 *major = record->version.major;
MiniTLS 2:527a66d0a1a9 161 *minor = record->version.minor;
MiniTLS 2:527a66d0a1a9 162 }
MiniTLS 2:527a66d0a1a9 163
MiniTLS 2:527a66d0a1a9 164 minitls_err_t tls_record_change_cipher_spec(tls_record_t* record, bool tx_nrx)
MiniTLS 2:527a66d0a1a9 165 {
MiniTLS 2:527a66d0a1a9 166 if(tx_nrx)
MiniTLS 2:527a66d0a1a9 167 {
MiniTLS 2:527a66d0a1a9 168 if(record->security_tx_state == TLS_SECURITY_INTIALIZED)
MiniTLS 2:527a66d0a1a9 169 {
MiniTLS 2:527a66d0a1a9 170 record->security_tx_state = TLS_SECURITY_ACTIVE;
MiniTLS 2:527a66d0a1a9 171 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 172 }
MiniTLS 2:527a66d0a1a9 173 else
MiniTLS 2:527a66d0a1a9 174 {
MiniTLS 2:527a66d0a1a9 175 return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 2:527a66d0a1a9 176 }
MiniTLS 2:527a66d0a1a9 177 }
MiniTLS 2:527a66d0a1a9 178 else
MiniTLS 2:527a66d0a1a9 179 {
MiniTLS 2:527a66d0a1a9 180 if(record->security_rx_state == TLS_SECURITY_INTIALIZED)
MiniTLS 2:527a66d0a1a9 181 {
MiniTLS 2:527a66d0a1a9 182 record->security_rx_state = TLS_SECURITY_ACTIVE;
MiniTLS 2:527a66d0a1a9 183 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 184 }
MiniTLS 2:527a66d0a1a9 185 else
MiniTLS 2:527a66d0a1a9 186 {
MiniTLS 2:527a66d0a1a9 187 return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 2:527a66d0a1a9 188 }
MiniTLS 2:527a66d0a1a9 189 }
MiniTLS 2:527a66d0a1a9 190 }
MiniTLS 2:527a66d0a1a9 191
MiniTLS 2:527a66d0a1a9 192 bool tls_record_is_secure(tls_record_t* record)
MiniTLS 2:527a66d0a1a9 193 {
MiniTLS 2:527a66d0a1a9 194 if( record->security_tx_state != TLS_SECURITY_ACTIVE )
MiniTLS 2:527a66d0a1a9 195 {
MiniTLS 2:527a66d0a1a9 196 return false;
MiniTLS 2:527a66d0a1a9 197 }
MiniTLS 2:527a66d0a1a9 198 if( record->security_rx_state != TLS_SECURITY_ACTIVE )
MiniTLS 2:527a66d0a1a9 199 {
MiniTLS 2:527a66d0a1a9 200 return false;
MiniTLS 2:527a66d0a1a9 201 }
MiniTLS 2:527a66d0a1a9 202 return true;
MiniTLS 2:527a66d0a1a9 203 }
MiniTLS 2:527a66d0a1a9 204
MiniTLS 2:527a66d0a1a9 205 minitls_err_t tls_record_connect(tls_record_t* record, const char* hostname, uint16_t port)
MiniTLS 2:527a66d0a1a9 206 {
MiniTLS 2:527a66d0a1a9 207 DBG("Trying to connect to %s:%d", hostname, port);
MiniTLS 2:527a66d0a1a9 208
MiniTLS 2:527a66d0a1a9 209 int r = socket_connect(record->socket_fd, hostname, port);
MiniTLS 2:527a66d0a1a9 210 if(r < 0)
MiniTLS 2:527a66d0a1a9 211 {
MiniTLS 2:527a66d0a1a9 212 socket_close(record->socket_fd);
MiniTLS 2:527a66d0a1a9 213 record->socket_fd = -1;
MiniTLS 2:527a66d0a1a9 214 return MINITLS_ERR_SOCKET_ERROR;
MiniTLS 2:527a66d0a1a9 215 }
MiniTLS 2:527a66d0a1a9 216
MiniTLS 2:527a66d0a1a9 217 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 218 }
MiniTLS 2:527a66d0a1a9 219
MiniTLS 2:527a66d0a1a9 220 minitls_err_t tls_record_process(tls_record_t* record)
MiniTLS 2:527a66d0a1a9 221 {
MiniTLS 2:527a66d0a1a9 222 //Reset buffer length
MiniTLS 2:527a66d0a1a9 223 buffer_reset(&record->buffer);
MiniTLS 2:527a66d0a1a9 224
MiniTLS 2:527a66d0a1a9 225 //Read header
MiniTLS 2:527a66d0a1a9 226 minitls_err_t ret = record_socket_read(record, FRAGMENT_HEADER_SIZE);
MiniTLS 2:527a66d0a1a9 227 if(ret == MINITLS_ERR_SOCKET_CLOSED)
MiniTLS 2:527a66d0a1a9 228 {
MiniTLS 2:527a66d0a1a9 229 return MINITLS_ERR_SOCKET_CLOSED;
MiniTLS 2:527a66d0a1a9 230 }
MiniTLS 2:527a66d0a1a9 231 else if(ret)
MiniTLS 2:527a66d0a1a9 232 {
MiniTLS 2:527a66d0a1a9 233 ERR("Socket err %d", ret);
MiniTLS 2:527a66d0a1a9 234 tls_alert_send( record, TLS_ALERT_FATAL, INTERNAL_ERROR, &record->buffer);
MiniTLS 2:527a66d0a1a9 235 return ret;
MiniTLS 2:527a66d0a1a9 236 }
MiniTLS 2:527a66d0a1a9 237
MiniTLS 2:527a66d0a1a9 238 //Read version
MiniTLS 2:527a66d0a1a9 239 tls_fragment_header_t header;
MiniTLS 2:527a66d0a1a9 240
MiniTLS 2:527a66d0a1a9 241 header.type = buffer_nu8_read(&record->buffer);
MiniTLS 2:527a66d0a1a9 242 header.version.major = buffer_nu8_read(&record->buffer);
MiniTLS 2:527a66d0a1a9 243 header.version.minor = buffer_nu8_read(&record->buffer);
MiniTLS 2:527a66d0a1a9 244 header.length = buffer_nu16_read(&record->buffer);
MiniTLS 2:527a66d0a1a9 245
MiniTLS 2:527a66d0a1a9 246 #if 1 //TODO how to relax this?
MiniTLS 2:527a66d0a1a9 247 if( (header.version.major != record->version.major) || (header.version.minor != record->version.minor) )
MiniTLS 2:527a66d0a1a9 248 {
MiniTLS 2:527a66d0a1a9 249 ERR("Version mismatch");
MiniTLS 2:527a66d0a1a9 250 tls_alert_send( record, TLS_ALERT_FATAL, PROTOCOL_VERSION, &record->buffer);
MiniTLS 2:527a66d0a1a9 251 return MINITLS_ERR_PROTOCOL_VERSION;
MiniTLS 2:527a66d0a1a9 252 }
MiniTLS 2:527a66d0a1a9 253 #endif
MiniTLS 2:527a66d0a1a9 254 //Check content type
MiniTLS 2:527a66d0a1a9 255 //Check that encryption level is OK for this content type
MiniTLS 2:527a66d0a1a9 256 switch( header.type )
MiniTLS 2:527a66d0a1a9 257 {
MiniTLS 2:527a66d0a1a9 258 //All of these are OK in plain mode
MiniTLS 2:527a66d0a1a9 259 case TLS_CHANGE_CIPHER_SPEC:
MiniTLS 2:527a66d0a1a9 260 case TLS_ALERT:
MiniTLS 2:527a66d0a1a9 261 case TLS_HANDSHAKE:
MiniTLS 2:527a66d0a1a9 262 break;
MiniTLS 2:527a66d0a1a9 263 //This is only acceptable in ciphered mode:
MiniTLS 2:527a66d0a1a9 264 case TLS_APPLICATION_DATA:
MiniTLS 2:527a66d0a1a9 265 if( (!tls_record_is_secure(record)) || (!record->handshake_done) )
MiniTLS 2:527a66d0a1a9 266 {
MiniTLS 2:527a66d0a1a9 267 tls_alert_send( record, TLS_ALERT_FATAL, INSUFFICIENT_SECURITY, &record->buffer);
MiniTLS 2:527a66d0a1a9 268 return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 2:527a66d0a1a9 269 }
MiniTLS 2:527a66d0a1a9 270 break;
MiniTLS 2:527a66d0a1a9 271 default:
MiniTLS 2:527a66d0a1a9 272 tls_alert_send( record, TLS_ALERT_FATAL, ILLEGAL_PARAMETER, &record->buffer);
MiniTLS 2:527a66d0a1a9 273 return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 2:527a66d0a1a9 274 }
MiniTLS 2:527a66d0a1a9 275
MiniTLS 2:527a66d0a1a9 276 //Reset buffer
MiniTLS 2:527a66d0a1a9 277 buffer_reset(&record->buffer);
MiniTLS 2:527a66d0a1a9 278
MiniTLS 2:527a66d0a1a9 279 //Read payload
MiniTLS 2:527a66d0a1a9 280 ret = record_socket_read(record, header.length);
MiniTLS 2:527a66d0a1a9 281 if(ret)
MiniTLS 2:527a66d0a1a9 282 {
MiniTLS 2:527a66d0a1a9 283 ERR("Socket err %d", ret);
MiniTLS 2:527a66d0a1a9 284 tls_alert_send( record, TLS_ALERT_FATAL, INTERNAL_ERROR, &record->buffer);
MiniTLS 2:527a66d0a1a9 285 return ret;
MiniTLS 2:527a66d0a1a9 286 }
MiniTLS 2:527a66d0a1a9 287
MiniTLS 2:527a66d0a1a9 288 if( record->security_rx_state == TLS_SECURITY_ACTIVE )
MiniTLS 2:527a66d0a1a9 289 {
MiniTLS 2:527a66d0a1a9 290
MiniTLS 3:eb324ffffd2b 291 #if CRYPTO_AES_128
MiniTLS 3:eb324ffffd2b 292 if(record->security_type == TLS_SECURITY_TYPE_AES_128_CBC_SHA)
MiniTLS 2:527a66d0a1a9 293 {
MiniTLS 3:eb324ffffd2b 294 DBG("IV + Ciphertext");
MiniTLS 3:eb324ffffd2b 295 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 2:527a66d0a1a9 296
MiniTLS 3:eb324ffffd2b 297 buffer_t buffer_iv_header;
MiniTLS 3:eb324ffffd2b 298 if( (buffer_length(&record->buffer) < 2*AES_128_BLOCK_SIZE) || ( (buffer_length(&record->buffer) % AES_128_BLOCK_SIZE) != 0 ) )
MiniTLS 3:eb324ffffd2b 299 {
MiniTLS 3:eb324ffffd2b 300 tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer );
MiniTLS 3:eb324ffffd2b 301 return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 3:eb324ffffd2b 302 }
MiniTLS 3:eb324ffffd2b 303 buffer_byref(&buffer_iv_header, buffer_current_read_position(&record->buffer), AES_128_BLOCK_SIZE); //Extract IV vector
MiniTLS 3:eb324ffffd2b 304 buffer_n_discard(&record->buffer, AES_128_BLOCK_SIZE);
MiniTLS 2:527a66d0a1a9 305
MiniTLS 3:eb324ffffd2b 306 //Decrypt message
MiniTLS 3:eb324ffffd2b 307 ret = crypto_aes_128_cbc_decrypt( &record->cipher_rx.aes_128, &buffer_iv_header, &record->buffer );
MiniTLS 3:eb324ffffd2b 308 if(ret)
MiniTLS 3:eb324ffffd2b 309 {
MiniTLS 3:eb324ffffd2b 310 ERR("Failed to decipher, ret %d", ret);
MiniTLS 3:eb324ffffd2b 311 tls_alert_send( record, TLS_ALERT_FATAL, DECRYPT_ERROR, &record->buffer );
MiniTLS 3:eb324ffffd2b 312 return ret;
MiniTLS 3:eb324ffffd2b 313 }
MiniTLS 2:527a66d0a1a9 314
MiniTLS 3:eb324ffffd2b 315 DBG("Plaintext + MAC + padding + padding length");
MiniTLS 3:eb324ffffd2b 316 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 2:527a66d0a1a9 317
MiniTLS 3:eb324ffffd2b 318 //Check and remove padding
MiniTLS 3:eb324ffffd2b 319 size_t padding_length = *(buffer_current_write_position(&record->buffer) - 1);
MiniTLS 3:eb324ffffd2b 320
MiniTLS 3:eb324ffffd2b 321 if( padding_length + 1 > buffer_length(&record->buffer) )
MiniTLS 2:527a66d0a1a9 322 {
MiniTLS 3:eb324ffffd2b 323 ERR("Wrong padding length");
MiniTLS 2:527a66d0a1a9 324 tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer );
MiniTLS 2:527a66d0a1a9 325 return MINITLS_ERR_CRYPTO;
MiniTLS 2:527a66d0a1a9 326 }
MiniTLS 3:eb324ffffd2b 327
MiniTLS 3:eb324ffffd2b 328 int p;
MiniTLS 3:eb324ffffd2b 329 //Check each padding byte
MiniTLS 3:eb324ffffd2b 330 for(p = 0; p < padding_length; p++)
MiniTLS 3:eb324ffffd2b 331 {
MiniTLS 3:eb324ffffd2b 332 if( *(buffer_current_write_position(&record->buffer) - 1 - p) != padding_length )
MiniTLS 3:eb324ffffd2b 333 {
MiniTLS 3:eb324ffffd2b 334 ERR("Wrong padding");
MiniTLS 3:eb324ffffd2b 335 tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer );
MiniTLS 3:eb324ffffd2b 336 return MINITLS_ERR_CRYPTO;
MiniTLS 3:eb324ffffd2b 337 }
MiniTLS 3:eb324ffffd2b 338 }
MiniTLS 2:527a66d0a1a9 339
MiniTLS 3:eb324ffffd2b 340 //Remove trailing padding + padding length
MiniTLS 3:eb324ffffd2b 341 buffer_set_length(&record->buffer, buffer_length(&record->buffer) - 1 - padding_length);
MiniTLS 3:eb324ffffd2b 342 }
MiniTLS 3:eb324ffffd2b 343 else
MiniTLS 3:eb324ffffd2b 344 #endif
MiniTLS 3:eb324ffffd2b 345 #if CRYPTO_ARC4
MiniTLS 3:eb324ffffd2b 346 if(record->security_type == TLS_SECURITY_TYPE_ARC4_SHA)
MiniTLS 3:eb324ffffd2b 347 {
MiniTLS 3:eb324ffffd2b 348 DBG("Ciphertext");
MiniTLS 3:eb324ffffd2b 349 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 3:eb324ffffd2b 350
MiniTLS 3:eb324ffffd2b 351 //Decrypt message
MiniTLS 3:eb324ffffd2b 352 crypto_arc4_process( &record->cipher_rx.arc4, &record->buffer );
MiniTLS 3:eb324ffffd2b 353 }
MiniTLS 3:eb324ffffd2b 354 else
MiniTLS 3:eb324ffffd2b 355 #endif
MiniTLS 3:eb324ffffd2b 356 {}
MiniTLS 2:527a66d0a1a9 357
MiniTLS 2:527a66d0a1a9 358 DBG("Plaintext + MAC");
MiniTLS 2:527a66d0a1a9 359 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 2:527a66d0a1a9 360
MiniTLS 2:527a66d0a1a9 361 //Check MAC
MiniTLS 2:527a66d0a1a9 362 ret = tls_mac_check( record->server_write_mac_key, header.type, header.version, record->sequence_number_rx, &record->buffer );
MiniTLS 2:527a66d0a1a9 363 if(ret)
MiniTLS 2:527a66d0a1a9 364 {
MiniTLS 2:527a66d0a1a9 365 ERR("MAC Check failed, ret %d", ret);
MiniTLS 2:527a66d0a1a9 366 tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer );
MiniTLS 2:527a66d0a1a9 367 return ret;
MiniTLS 2:527a66d0a1a9 368 }
MiniTLS 2:527a66d0a1a9 369
MiniTLS 2:527a66d0a1a9 370 DBG("Plaintext");
MiniTLS 2:527a66d0a1a9 371 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 2:527a66d0a1a9 372
MiniTLS 2:527a66d0a1a9 373 //Increment seq number
MiniTLS 2:527a66d0a1a9 374 record->sequence_number_rx++;
MiniTLS 2:527a66d0a1a9 375 }
MiniTLS 2:527a66d0a1a9 376 else
MiniTLS 2:527a66d0a1a9 377 {
MiniTLS 2:527a66d0a1a9 378 //No security
MiniTLS 2:527a66d0a1a9 379 }
MiniTLS 2:527a66d0a1a9 380
MiniTLS 2:527a66d0a1a9 381 //Now dispatch depending on content type
MiniTLS 2:527a66d0a1a9 382 switch( header.type )
MiniTLS 2:527a66d0a1a9 383 {
MiniTLS 2:527a66d0a1a9 384 case TLS_CHANGE_CIPHER_SPEC:
MiniTLS 2:527a66d0a1a9 385 ret = tls_record_change_cipher_spec(record, false);
MiniTLS 2:527a66d0a1a9 386 if(ret)
MiniTLS 2:527a66d0a1a9 387 {
MiniTLS 2:527a66d0a1a9 388 ERR("Invalid change cipher spec request, ret %d", ret);
MiniTLS 2:527a66d0a1a9 389 tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer );
MiniTLS 2:527a66d0a1a9 390 return ret;
MiniTLS 2:527a66d0a1a9 391 }
MiniTLS 2:527a66d0a1a9 392 break;
MiniTLS 2:527a66d0a1a9 393 case TLS_ALERT:
MiniTLS 2:527a66d0a1a9 394 ret = tls_alert_process( record, &record->buffer );
MiniTLS 2:527a66d0a1a9 395 if(ret)
MiniTLS 2:527a66d0a1a9 396 {
MiniTLS 2:527a66d0a1a9 397 tls_record_close(record);
MiniTLS 2:527a66d0a1a9 398 //Close connection in any case
MiniTLS 2:527a66d0a1a9 399 if(ret == MINITLS_ERR_CONNECTION_CLOSED)
MiniTLS 2:527a66d0a1a9 400 {
MiniTLS 2:527a66d0a1a9 401 DBG("Connection closed by remote party");
MiniTLS 2:527a66d0a1a9 402 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 403 }
MiniTLS 2:527a66d0a1a9 404 //FIXME Do something
MiniTLS 2:527a66d0a1a9 405 ERR("Alert received, ret %d", ret);
MiniTLS 2:527a66d0a1a9 406 return ret;
MiniTLS 2:527a66d0a1a9 407 }
MiniTLS 2:527a66d0a1a9 408 break;
MiniTLS 2:527a66d0a1a9 409 case TLS_HANDSHAKE:
MiniTLS 2:527a66d0a1a9 410 if(/*(record->tls_socket->handshake != NULL) &&*/ !tls_handshake_is_done(&record->tls_socket->handshake))
MiniTLS 2:527a66d0a1a9 411 {
MiniTLS 2:527a66d0a1a9 412 ret = tls_handshake_process(&record->tls_socket->handshake, &record->buffer );
MiniTLS 2:527a66d0a1a9 413 if(ret)
MiniTLS 2:527a66d0a1a9 414 {
MiniTLS 2:527a66d0a1a9 415 ERR("Handshake process returned %d", ret);
MiniTLS 2:527a66d0a1a9 416 //TLS alert already sent by handshake function
MiniTLS 2:527a66d0a1a9 417 tls_handshake_clean(&record->tls_socket->handshake); //Cleanup handshake
MiniTLS 2:527a66d0a1a9 418 //record->tls_socket->handshake = NULL;
MiniTLS 2:527a66d0a1a9 419 return ret;
MiniTLS 2:527a66d0a1a9 420 }
MiniTLS 2:527a66d0a1a9 421 if(tls_handshake_is_done(&record->tls_socket->handshake))
MiniTLS 2:527a66d0a1a9 422 {
MiniTLS 2:527a66d0a1a9 423 tls_handshake_clean(&record->tls_socket->handshake); //Cleanup handshake
MiniTLS 2:527a66d0a1a9 424 //record->tls_socket->handshake = NULL;
MiniTLS 2:527a66d0a1a9 425 record->handshake_done = true; //Enable application data layer
MiniTLS 2:527a66d0a1a9 426 }
MiniTLS 2:527a66d0a1a9 427 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 428 }
MiniTLS 2:527a66d0a1a9 429 else
MiniTLS 2:527a66d0a1a9 430 {
MiniTLS 2:527a66d0a1a9 431 ERR("Unexpected handshake message, ret %d", ret);
MiniTLS 2:527a66d0a1a9 432 tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer );
MiniTLS 2:527a66d0a1a9 433 return ret;
MiniTLS 2:527a66d0a1a9 434 }
MiniTLS 2:527a66d0a1a9 435 case TLS_APPLICATION_DATA:
MiniTLS 2:527a66d0a1a9 436 //Pass message to socket layer
MiniTLS 2:527a66d0a1a9 437 return tls_socket_readable_callback(record->tls_socket, &record->buffer);
MiniTLS 2:527a66d0a1a9 438 default:
MiniTLS 2:527a66d0a1a9 439 //Has already been checked above
MiniTLS 2:527a66d0a1a9 440 return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 2:527a66d0a1a9 441 }
MiniTLS 2:527a66d0a1a9 442
MiniTLS 2:527a66d0a1a9 443 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 444 }
MiniTLS 2:527a66d0a1a9 445
MiniTLS 2:527a66d0a1a9 446 minitls_err_t tls_record_send(tls_record_t* record, tls_content_type_t content_type, buffer_t* payload)
MiniTLS 2:527a66d0a1a9 447 {
MiniTLS 2:527a66d0a1a9 448 minitls_err_t ret;
MiniTLS 2:527a66d0a1a9 449 int padding_item;
MiniTLS 2:527a66d0a1a9 450 /*
MiniTLS 2:527a66d0a1a9 451 struct {
MiniTLS 2:527a66d0a1a9 452 opaque IV[SecurityParameters.record_iv_length];
MiniTLS 2:527a66d0a1a9 453 block-ciphered struct {
MiniTLS 2:527a66d0a1a9 454 opaque content[TLSCompressed.length];
MiniTLS 2:527a66d0a1a9 455 opaque MAC[SecurityParameters.mac_length];
MiniTLS 2:527a66d0a1a9 456 uint8 padding[GenericBlockCipher.padding_length];
MiniTLS 2:527a66d0a1a9 457 uint8 padding_length;
MiniTLS 2:527a66d0a1a9 458 };
MiniTLS 2:527a66d0a1a9 459 } GenericBlockCipher;
MiniTLS 2:527a66d0a1a9 460 */
MiniTLS 2:527a66d0a1a9 461
MiniTLS 2:527a66d0a1a9 462 //Check content type
MiniTLS 2:527a66d0a1a9 463 //Check that encryption level is OK for this content type
MiniTLS 2:527a66d0a1a9 464 switch( content_type )
MiniTLS 2:527a66d0a1a9 465 {
MiniTLS 2:527a66d0a1a9 466 //All of these are OK in plain mode
MiniTLS 2:527a66d0a1a9 467 case TLS_CHANGE_CIPHER_SPEC:
MiniTLS 2:527a66d0a1a9 468 case TLS_ALERT:
MiniTLS 2:527a66d0a1a9 469 case TLS_HANDSHAKE:
MiniTLS 2:527a66d0a1a9 470 break;
MiniTLS 2:527a66d0a1a9 471 //This is only acceptable in ciphered mode:
MiniTLS 2:527a66d0a1a9 472 case TLS_APPLICATION_DATA:
MiniTLS 2:527a66d0a1a9 473 if( (!tls_record_is_secure(record)) || (!record->handshake_done) )
MiniTLS 2:527a66d0a1a9 474 {
MiniTLS 2:527a66d0a1a9 475 tls_alert_send( record, TLS_ALERT_FATAL, INSUFFICIENT_SECURITY, &record->buffer);
MiniTLS 2:527a66d0a1a9 476 return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 2:527a66d0a1a9 477 }
MiniTLS 2:527a66d0a1a9 478 break;
MiniTLS 2:527a66d0a1a9 479 default:
MiniTLS 2:527a66d0a1a9 480 tls_alert_send( record, TLS_ALERT_FATAL, ILLEGAL_PARAMETER, &record->buffer);
MiniTLS 2:527a66d0a1a9 481 return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 2:527a66d0a1a9 482 }
MiniTLS 2:527a66d0a1a9 483
MiniTLS 2:527a66d0a1a9 484 //Buffer must have enough space to add IV (head) + MAC (tail) + padding (tail)
MiniTLS 2:527a66d0a1a9 485
MiniTLS 2:527a66d0a1a9 486 buffer_t header_iv;
MiniTLS 2:527a66d0a1a9 487 uint8_t header_iv_data[AES_128_BLOCK_SIZE];
MiniTLS 2:527a66d0a1a9 488 if( record->security_tx_state == TLS_SECURITY_ACTIVE )
MiniTLS 2:527a66d0a1a9 489 {
MiniTLS 2:527a66d0a1a9 490 //FIXME generate a random IV
MiniTLS 2:527a66d0a1a9 491
MiniTLS 2:527a66d0a1a9 492 DBG("Plaintext");
MiniTLS 2:527a66d0a1a9 493 DBG_BLOCK(buffer_dump(payload);)
MiniTLS 2:527a66d0a1a9 494
MiniTLS 2:527a66d0a1a9 495 //Compute & append MAC
MiniTLS 2:527a66d0a1a9 496 DBG("Sequence number: %d", record->sequence_number_tx);
MiniTLS 2:527a66d0a1a9 497 ret = tls_mac_append( record->client_write_mac_key, content_type, record->version, record->sequence_number_tx, payload );
MiniTLS 2:527a66d0a1a9 498 if(ret)
MiniTLS 2:527a66d0a1a9 499 {
MiniTLS 2:527a66d0a1a9 500 ERR("Could not append MAC, ret %d", ret);
MiniTLS 2:527a66d0a1a9 501 return ret;
MiniTLS 2:527a66d0a1a9 502 }
MiniTLS 2:527a66d0a1a9 503
MiniTLS 2:527a66d0a1a9 504 //Increment sequence number
MiniTLS 2:527a66d0a1a9 505 record->sequence_number_tx++;
MiniTLS 2:527a66d0a1a9 506
MiniTLS 2:527a66d0a1a9 507 DBG("Plaintext + MAC");
MiniTLS 2:527a66d0a1a9 508 DBG_BLOCK(buffer_dump(payload);)
MiniTLS 2:527a66d0a1a9 509
MiniTLS 3:eb324ffffd2b 510 #if CRYPTO_AES_128
MiniTLS 3:eb324ffffd2b 511 if(record->security_type == TLS_SECURITY_TYPE_AES_128_CBC_SHA)
MiniTLS 2:527a66d0a1a9 512 {
MiniTLS 3:eb324ffffd2b 513
MiniTLS 3:eb324ffffd2b 514 //Add padding
MiniTLS 3:eb324ffffd2b 515 size_t padding_length = AES_128_BLOCK_SIZE - (buffer_length(payload) % AES_128_BLOCK_SIZE) - 1;
MiniTLS 3:eb324ffffd2b 516 if(buffer_space(payload) < padding_length)
MiniTLS 3:eb324ffffd2b 517 {
MiniTLS 3:eb324ffffd2b 518 return MINITLS_ERR_BUFFER_TOO_SMALL;
MiniTLS 3:eb324ffffd2b 519 }
MiniTLS 2:527a66d0a1a9 520
MiniTLS 3:eb324ffffd2b 521 for(padding_item = 0; padding_item < padding_length; padding_item++)
MiniTLS 3:eb324ffffd2b 522 {
MiniTLS 3:eb324ffffd2b 523 buffer_nu8_write(payload, padding_length);
MiniTLS 3:eb324ffffd2b 524 }
MiniTLS 3:eb324ffffd2b 525
MiniTLS 2:527a66d0a1a9 526 buffer_nu8_write(payload, padding_length);
MiniTLS 2:527a66d0a1a9 527
MiniTLS 3:eb324ffffd2b 528 DBG("Plaintext + MAC + Padding + Padding Length");
MiniTLS 3:eb324ffffd2b 529 DBG_BLOCK(buffer_dump(payload);)
MiniTLS 3:eb324ffffd2b 530
MiniTLS 3:eb324ffffd2b 531 buffer_init( &header_iv, header_iv_data, AES_128_BLOCK_SIZE );
MiniTLS 2:527a66d0a1a9 532
MiniTLS 3:eb324ffffd2b 533 crypto_prng_get(record->tls_socket->minitls->prng, buffer_current_write_position(&header_iv), AES_128_BLOCK_SIZE);
MiniTLS 3:eb324ffffd2b 534 buffer_n_skip(&header_iv, AES_128_BLOCK_SIZE);
MiniTLS 2:527a66d0a1a9 535
MiniTLS 3:eb324ffffd2b 536 //Encrypt message
MiniTLS 3:eb324ffffd2b 537 ret = crypto_aes_128_cbc_encrypt( &record->cipher_tx.aes_128, &header_iv, payload );
MiniTLS 3:eb324ffffd2b 538 if(ret)
MiniTLS 3:eb324ffffd2b 539 {
MiniTLS 3:eb324ffffd2b 540 ERR("Failed to encipher, ret %d", ret);
MiniTLS 3:eb324ffffd2b 541 return ret;
MiniTLS 3:eb324ffffd2b 542 }
MiniTLS 3:eb324ffffd2b 543 }
MiniTLS 3:eb324ffffd2b 544 else
MiniTLS 3:eb324ffffd2b 545 #endif
MiniTLS 3:eb324ffffd2b 546 #if CRYPTO_ARC4
MiniTLS 3:eb324ffffd2b 547 if(record->security_type == TLS_SECURITY_TYPE_ARC4_SHA)
MiniTLS 2:527a66d0a1a9 548 {
MiniTLS 3:eb324ffffd2b 549 //No IV
MiniTLS 3:eb324ffffd2b 550 buffer_init( &header_iv, NULL, 0 ); //0 Length
MiniTLS 3:eb324ffffd2b 551
MiniTLS 3:eb324ffffd2b 552 //Encrypt message
MiniTLS 3:eb324ffffd2b 553 crypto_arc4_process( &record->cipher_tx.arc4, payload );
MiniTLS 2:527a66d0a1a9 554 }
MiniTLS 3:eb324ffffd2b 555 else
MiniTLS 3:eb324ffffd2b 556 #endif
MiniTLS 3:eb324ffffd2b 557 {}
MiniTLS 2:527a66d0a1a9 558
MiniTLS 2:527a66d0a1a9 559 DBG("Ciphertext");
MiniTLS 2:527a66d0a1a9 560 DBG_BLOCK(buffer_dump(payload);)
MiniTLS 2:527a66d0a1a9 561 }
MiniTLS 2:527a66d0a1a9 562 else
MiniTLS 2:527a66d0a1a9 563 {
MiniTLS 2:527a66d0a1a9 564 buffer_init( &header_iv, NULL, 0 ); //0 Length
MiniTLS 2:527a66d0a1a9 565 }
MiniTLS 2:527a66d0a1a9 566
MiniTLS 2:527a66d0a1a9 567 //Now send message header
MiniTLS 2:527a66d0a1a9 568 tls_fragment_header_t header;
MiniTLS 2:527a66d0a1a9 569 header.type = content_type;
MiniTLS 2:527a66d0a1a9 570 header.version.major = record->version.major;
MiniTLS 2:527a66d0a1a9 571 header.version.minor = record->version.minor;
MiniTLS 2:527a66d0a1a9 572 header.length = buffer_length( &header_iv ) + buffer_length(payload);
MiniTLS 2:527a66d0a1a9 573
MiniTLS 2:527a66d0a1a9 574 buffer_t header_fragment;
MiniTLS 2:527a66d0a1a9 575 uint8_t header_fragment_data[FRAGMENT_HEADER_SIZE];
MiniTLS 2:527a66d0a1a9 576
MiniTLS 2:527a66d0a1a9 577 buffer_init( &header_fragment, header_fragment_data, FRAGMENT_HEADER_SIZE );
MiniTLS 2:527a66d0a1a9 578
MiniTLS 2:527a66d0a1a9 579 buffer_nu8_write(&header_fragment, header.type);
MiniTLS 2:527a66d0a1a9 580 buffer_nu8_write(&header_fragment, header.version.major);
MiniTLS 2:527a66d0a1a9 581 buffer_nu8_write(&header_fragment, header.version.minor);
MiniTLS 2:527a66d0a1a9 582 buffer_nu16_write(&header_fragment, header.length);
MiniTLS 2:527a66d0a1a9 583
MiniTLS 2:527a66d0a1a9 584 //Send fragment header
MiniTLS 2:527a66d0a1a9 585 ret = record_socket_write(record, &header_fragment);
MiniTLS 2:527a66d0a1a9 586 if(ret)
MiniTLS 2:527a66d0a1a9 587 {
MiniTLS 2:527a66d0a1a9 588 return ret;
MiniTLS 2:527a66d0a1a9 589 }
MiniTLS 2:527a66d0a1a9 590
MiniTLS 2:527a66d0a1a9 591 //Send IV
MiniTLS 2:527a66d0a1a9 592 ret = record_socket_write(record, &header_iv);
MiniTLS 2:527a66d0a1a9 593 if(ret)
MiniTLS 2:527a66d0a1a9 594 {
MiniTLS 2:527a66d0a1a9 595 return ret;
MiniTLS 2:527a66d0a1a9 596 }
MiniTLS 2:527a66d0a1a9 597
MiniTLS 2:527a66d0a1a9 598 //Send payload
MiniTLS 2:527a66d0a1a9 599 ret = record_socket_write(record, payload);
MiniTLS 2:527a66d0a1a9 600 if(ret)
MiniTLS 2:527a66d0a1a9 601 {
MiniTLS 2:527a66d0a1a9 602 return ret;
MiniTLS 2:527a66d0a1a9 603 }
MiniTLS 2:527a66d0a1a9 604
MiniTLS 2:527a66d0a1a9 605 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 606 }
MiniTLS 2:527a66d0a1a9 607
MiniTLS 2:527a66d0a1a9 608 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 609 const uint8_t* client_write_cipher_key, const uint8_t* server_write_cipher_key)
MiniTLS 2:527a66d0a1a9 610 {
MiniTLS 3:eb324ffffd2b 611 if( (security != TLS_SECURITY_TYPE_AES_128_CBC_SHA) && (security != TLS_SECURITY_TYPE_ARC4_SHA) )
MiniTLS 2:527a66d0a1a9 612 {
MiniTLS 2:527a66d0a1a9 613 return MINITLS_ERR_NOT_IMPLEMENTED;
MiniTLS 2:527a66d0a1a9 614 }
MiniTLS 2:527a66d0a1a9 615
MiniTLS 2:527a66d0a1a9 616 //Copy keys
MiniTLS 2:527a66d0a1a9 617 memcpy(&record->client_write_mac_key, client_write_mac_key, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 2:527a66d0a1a9 618 memcpy(&record->server_write_mac_key, server_write_mac_key, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 3:eb324ffffd2b 619 memcpy(&record->client_write_cipher_key, client_write_cipher_key, AES_128_KEY_SIZE); //TODO generic key size
MiniTLS 2:527a66d0a1a9 620 memcpy(&record->server_write_cipher_key, server_write_cipher_key, AES_128_KEY_SIZE);
MiniTLS 2:527a66d0a1a9 621
MiniTLS 2:527a66d0a1a9 622 //Intialize cipher
MiniTLS 2:527a66d0a1a9 623
MiniTLS 2:527a66d0a1a9 624 record->sequence_number_tx = 0;
MiniTLS 2:527a66d0a1a9 625 record->sequence_number_rx = 0;
MiniTLS 2:527a66d0a1a9 626
MiniTLS 3:eb324ffffd2b 627 switch(security)
MiniTLS 3:eb324ffffd2b 628 {
MiniTLS 3:eb324ffffd2b 629 #if CRYPTO_AES_128
MiniTLS 3:eb324ffffd2b 630 case TLS_SECURITY_TYPE_AES_128_CBC_SHA:
MiniTLS 3:eb324ffffd2b 631 crypto_aes_128_init(&record->cipher_tx.aes_128, record->client_write_cipher_key, expand_encryption_key);
MiniTLS 3:eb324ffffd2b 632 crypto_aes_128_init(&record->cipher_rx.aes_128, record->server_write_cipher_key, expand_decryption_key);
MiniTLS 3:eb324ffffd2b 633 break;
MiniTLS 3:eb324ffffd2b 634 #endif
MiniTLS 3:eb324ffffd2b 635 #if CRYPTO_ARC4
MiniTLS 3:eb324ffffd2b 636 case TLS_SECURITY_TYPE_ARC4_SHA:
MiniTLS 3:eb324ffffd2b 637 crypto_arc4_init(&record->cipher_tx.arc4, record->client_write_cipher_key, TLS_ARC4_KEY_SIZE );
MiniTLS 3:eb324ffffd2b 638 crypto_arc4_init(&record->cipher_rx.arc4, record->server_write_cipher_key, TLS_ARC4_KEY_SIZE);
MiniTLS 3:eb324ffffd2b 639 break;
MiniTLS 3:eb324ffffd2b 640 #endif
MiniTLS 3:eb324ffffd2b 641 default:
MiniTLS 3:eb324ffffd2b 642 break;
MiniTLS 3:eb324ffffd2b 643 }
MiniTLS 2:527a66d0a1a9 644
MiniTLS 2:527a66d0a1a9 645 record->security_tx_state = TLS_SECURITY_INTIALIZED;
MiniTLS 2:527a66d0a1a9 646 record->security_rx_state = TLS_SECURITY_INTIALIZED;
MiniTLS 3:eb324ffffd2b 647 record->security_type = security;
MiniTLS 2:527a66d0a1a9 648
MiniTLS 2:527a66d0a1a9 649 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 650 }
MiniTLS 2:527a66d0a1a9 651
MiniTLS 2:527a66d0a1a9 652 minitls_err_t tls_record_close(tls_record_t* record)
MiniTLS 2:527a66d0a1a9 653 {
MiniTLS 2:527a66d0a1a9 654 if(record->socket_fd < 0) //Already closed
MiniTLS 2:527a66d0a1a9 655 {
MiniTLS 2:527a66d0a1a9 656 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 657 }
MiniTLS 2:527a66d0a1a9 658
MiniTLS 2:527a66d0a1a9 659 //Don't really care about the return
MiniTLS 2:527a66d0a1a9 660 tls_alert_send(record, TLS_ALERT_WARNING, CLOSE_NOTIFY, &record->buffer);
MiniTLS 2:527a66d0a1a9 661
MiniTLS 2:527a66d0a1a9 662 //Close socket
MiniTLS 2:527a66d0a1a9 663 socket_close(record->socket_fd);
MiniTLS 2:527a66d0a1a9 664 record->socket_fd = -1;
MiniTLS 2:527a66d0a1a9 665
MiniTLS 2:527a66d0a1a9 666 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 667 }
MiniTLS 2:527a66d0a1a9 668
MiniTLS 2:527a66d0a1a9 669 minitls_err_t tls_record_set_read_timeout(tls_record_t* record, int timeout)
MiniTLS 2:527a66d0a1a9 670 {
MiniTLS 2:527a66d0a1a9 671 record->read_timeout = timeout;
MiniTLS 2:527a66d0a1a9 672
MiniTLS 2:527a66d0a1a9 673 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 674 }
MiniTLS 2:527a66d0a1a9 675
MiniTLS 2:527a66d0a1a9 676 minitls_err_t tls_record_set_write_timeout(tls_record_t* record, int timeout)
MiniTLS 2:527a66d0a1a9 677 {
MiniTLS 2:527a66d0a1a9 678 record->write_timeout = timeout;
MiniTLS 2:527a66d0a1a9 679
MiniTLS 2:527a66d0a1a9 680 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 681 }
MiniTLS 2:527a66d0a1a9 682
MiniTLS 2:527a66d0a1a9 683 minitls_err_t record_wait_readable(tls_record_t* record)
MiniTLS 2:527a66d0a1a9 684 {
MiniTLS 2:527a66d0a1a9 685 if(record->socket_fd < 0)
MiniTLS 2:527a66d0a1a9 686 {
MiniTLS 2:527a66d0a1a9 687 return MINITLS_ERR_SOCKET_CLOSED;
MiniTLS 2:527a66d0a1a9 688 }
MiniTLS 2:527a66d0a1a9 689
MiniTLS 2:527a66d0a1a9 690 //Wait for record to be readable
MiniTLS 2:527a66d0a1a9 691 int ret = socket_wait_readable(record->socket_fd, record->read_timeout );
MiniTLS 2:527a66d0a1a9 692 if( ret < 0 )
MiniTLS 2:527a66d0a1a9 693 {
MiniTLS 2:527a66d0a1a9 694 //Timeout
MiniTLS 2:527a66d0a1a9 695 return MINITLS_ERR_TIMEOUT;
MiniTLS 2:527a66d0a1a9 696 }
MiniTLS 2:527a66d0a1a9 697 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 698 }
MiniTLS 2:527a66d0a1a9 699
MiniTLS 2:527a66d0a1a9 700 minitls_err_t record_wait_writeable(tls_record_t* record)
MiniTLS 2:527a66d0a1a9 701 {
MiniTLS 2:527a66d0a1a9 702 if(record->socket_fd < 0)
MiniTLS 2:527a66d0a1a9 703 {
MiniTLS 2:527a66d0a1a9 704 return MINITLS_ERR_SOCKET_CLOSED;
MiniTLS 2:527a66d0a1a9 705 }
MiniTLS 2:527a66d0a1a9 706
MiniTLS 2:527a66d0a1a9 707 //Wait for record to be writeable
MiniTLS 2:527a66d0a1a9 708 int ret = socket_wait_writeable(record->socket_fd, record->write_timeout );
MiniTLS 2:527a66d0a1a9 709 if( ret < 0 )
MiniTLS 2:527a66d0a1a9 710 {
MiniTLS 2:527a66d0a1a9 711 //Timeout
MiniTLS 2:527a66d0a1a9 712 return MINITLS_ERR_TIMEOUT;
MiniTLS 2:527a66d0a1a9 713 }
MiniTLS 2:527a66d0a1a9 714 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 715 }
MiniTLS 2:527a66d0a1a9 716
MiniTLS 2:527a66d0a1a9 717 minitls_err_t record_socket_read(tls_record_t* record, size_t size)
MiniTLS 2:527a66d0a1a9 718 {
MiniTLS 2:527a66d0a1a9 719 minitls_err_t ret;
MiniTLS 2:527a66d0a1a9 720 if(record->socket_fd < 0)
MiniTLS 2:527a66d0a1a9 721 {
MiniTLS 2:527a66d0a1a9 722 return MINITLS_ERR_SOCKET_CLOSED;
MiniTLS 2:527a66d0a1a9 723 }
MiniTLS 2:527a66d0a1a9 724
MiniTLS 2:527a66d0a1a9 725 DBG("Trying to read %d bytes", size);
MiniTLS 2:527a66d0a1a9 726 while(size > 0)
MiniTLS 2:527a66d0a1a9 727 {
MiniTLS 2:527a66d0a1a9 728 //Read Fragment length
MiniTLS 2:527a66d0a1a9 729 if( buffer_space(&record->buffer) < size )
MiniTLS 2:527a66d0a1a9 730 {
MiniTLS 2:527a66d0a1a9 731 ERR("Won't be able to read packet (%d bytes to read - %d bytes of space)", size, buffer_space(&record->buffer));
MiniTLS 2:527a66d0a1a9 732 return MINITLS_ERR_BUFFER_TOO_SMALL;
MiniTLS 2:527a66d0a1a9 733 }
MiniTLS 2:527a66d0a1a9 734
MiniTLS 2:527a66d0a1a9 735 ret = record_wait_readable(record);
MiniTLS 2:527a66d0a1a9 736 if(ret)
MiniTLS 2:527a66d0a1a9 737 {
MiniTLS 2:527a66d0a1a9 738 ERR("Timeout");
MiniTLS 2:527a66d0a1a9 739 return ret;
MiniTLS 2:527a66d0a1a9 740 }
MiniTLS 2:527a66d0a1a9 741
MiniTLS 3:eb324ffffd2b 742 int count = socket_recv(record->socket_fd, buffer_current_write_position(&record->buffer), size /*- buffer_length(&record->buffer)*/);
MiniTLS 2:527a66d0a1a9 743 if( count > 0 )
MiniTLS 2:527a66d0a1a9 744 {
MiniTLS 2:527a66d0a1a9 745 buffer_n_skip(&record->buffer, count);
MiniTLS 2:527a66d0a1a9 746 size -= count;
MiniTLS 2:527a66d0a1a9 747 }
MiniTLS 2:527a66d0a1a9 748 else if( count == 0 )
MiniTLS 2:527a66d0a1a9 749 {
MiniTLS 2:527a66d0a1a9 750 WARN("Socket closed");
MiniTLS 2:527a66d0a1a9 751 return MINITLS_ERR_SOCKET_CLOSED;
MiniTLS 2:527a66d0a1a9 752 }
MiniTLS 2:527a66d0a1a9 753 else
MiniTLS 2:527a66d0a1a9 754 {
MiniTLS 2:527a66d0a1a9 755 ERR("Error (returned %d)", count);
MiniTLS 2:527a66d0a1a9 756 return MINITLS_ERR_SOCKET_ERROR;
MiniTLS 2:527a66d0a1a9 757 }
MiniTLS 2:527a66d0a1a9 758 }
MiniTLS 2:527a66d0a1a9 759
MiniTLS 2:527a66d0a1a9 760 DBG_BLOCK(buffer_dump(&record->buffer);)
MiniTLS 2:527a66d0a1a9 761
MiniTLS 2:527a66d0a1a9 762 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 763 }
MiniTLS 2:527a66d0a1a9 764
MiniTLS 2:527a66d0a1a9 765 minitls_err_t record_socket_write(tls_record_t* record, buffer_t* data)
MiniTLS 2:527a66d0a1a9 766 {
MiniTLS 2:527a66d0a1a9 767 minitls_err_t ret;
MiniTLS 2:527a66d0a1a9 768 if(record->socket_fd < 0)
MiniTLS 2:527a66d0a1a9 769 {
MiniTLS 2:527a66d0a1a9 770 return MINITLS_ERR_SOCKET_CLOSED;
MiniTLS 2:527a66d0a1a9 771 }
MiniTLS 2:527a66d0a1a9 772
MiniTLS 2:527a66d0a1a9 773 DBG("Trying to write %d bytes", buffer_length(data));
MiniTLS 2:527a66d0a1a9 774 DBG_BLOCK(buffer_dump(data);)
MiniTLS 2:527a66d0a1a9 775 while(buffer_length(data) > 0)
MiniTLS 2:527a66d0a1a9 776 {
MiniTLS 2:527a66d0a1a9 777 ret = record_wait_writeable(record);
MiniTLS 2:527a66d0a1a9 778 if(ret)
MiniTLS 2:527a66d0a1a9 779 {
MiniTLS 2:527a66d0a1a9 780 ERR("Timeout");
MiniTLS 2:527a66d0a1a9 781 return ret;
MiniTLS 2:527a66d0a1a9 782 }
MiniTLS 2:527a66d0a1a9 783
MiniTLS 2:527a66d0a1a9 784 int count = socket_send(record->socket_fd, buffer_current_read_position(data), buffer_length(data));
MiniTLS 2:527a66d0a1a9 785 if( count > 0 )
MiniTLS 2:527a66d0a1a9 786 {
MiniTLS 2:527a66d0a1a9 787 buffer_n_discard(data, count);
MiniTLS 2:527a66d0a1a9 788 }
MiniTLS 2:527a66d0a1a9 789 else if( count == 0 )
MiniTLS 2:527a66d0a1a9 790 {
MiniTLS 2:527a66d0a1a9 791 WARN("Socket closed");
MiniTLS 2:527a66d0a1a9 792 return MINITLS_ERR_SOCKET_CLOSED;
MiniTLS 2:527a66d0a1a9 793 }
MiniTLS 2:527a66d0a1a9 794 else
MiniTLS 2:527a66d0a1a9 795 {
MiniTLS 2:527a66d0a1a9 796 ERR("Error (returned %d)", count);
MiniTLS 2:527a66d0a1a9 797 return MINITLS_ERR_SOCKET_ERROR;
MiniTLS 2:527a66d0a1a9 798 }
MiniTLS 2:527a66d0a1a9 799 }
MiniTLS 2:527a66d0a1a9 800 DBG("Done");
MiniTLS 2:527a66d0a1a9 801 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 802 }
MiniTLS 2:527a66d0a1a9 803
MiniTLS 2:527a66d0a1a9 804
MiniTLS 2:527a66d0a1a9 805 minitls_err_t tls_mac_append( const uint8_t* key, tls_content_type_t content_type, tls_protocol_version_t version,
MiniTLS 2:527a66d0a1a9 806 uint64_t sequence_number, buffer_t* buffer )
MiniTLS 2:527a66d0a1a9 807 {
MiniTLS 2:527a66d0a1a9 808 crypto_hmac_sha1_t mac;
MiniTLS 2:527a66d0a1a9 809 crypto_hmac_sha1_init(&mac, key, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 2:527a66d0a1a9 810
MiniTLS 2:527a66d0a1a9 811 if( buffer_space(buffer) < HMAC_SHA1_SIZE )
MiniTLS 2:527a66d0a1a9 812 {
MiniTLS 2:527a66d0a1a9 813 return MINITLS_ERR_BUFFER_TOO_SMALL;
MiniTLS 2:527a66d0a1a9 814 }
MiniTLS 2:527a66d0a1a9 815
MiniTLS 2:527a66d0a1a9 816 uint8_t header_buf[13];
MiniTLS 2:527a66d0a1a9 817 buffer_t header;
MiniTLS 2:527a66d0a1a9 818
MiniTLS 2:527a66d0a1a9 819 buffer_init(&header, header_buf, 13);
MiniTLS 2:527a66d0a1a9 820
MiniTLS 2:527a66d0a1a9 821 buffer_nu64_write(&header, sequence_number);
MiniTLS 2:527a66d0a1a9 822
MiniTLS 2:527a66d0a1a9 823 buffer_nu8_write(&header, content_type);
MiniTLS 2:527a66d0a1a9 824
MiniTLS 2:527a66d0a1a9 825 buffer_nu8_write(&header, version.major);
MiniTLS 2:527a66d0a1a9 826 buffer_nu8_write(&header, version.minor);
MiniTLS 2:527a66d0a1a9 827
MiniTLS 2:527a66d0a1a9 828 buffer_nu16_write(&header, buffer_length(buffer));
MiniTLS 2:527a66d0a1a9 829
MiniTLS 2:527a66d0a1a9 830 crypto_hmac_sha1_update(&mac, header_buf, 13);
MiniTLS 2:527a66d0a1a9 831 crypto_hmac_sha1_update(&mac, buffer_current_read_position(buffer), buffer_length(buffer));
MiniTLS 2:527a66d0a1a9 832 crypto_hmac_sha1_end(&mac, buffer_current_write_position(buffer));
MiniTLS 2:527a66d0a1a9 833 buffer_n_skip(buffer, HMAC_SHA1_SIZE);
MiniTLS 2:527a66d0a1a9 834
MiniTLS 2:527a66d0a1a9 835 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 836 }
MiniTLS 2:527a66d0a1a9 837
MiniTLS 2:527a66d0a1a9 838 minitls_err_t tls_mac_check( const uint8_t* key, tls_content_type_t content_type, tls_protocol_version_t version,
MiniTLS 2:527a66d0a1a9 839 uint64_t sequence_number, buffer_t* buffer )
MiniTLS 2:527a66d0a1a9 840 {
MiniTLS 2:527a66d0a1a9 841 crypto_hmac_sha1_t mac;
MiniTLS 2:527a66d0a1a9 842 crypto_hmac_sha1_init(&mac, key, TLS_HMAC_SHA1_KEY_SIZE);
MiniTLS 2:527a66d0a1a9 843
MiniTLS 2:527a66d0a1a9 844 if( buffer_length(buffer) < HMAC_SHA1_SIZE )
MiniTLS 2:527a66d0a1a9 845 {
MiniTLS 2:527a66d0a1a9 846 return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
MiniTLS 2:527a66d0a1a9 847 }
MiniTLS 2:527a66d0a1a9 848
MiniTLS 2:527a66d0a1a9 849 size_t data_offset = buffer_get_read_offset(buffer);
MiniTLS 2:527a66d0a1a9 850 size_t data_length = buffer_length(buffer) - HMAC_SHA1_SIZE;
MiniTLS 2:527a66d0a1a9 851
MiniTLS 2:527a66d0a1a9 852 uint8_t check[HMAC_SHA1_SIZE];
MiniTLS 2:527a66d0a1a9 853
MiniTLS 2:527a66d0a1a9 854 uint8_t header_buf[13];
MiniTLS 2:527a66d0a1a9 855 buffer_t header;
MiniTLS 2:527a66d0a1a9 856
MiniTLS 2:527a66d0a1a9 857 buffer_init(&header, header_buf, 13);
MiniTLS 2:527a66d0a1a9 858
MiniTLS 2:527a66d0a1a9 859 buffer_nu64_write(&header, sequence_number);
MiniTLS 2:527a66d0a1a9 860
MiniTLS 2:527a66d0a1a9 861 buffer_nu8_write(&header, content_type);
MiniTLS 2:527a66d0a1a9 862
MiniTLS 2:527a66d0a1a9 863 buffer_nu8_write(&header, version.major);
MiniTLS 2:527a66d0a1a9 864 buffer_nu8_write(&header, version.minor);
MiniTLS 2:527a66d0a1a9 865
MiniTLS 2:527a66d0a1a9 866 buffer_nu16_write(&header, data_length);
MiniTLS 2:527a66d0a1a9 867
MiniTLS 2:527a66d0a1a9 868 crypto_hmac_sha1_update(&mac, header_buf, 13);
MiniTLS 2:527a66d0a1a9 869 crypto_hmac_sha1_update(&mac, buffer_current_read_position(buffer), data_length);
MiniTLS 2:527a66d0a1a9 870 buffer_n_discard(buffer, data_length);
MiniTLS 2:527a66d0a1a9 871 crypto_hmac_sha1_end(&mac, check);
MiniTLS 2:527a66d0a1a9 872
MiniTLS 2:527a66d0a1a9 873 if( memcmp(buffer_current_read_position(buffer), check, HMAC_SHA1_SIZE) != 0 )
MiniTLS 2:527a66d0a1a9 874 {
MiniTLS 2:527a66d0a1a9 875 ERR("MAC differs; computed MAC was:");
MiniTLS 2:527a66d0a1a9 876
MiniTLS 2:527a66d0a1a9 877 buffer_t computed_mac;
MiniTLS 2:527a66d0a1a9 878 buffer_byref(&computed_mac, check, HMAC_SHA1_SIZE);
MiniTLS 2:527a66d0a1a9 879 DBG_BLOCK(buffer_dump(&computed_mac);)
MiniTLS 2:527a66d0a1a9 880
MiniTLS 2:527a66d0a1a9 881 return MINITLS_ERR_WRONG_MAC;
MiniTLS 2:527a66d0a1a9 882 }
MiniTLS 2:527a66d0a1a9 883
MiniTLS 2:527a66d0a1a9 884 //Reset buffer position and discard MAC
MiniTLS 2:527a66d0a1a9 885 buffer_set_read_offset(buffer, data_offset);
MiniTLS 2:527a66d0a1a9 886 buffer_set_length(buffer, data_length);
MiniTLS 2:527a66d0a1a9 887
MiniTLS 2:527a66d0a1a9 888 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 889 }
MiniTLS 2:527a66d0a1a9 890
MiniTLS 2:527a66d0a1a9 891
MiniTLS 2:527a66d0a1a9 892
MiniTLS 2:527a66d0a1a9 893