ARM Shanghai IoT Team (Internal) / newMiniTLS-GPL

Fork of MiniTLS-GPL by Donatien Garnier

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tls_record.c Source File

tls_record.c

Go to the documentation of this file.
00001 /*
00002 MiniTLS - A super trimmed down TLS/SSL Library for embedded devices
00003 Author: Donatien Garnier
00004 Copyright (C) 2013-2014 AppNearMe Ltd
00005 
00006 This program is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU General Public License
00008 as published by the Free Software Foundation; either version 2
00009 of the License, or (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with this program; if not, write to the Free Software
00018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019 *//**
00020  * \file tls_record.c
00021  * \copyright Copyright (c) AppNearMe Ltd 2013
00022  * \author Donatien Garnier
00023  */
00024 
00025 #define __DEBUG__ 4
00026 #ifndef __MODULE__
00027 #define __MODULE__ "tls_record.c"
00028 #endif
00029 
00030 #include "core/fwk.h"
00031 #include "inc/minitls_config.h"
00032 #include "inc/minitls_errors.h"
00033 #include "tls_record.h"
00034 #include "tls_alert.h"
00035 
00036 #include "tls_handshake.h"
00037 #include "tls_socket.h"
00038 
00039 #include "socket/socket.h"
00040 
00041 #include "crypto/crypto_aes_128_cbc.h"
00042 #include "crypto/crypto_hmac_sha1.h"
00043 
00044 static minitls_err_t record_wait_readable(tls_record_t* record);
00045 static minitls_err_t record_wait_writeable(tls_record_t* record);
00046 
00047 static minitls_err_t record_socket_read(tls_record_t* record, size_t size);
00048 static minitls_err_t record_socket_write(tls_record_t* record, buffer_t* data);
00049 
00050 static minitls_err_t tls_mac_append( const uint8_t* key, tls_content_type_t content_type, tls_protocol_version_t version,
00051     uint64_t sequence_number, buffer_t* buffer );
00052 static minitls_err_t tls_mac_check( const uint8_t* key, tls_content_type_t content_type, tls_protocol_version_t version,
00053     uint64_t sequence_number, buffer_t* buffer );
00054 
00055 typedef struct __tls_fragment_header
00056 {
00057   tls_content_type_t type;
00058   tls_protocol_version_t version;
00059   uint16_t length; //(MAX 2^14 + 2048 = 18432)
00060 } tls_fragment_header_t;
00061 
00062 #define FRAGMENT_HEADER_SIZE 5
00063 
00064 #define DEFAULT_READ_TIMEOUT 20000
00065 #define DEFAULT_WRITE_TIMEOUT 20000
00066 
00067 minitls_err_t tls_record_init(tls_record_t* record, tls_socket_t* sock, uint8_t* buf, size_t buf_size)
00068 {
00069 
00070   record->handshake_done = false;
00071 
00072   //Open BSD socket
00073   record->socket_fd = socket_socket();
00074   if(record->socket_fd < 0)
00075   {
00076     ERR("Could not create socket descriptor");
00077     return MINITLS_ERR_SOCKET_ERROR;
00078   }
00079 
00080   record->read_timeout = DEFAULT_READ_TIMEOUT;
00081   record->write_timeout = DEFAULT_WRITE_TIMEOUT;
00082 
00083   if(buf_size >= TLS_DEFAULT_MAX_FRAGMENT_SIZE)
00084   {
00085     record->max_fragment_size = TLS_DEFAULT_MAX_FRAGMENT_SIZE;
00086   }
00087   else if( buf_size >= 4096 + TLS_ENCRYPTION_MAX_OVERHEAD )
00088   {
00089     record->max_fragment_size = 4096;
00090   }
00091   else if( buf_size >= 2048 + TLS_ENCRYPTION_MAX_OVERHEAD )
00092   {
00093     record->max_fragment_size = 2048;
00094   }
00095   else if( buf_size >= 1024 + TLS_ENCRYPTION_MAX_OVERHEAD )
00096   {
00097     record->max_fragment_size = 1024;
00098   }
00099   else if( buf_size >= 512 + TLS_ENCRYPTION_MAX_OVERHEAD )
00100   {
00101     record->max_fragment_size = 512;
00102   }
00103   else
00104   {
00105     ERR("Buffer is too small");
00106     return MINITLS_ERR_BUFFER_TOO_SMALL;
00107   }
00108 
00109   DBG("Max fragment size: %d bytes", record->max_fragment_size);
00110 
00111   if( (buf_size != TLS_DEFAULT_MAX_FRAGMENT_SIZE)
00112       && (buf_size != (record->max_fragment_size + TLS_ENCRYPTION_MAX_OVERHEAD)) )
00113   {
00114     WARN("Buffer size is not optimum");
00115   }
00116 
00117   //Initialize with oldest protocol version by default (as recommended by RFC 5246's Annex E)
00118 #if MINITLS_CFG_PROTOCOL_SSL_3
00119   record->version.major = SSL_3_VERSION_MAJOR;
00120   record->version.minor = SSL_3_VERSION_MINOR;
00121 #elif MINITLS_CFG_PROTOCOL_TLS_1_0
00122   record->version.major = TLS_1_0_VERSION_MAJOR;
00123   record->version.minor = TLS_1_0_VERSION_MINOR;
00124 #elif MINITLS_CFG_PROTOCOL_TLS_1_1
00125   record->version.major = TLS_1_1_VERSION_MAJOR;
00126   record->version.minor = TLS_1_1_VERSION_MINOR;
00127 #elif MINITLS_CFG_PROTOCOL_TLS_1_2
00128   record->version.major = TLS_1_2_VERSION_MAJOR;
00129   record->version.minor = TLS_1_2_VERSION_MINOR;
00130 #else
00131 #error No SSL/TLS protocol version enabled
00132 #endif
00133 
00134   buffer_init(&record->buffer, buf, buf_size);
00135 
00136   record->tls_socket = sock;
00137 
00138   //Init security
00139   record->security_rx_state = TLS_SECURITY_NONE;
00140   record->security_tx_state = TLS_SECURITY_NONE;
00141   record->security_type = TLS_SECURITY_TYPE_NULL_NULL_NULL;
00142 
00143   //Memset keys
00144   memset(&record->client_write_mac_key, 0, TLS_HMAC_SHA1_KEY_SIZE);
00145   memset(&record->server_write_mac_key, 0, TLS_HMAC_SHA1_KEY_SIZE);
00146   memset(&record->client_write_cipher_key, 0, AES_128_KEY_SIZE);
00147   memset(&record->server_write_cipher_key, 0, AES_128_KEY_SIZE);
00148 
00149   return MINITLS_OK;
00150 }
00151 
00152 void tls_record_set_protocol_version(tls_record_t* record, uint8_t major, uint8_t minor)
00153 {
00154   record->version.major = major;
00155   record->version.minor = minor;
00156 }
00157 
00158 void tls_record_get_protocol_version(tls_record_t* record, uint8_t* major, uint8_t* minor)
00159 {
00160   *major = record->version.major;
00161   *minor = record->version.minor;
00162 }
00163 
00164 minitls_err_t tls_record_change_cipher_spec(tls_record_t* record, bool tx_nrx)
00165 {
00166   if(tx_nrx)
00167   {
00168     if(record->security_tx_state == TLS_SECURITY_INTIALIZED)
00169     {
00170       record->security_tx_state = TLS_SECURITY_ACTIVE;
00171       return MINITLS_OK;
00172     }
00173     else
00174     {
00175       return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
00176     }
00177   }
00178   else
00179   {
00180     if(record->security_rx_state == TLS_SECURITY_INTIALIZED)
00181     {
00182       record->security_rx_state = TLS_SECURITY_ACTIVE;
00183       return MINITLS_OK;
00184     }
00185     else
00186     {
00187       return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
00188     }
00189   }
00190 }
00191 
00192 bool tls_record_is_secure(tls_record_t* record)
00193 {
00194   if( record->security_tx_state != TLS_SECURITY_ACTIVE )
00195   {
00196     return false;
00197   }
00198   if( record->security_rx_state != TLS_SECURITY_ACTIVE )
00199   {
00200     return false;
00201   }
00202   return true;
00203 }
00204 
00205 minitls_err_t tls_record_connect(tls_record_t* record, const char* hostname, uint16_t port)
00206 {
00207   DBG("Trying to connect to %s:%d", hostname, port);
00208 
00209   int r = socket_connect(record->socket_fd, hostname, port);
00210   if(r < 0)
00211   {
00212     socket_close(record->socket_fd);
00213     record->socket_fd = -1;
00214     return MINITLS_ERR_SOCKET_ERROR;
00215   }
00216 
00217   return MINITLS_OK;
00218 }
00219 
00220 minitls_err_t tls_record_process(tls_record_t* record)
00221 {
00222   //Reset buffer length
00223   buffer_reset(&record->buffer);
00224 
00225   //Read header
00226   minitls_err_t ret = record_socket_read(record, FRAGMENT_HEADER_SIZE);
00227   if(ret == MINITLS_ERR_SOCKET_CLOSED)
00228   {
00229     return MINITLS_ERR_SOCKET_CLOSED;
00230   }
00231   else if(ret)
00232   {
00233     ERR("Socket err %d", ret);
00234     tls_alert_send( record, TLS_ALERT_FATAL, INTERNAL_ERROR, &record->buffer);
00235     return ret;
00236   }
00237 
00238   //Read version
00239   tls_fragment_header_t header;
00240 
00241   header.type = buffer_nu8_read(&record->buffer);
00242   header.version.major = buffer_nu8_read(&record->buffer);
00243   header.version.minor = buffer_nu8_read(&record->buffer);
00244   header.length = buffer_nu16_read(&record->buffer);
00245 
00246 #if 1 //TODO how to relax this?
00247   if( (header.version.major != record->version.major) || (header.version.minor != record->version.minor) )
00248   {
00249     ERR("Version mismatch");
00250     tls_alert_send( record, TLS_ALERT_FATAL, PROTOCOL_VERSION, &record->buffer);
00251     return MINITLS_ERR_PROTOCOL_VERSION;
00252   }
00253 #endif
00254   //Check content type
00255   //Check that encryption level is OK for this content type
00256   switch( header.type )
00257   {
00258   //All of these are OK in plain mode
00259   case TLS_CHANGE_CIPHER_SPEC:
00260   case TLS_ALERT:
00261   case TLS_HANDSHAKE:
00262     break;
00263   //This is only acceptable in ciphered mode:
00264   case TLS_APPLICATION_DATA:
00265     if( (!tls_record_is_secure(record)) || (!record->handshake_done) )
00266     {
00267       tls_alert_send( record, TLS_ALERT_FATAL, INSUFFICIENT_SECURITY, &record->buffer);
00268       return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
00269     }
00270     break;
00271   default:
00272     tls_alert_send( record, TLS_ALERT_FATAL, ILLEGAL_PARAMETER, &record->buffer);
00273     return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
00274   }
00275 
00276   //Reset buffer
00277   buffer_reset(&record->buffer);
00278 
00279   //Read payload
00280   ret = record_socket_read(record, header.length);
00281   if(ret)
00282   {
00283     ERR("Socket err %d", ret);
00284     tls_alert_send( record, TLS_ALERT_FATAL, INTERNAL_ERROR, &record->buffer);
00285     return ret;
00286   }
00287 
00288   if( record->security_rx_state == TLS_SECURITY_ACTIVE )
00289   {
00290 
00291 #if CRYPTO_AES_128
00292     if(record->security_type == TLS_SECURITY_TYPE_AES_128_CBC_SHA)
00293     {
00294       DBG("IV + Ciphertext");
00295       DBG_BLOCK(buffer_dump(&record->buffer);)
00296 
00297       buffer_t buffer_iv_header;
00298       if( (buffer_length(&record->buffer) < 2*AES_128_BLOCK_SIZE) || ( (buffer_length(&record->buffer) % AES_128_BLOCK_SIZE) != 0 ) )
00299       {
00300         tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer );
00301         return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
00302       }
00303       buffer_byref(&buffer_iv_header, buffer_current_read_position(&record->buffer), AES_128_BLOCK_SIZE); //Extract IV vector
00304       buffer_n_discard(&record->buffer, AES_128_BLOCK_SIZE);
00305 
00306       //Decrypt message
00307       ret = crypto_aes_128_cbc_decrypt( &record->cipher_rx.aes_128, &buffer_iv_header, &record->buffer );
00308       if(ret)
00309       {
00310         ERR("Failed to decipher, ret %d", ret);
00311         tls_alert_send( record, TLS_ALERT_FATAL, DECRYPT_ERROR, &record->buffer );
00312         return ret;
00313       }
00314 
00315       DBG("Plaintext + MAC + padding + padding length");
00316       DBG_BLOCK(buffer_dump(&record->buffer);)
00317 
00318       //Check and remove padding
00319       size_t padding_length = *(buffer_current_write_position(&record->buffer) - 1);
00320 
00321       if( padding_length + 1 > buffer_length(&record->buffer) )
00322       {
00323         ERR("Wrong padding length");
00324         tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer );
00325         return MINITLS_ERR_CRYPTO;
00326       }
00327 
00328       int p;
00329       //Check each padding byte
00330       for(p = 0; p < padding_length; p++)
00331       {
00332         if( *(buffer_current_write_position(&record->buffer) - 1 - p) != padding_length )
00333         {
00334           ERR("Wrong padding");
00335           tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer );
00336           return MINITLS_ERR_CRYPTO;
00337         }
00338       }
00339 
00340       //Remove trailing padding + padding length
00341       buffer_set_length(&record->buffer, buffer_length(&record->buffer) - 1 - padding_length);
00342     }
00343     else
00344 #endif
00345 #if CRYPTO_ARC4
00346     if(record->security_type == TLS_SECURITY_TYPE_ARC4_SHA)
00347     {
00348       DBG("Ciphertext");
00349       DBG_BLOCK(buffer_dump(&record->buffer);)
00350 
00351       //Decrypt message
00352       crypto_arc4_process( &record->cipher_rx.arc4, &record->buffer );
00353     }
00354     else
00355 #endif
00356     {}
00357 
00358     DBG("Plaintext + MAC");
00359     DBG_BLOCK(buffer_dump(&record->buffer);)
00360 
00361     //Check MAC
00362     ret = tls_mac_check( record->server_write_mac_key, header.type, header.version, record->sequence_number_rx, &record->buffer );
00363     if(ret)
00364     {
00365       ERR("MAC Check failed, ret %d", ret);
00366       tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer );
00367       return ret;
00368     }
00369 
00370     DBG("Plaintext");
00371     DBG_BLOCK(buffer_dump(&record->buffer);)
00372 
00373     //Increment seq number
00374     record->sequence_number_rx++;
00375   }
00376   else
00377   {
00378     //No security
00379   }
00380 
00381   //Now dispatch depending on content type
00382   switch( header.type )
00383   {
00384   case TLS_CHANGE_CIPHER_SPEC:
00385     ret = tls_record_change_cipher_spec(record, false);
00386     if(ret)
00387     {
00388       ERR("Invalid change cipher spec request, ret %d", ret);
00389       tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer );
00390       return ret;
00391     }
00392     break;
00393   case TLS_ALERT:
00394     ret = tls_alert_process( record, &record->buffer );
00395     if(ret)
00396     {
00397       tls_record_close(record);
00398       //Close connection in any case
00399       if(ret == MINITLS_ERR_CONNECTION_CLOSED)
00400       {
00401         DBG("Connection closed by remote party");
00402         return MINITLS_OK;
00403       }
00404       //FIXME Do something
00405       ERR("Alert received, ret %d", ret);
00406       return ret;
00407     }
00408     break;
00409   case TLS_HANDSHAKE:
00410     if(/*(record->tls_socket->handshake != NULL) &&*/ !tls_handshake_is_done(&record->tls_socket->handshake))
00411     {
00412       ret = tls_handshake_process(&record->tls_socket->handshake, &record->buffer );
00413       if(ret)
00414       {
00415         ERR("Handshake process returned %d", ret);
00416         //TLS alert already sent by handshake function
00417         tls_handshake_clean(&record->tls_socket->handshake); //Cleanup handshake
00418         //record->tls_socket->handshake = NULL;
00419         return ret;
00420       }
00421       if(tls_handshake_is_done(&record->tls_socket->handshake))
00422       {
00423         tls_handshake_clean(&record->tls_socket->handshake); //Cleanup handshake
00424         //record->tls_socket->handshake = NULL;
00425         record->handshake_done = true; //Enable application data layer
00426       }
00427       return MINITLS_OK;
00428     }
00429     else
00430     {
00431       ERR("Unexpected handshake message, ret %d", ret);
00432       tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer );
00433       return ret;
00434     }
00435   case TLS_APPLICATION_DATA:
00436     //Pass message to socket layer
00437     return tls_socket_readable_callback(record->tls_socket,  &record->buffer);
00438   default:
00439     //Has already been checked above
00440     return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
00441   }
00442 
00443   return MINITLS_OK;
00444 }
00445 
00446 minitls_err_t tls_record_send(tls_record_t* record, tls_content_type_t content_type, buffer_t* payload)
00447 {
00448   minitls_err_t ret;
00449   int padding_item;
00450   /*
00451   struct {
00452       opaque IV[SecurityParameters.record_iv_length];
00453       block-ciphered struct {
00454           opaque content[TLSCompressed.length];
00455           opaque MAC[SecurityParameters.mac_length];
00456           uint8 padding[GenericBlockCipher.padding_length];
00457           uint8 padding_length;
00458       };
00459   } GenericBlockCipher;
00460   */
00461 
00462   //Check content type
00463   //Check that encryption level is OK for this content type
00464   switch( content_type )
00465   {
00466   //All of these are OK in plain mode
00467   case TLS_CHANGE_CIPHER_SPEC:
00468   case TLS_ALERT:
00469   case TLS_HANDSHAKE:
00470     break;
00471   //This is only acceptable in ciphered mode:
00472   case TLS_APPLICATION_DATA:
00473     if( (!tls_record_is_secure(record)) || (!record->handshake_done) )
00474     {
00475       tls_alert_send( record, TLS_ALERT_FATAL, INSUFFICIENT_SECURITY, &record->buffer);
00476       return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
00477     }
00478     break;
00479   default:
00480     tls_alert_send( record, TLS_ALERT_FATAL, ILLEGAL_PARAMETER, &record->buffer);
00481     return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
00482   }
00483 
00484   //Buffer must have enough space to add IV (head) + MAC (tail) + padding (tail)
00485 
00486   buffer_t header_iv;
00487   uint8_t header_iv_data[AES_128_BLOCK_SIZE];
00488   if( record->security_tx_state == TLS_SECURITY_ACTIVE )
00489   {
00490     //FIXME generate a random IV
00491 
00492     DBG("Plaintext");
00493     DBG_BLOCK(buffer_dump(payload);)
00494 
00495     //Compute & append MAC
00496     DBG("Sequence number: %d", record->sequence_number_tx);
00497     ret = tls_mac_append( record->client_write_mac_key, content_type, record->version, record->sequence_number_tx, payload );
00498     if(ret)
00499     {
00500       ERR("Could not append MAC, ret %d", ret);
00501       return ret;
00502     }
00503 
00504     //Increment sequence number
00505     record->sequence_number_tx++;
00506 
00507     DBG("Plaintext + MAC");
00508     DBG_BLOCK(buffer_dump(payload);)
00509 
00510 #if CRYPTO_AES_128
00511     if(record->security_type == TLS_SECURITY_TYPE_AES_128_CBC_SHA)
00512     {
00513 
00514       //Add padding
00515       size_t padding_length = AES_128_BLOCK_SIZE - (buffer_length(payload) % AES_128_BLOCK_SIZE) - 1;
00516       if(buffer_space(payload) < padding_length)
00517       {
00518         return MINITLS_ERR_BUFFER_TOO_SMALL;
00519       }
00520 
00521       for(padding_item = 0; padding_item < padding_length; padding_item++)
00522       {
00523         buffer_nu8_write(payload, padding_length);
00524       }
00525 
00526       buffer_nu8_write(payload, padding_length);
00527 
00528       DBG("Plaintext + MAC + Padding + Padding Length");
00529       DBG_BLOCK(buffer_dump(payload);)
00530 
00531       buffer_init( &header_iv, header_iv_data, AES_128_BLOCK_SIZE );
00532 
00533       crypto_prng_get(record->tls_socket->minitls->prng, buffer_current_write_position(&header_iv), AES_128_BLOCK_SIZE);
00534       buffer_n_skip(&header_iv, AES_128_BLOCK_SIZE);
00535 
00536       //Encrypt message
00537       ret = crypto_aes_128_cbc_encrypt( &record->cipher_tx.aes_128, &header_iv, payload );
00538       if(ret)
00539       {
00540         ERR("Failed to encipher, ret %d", ret);
00541         return ret;
00542       }
00543     }
00544     else
00545 #endif
00546 #if CRYPTO_ARC4
00547     if(record->security_type == TLS_SECURITY_TYPE_ARC4_SHA)
00548     {
00549       //No IV
00550       buffer_init( &header_iv, NULL, 0 ); //0 Length
00551 
00552       //Encrypt message
00553       crypto_arc4_process( &record->cipher_tx.arc4, payload );
00554     }
00555     else
00556 #endif
00557     {}
00558 
00559     DBG("Ciphertext");
00560     DBG_BLOCK(buffer_dump(payload);)
00561   }
00562   else
00563   {
00564     buffer_init( &header_iv, NULL, 0 ); //0 Length
00565   }
00566 
00567   //Now send message header
00568   tls_fragment_header_t header;
00569   header.type = content_type;
00570   header.version.major = record->version.major;
00571   header.version.minor = record->version.minor;
00572   header.length = buffer_length( &header_iv ) + buffer_length(payload);
00573 
00574   buffer_t header_fragment;
00575   uint8_t header_fragment_data[FRAGMENT_HEADER_SIZE];
00576 
00577   buffer_init( &header_fragment, header_fragment_data, FRAGMENT_HEADER_SIZE );
00578 
00579   buffer_nu8_write(&header_fragment, header.type);
00580   buffer_nu8_write(&header_fragment, header.version.major);
00581   buffer_nu8_write(&header_fragment, header.version.minor);
00582   buffer_nu16_write(&header_fragment, header.length);
00583 
00584   //Send fragment header
00585   ret = record_socket_write(record, &header_fragment);
00586   if(ret)
00587   {
00588     return ret;
00589   }
00590 
00591   //Send IV
00592   ret = record_socket_write(record, &header_iv);
00593   if(ret)
00594   {
00595     return ret;
00596   }
00597 
00598   //Send payload
00599   ret = record_socket_write(record, payload);
00600   if(ret)
00601   {
00602     return ret;
00603   }
00604 
00605   return MINITLS_OK;
00606 }
00607 
00608 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,
00609     const uint8_t* client_write_cipher_key, const uint8_t* server_write_cipher_key)
00610 {
00611   if( (security != TLS_SECURITY_TYPE_AES_128_CBC_SHA) && (security != TLS_SECURITY_TYPE_ARC4_SHA) )
00612   {
00613     return MINITLS_ERR_NOT_IMPLEMENTED;
00614   }
00615 
00616   //Copy keys
00617   memcpy(&record->client_write_mac_key, client_write_mac_key, TLS_HMAC_SHA1_KEY_SIZE);
00618   memcpy(&record->server_write_mac_key, server_write_mac_key, TLS_HMAC_SHA1_KEY_SIZE);
00619   memcpy(&record->client_write_cipher_key, client_write_cipher_key, AES_128_KEY_SIZE); //TODO generic key size
00620   memcpy(&record->server_write_cipher_key, server_write_cipher_key, AES_128_KEY_SIZE);
00621 
00622   //Intialize cipher
00623 
00624   record->sequence_number_tx = 0;
00625   record->sequence_number_rx = 0;
00626 
00627   switch(security)
00628   {
00629 #if CRYPTO_AES_128
00630   case TLS_SECURITY_TYPE_AES_128_CBC_SHA:
00631     crypto_aes_128_init(&record->cipher_tx.aes_128, record->client_write_cipher_key, expand_encryption_key);
00632     crypto_aes_128_init(&record->cipher_rx.aes_128, record->server_write_cipher_key, expand_decryption_key);
00633     break;
00634 #endif
00635 #if CRYPTO_ARC4
00636   case TLS_SECURITY_TYPE_ARC4_SHA:
00637     crypto_arc4_init(&record->cipher_tx.arc4, record->client_write_cipher_key, TLS_ARC4_KEY_SIZE );
00638     crypto_arc4_init(&record->cipher_rx.arc4, record->server_write_cipher_key, TLS_ARC4_KEY_SIZE);
00639     break;
00640 #endif
00641   default:
00642     break;
00643   }
00644 
00645   record->security_tx_state = TLS_SECURITY_INTIALIZED;
00646   record->security_rx_state = TLS_SECURITY_INTIALIZED;
00647   record->security_type = security;
00648 
00649   return MINITLS_OK;
00650 }
00651 
00652 minitls_err_t tls_record_close(tls_record_t* record)
00653 {
00654   if(record->socket_fd < 0) //Already closed
00655   {
00656     return MINITLS_OK;
00657   }
00658 
00659   //Don't really care about the return
00660   tls_alert_send(record, TLS_ALERT_WARNING, CLOSE_NOTIFY, &record->buffer);
00661 
00662   //Close socket
00663   socket_close(record->socket_fd);
00664   record->socket_fd = -1;
00665 
00666   return MINITLS_OK;
00667 }
00668 
00669 minitls_err_t tls_record_set_read_timeout(tls_record_t* record, int timeout)
00670 {
00671   record->read_timeout = timeout;
00672 
00673   return MINITLS_OK;
00674 }
00675 
00676 minitls_err_t tls_record_set_write_timeout(tls_record_t* record, int timeout)
00677 {
00678   record->write_timeout = timeout;
00679 
00680   return MINITLS_OK;
00681 }
00682 
00683 minitls_err_t record_wait_readable(tls_record_t* record)
00684 {
00685   if(record->socket_fd < 0)
00686   {
00687     return MINITLS_ERR_SOCKET_CLOSED;
00688   }
00689 
00690   //Wait for record to be readable
00691   int ret = socket_wait_readable(record->socket_fd, record->read_timeout );
00692   if( ret < 0 )
00693   {
00694     //Timeout
00695     return MINITLS_ERR_TIMEOUT;
00696   }
00697   return MINITLS_OK;
00698 }
00699 
00700 minitls_err_t record_wait_writeable(tls_record_t* record)
00701 {
00702   if(record->socket_fd < 0)
00703   {
00704     return MINITLS_ERR_SOCKET_CLOSED;
00705   }
00706 
00707   //Wait for record to be writeable
00708   int ret = socket_wait_writeable(record->socket_fd, record->write_timeout );
00709   if( ret < 0 )
00710   {
00711     //Timeout
00712     return MINITLS_ERR_TIMEOUT;
00713   }
00714   return MINITLS_OK;
00715 }
00716 
00717 minitls_err_t record_socket_read(tls_record_t* record, size_t size)
00718 {
00719   minitls_err_t ret;
00720   if(record->socket_fd < 0)
00721   {
00722     return MINITLS_ERR_SOCKET_CLOSED;
00723   }
00724 
00725   DBG("Trying to read %d bytes", size);
00726   while(size > 0)
00727   {
00728     //Read Fragment length
00729     if( buffer_space(&record->buffer) < size )
00730     {
00731       ERR("Won't be able to read packet (%d bytes to read - %d bytes of space)", size, buffer_space(&record->buffer));
00732       return MINITLS_ERR_BUFFER_TOO_SMALL;
00733     }
00734 
00735     ret = record_wait_readable(record);
00736     if(ret)
00737     {
00738      ERR("Timeout");
00739      return ret;
00740     }
00741 
00742     int count = socket_recv(record->socket_fd, buffer_current_write_position(&record->buffer), size /*- buffer_length(&record->buffer)*/);
00743     if( count > 0 )
00744     {
00745       buffer_n_skip(&record->buffer, count);
00746       size -= count;
00747     }
00748     else if( count == 0 )
00749     {
00750       WARN("Socket closed");
00751       return MINITLS_ERR_SOCKET_CLOSED;
00752     }
00753     else
00754     {
00755       ERR("Error (returned %d)", count);
00756       return MINITLS_ERR_SOCKET_ERROR;
00757     }
00758   }
00759 
00760   DBG_BLOCK(buffer_dump(&record->buffer);)
00761 
00762   return MINITLS_OK;
00763 }
00764 
00765 minitls_err_t record_socket_write(tls_record_t* record, buffer_t* data)
00766 {
00767   minitls_err_t ret;
00768   if(record->socket_fd < 0)
00769   {
00770     return MINITLS_ERR_SOCKET_CLOSED;
00771   }
00772 
00773   DBG("Trying to write %d bytes", buffer_length(data));
00774   DBG_BLOCK(buffer_dump(data);)
00775   while(buffer_length(data) > 0)
00776   {
00777     ret = record_wait_writeable(record);
00778     if(ret)
00779     {
00780      ERR("Timeout");
00781      return ret;
00782     }
00783 
00784     int count = socket_send(record->socket_fd, buffer_current_read_position(data), buffer_length(data));
00785     if( count > 0 )
00786     {
00787       buffer_n_discard(data, count);
00788     }
00789     else if( count == 0 )
00790     {
00791       WARN("Socket closed");
00792       return MINITLS_ERR_SOCKET_CLOSED;
00793     }
00794     else
00795     {
00796       ERR("Error (returned %d)", count);
00797       return MINITLS_ERR_SOCKET_ERROR;
00798     }
00799   }
00800   DBG("Done");
00801   return MINITLS_OK;
00802 }
00803 
00804 
00805 minitls_err_t tls_mac_append( const uint8_t* key, tls_content_type_t content_type, tls_protocol_version_t version,
00806     uint64_t sequence_number, buffer_t* buffer )
00807 {
00808   crypto_hmac_sha1_t mac;
00809   crypto_hmac_sha1_init(&mac, key, TLS_HMAC_SHA1_KEY_SIZE);
00810 
00811   if( buffer_space(buffer) < HMAC_SHA1_SIZE )
00812   {
00813     return MINITLS_ERR_BUFFER_TOO_SMALL;
00814   }
00815 
00816   uint8_t header_buf[13];
00817   buffer_t header;
00818 
00819   buffer_init(&header, header_buf, 13);
00820 
00821   buffer_nu64_write(&header, sequence_number);
00822 
00823   buffer_nu8_write(&header, content_type);
00824 
00825   buffer_nu8_write(&header, version.major);
00826   buffer_nu8_write(&header, version.minor);
00827 
00828   buffer_nu16_write(&header, buffer_length(buffer));
00829 
00830   crypto_hmac_sha1_update(&mac, header_buf, 13);
00831   crypto_hmac_sha1_update(&mac, buffer_current_read_position(buffer), buffer_length(buffer));
00832   crypto_hmac_sha1_end(&mac, buffer_current_write_position(buffer));
00833   buffer_n_skip(buffer, HMAC_SHA1_SIZE);
00834 
00835   return MINITLS_OK;
00836 }
00837 
00838 minitls_err_t tls_mac_check( const uint8_t* key, tls_content_type_t content_type, tls_protocol_version_t version,
00839     uint64_t sequence_number, buffer_t* buffer )
00840 {
00841   crypto_hmac_sha1_t mac;
00842   crypto_hmac_sha1_init(&mac, key, TLS_HMAC_SHA1_KEY_SIZE);
00843 
00844   if( buffer_length(buffer) < HMAC_SHA1_SIZE )
00845   {
00846     return MINITLS_ERR_PROTOCOL_NON_CONFORMANT;
00847   }
00848 
00849   size_t data_offset = buffer_get_read_offset(buffer);
00850   size_t data_length = buffer_length(buffer) - HMAC_SHA1_SIZE;
00851 
00852   uint8_t check[HMAC_SHA1_SIZE];
00853 
00854   uint8_t header_buf[13];
00855   buffer_t header;
00856 
00857   buffer_init(&header, header_buf, 13);
00858 
00859   buffer_nu64_write(&header, sequence_number);
00860 
00861   buffer_nu8_write(&header, content_type);
00862 
00863   buffer_nu8_write(&header, version.major);
00864   buffer_nu8_write(&header, version.minor);
00865 
00866   buffer_nu16_write(&header, data_length);
00867 
00868   crypto_hmac_sha1_update(&mac, header_buf, 13);
00869   crypto_hmac_sha1_update(&mac, buffer_current_read_position(buffer), data_length);
00870   buffer_n_discard(buffer, data_length);
00871   crypto_hmac_sha1_end(&mac, check);
00872 
00873   if( memcmp(buffer_current_read_position(buffer), check, HMAC_SHA1_SIZE) != 0 )
00874   {
00875     ERR("MAC differs; computed MAC was:");
00876 
00877     buffer_t computed_mac;
00878     buffer_byref(&computed_mac, check, HMAC_SHA1_SIZE);
00879     DBG_BLOCK(buffer_dump(&computed_mac);)
00880 
00881     return MINITLS_ERR_WRONG_MAC;
00882   }
00883 
00884   //Reset buffer position and discard MAC
00885   buffer_set_read_offset(buffer, data_offset);
00886   buffer_set_length(buffer, data_length);
00887 
00888   return MINITLS_OK;
00889 }
00890 
00891 
00892 
00893