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.
Diff: tls/tls_record.c
- Revision:
- 3:eb324ffffd2b
- Parent:
- 2:527a66d0a1a9
--- a/tls/tls_record.c Mon Jun 09 14:57:54 2014 +0000 +++ b/tls/tls_record.c Tue Jun 10 14:22:36 2014 +0000 @@ -22,7 +22,7 @@ * \author Donatien Garnier */ -#define __DEBUG__ 0 +#define __DEBUG__ 4 #ifndef __MODULE__ #define __MODULE__ "tls_record.c" #endif @@ -138,6 +138,7 @@ //Init security record->security_rx_state = TLS_SECURITY_NONE; record->security_tx_state = TLS_SECURITY_NONE; + record->security_type = TLS_SECURITY_TYPE_NULL_NULL_NULL; //Memset keys memset(&record->client_write_mac_key, 0, TLS_HMAC_SHA1_KEY_SIZE); @@ -286,54 +287,73 @@ if( record->security_rx_state == TLS_SECURITY_ACTIVE ) { - DBG("IV + Ciphertext"); - DBG_BLOCK(buffer_dump(&record->buffer);) - buffer_t buffer_iv_header; - if( (buffer_length(&record->buffer) < 2*AES_128_BLOCK_SIZE) || ( (buffer_length(&record->buffer) % AES_128_BLOCK_SIZE) != 0 ) ) +#if CRYPTO_AES_128 + if(record->security_type == TLS_SECURITY_TYPE_AES_128_CBC_SHA) { - tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer ); - return MINITLS_ERR_PROTOCOL_NON_CONFORMANT; - } - buffer_byref(&buffer_iv_header, buffer_current_read_position(&record->buffer), AES_128_BLOCK_SIZE); //Extract IV vector - buffer_n_discard(&record->buffer, AES_128_BLOCK_SIZE); + DBG("IV + Ciphertext"); + DBG_BLOCK(buffer_dump(&record->buffer);) - //Decrypt message - ret = crypto_aes_128_cbc_decrypt( &record->cipher_rx, &buffer_iv_header, &record->buffer ); - if(ret) - { - ERR("Failed to decipher, ret %d", ret); - tls_alert_send( record, TLS_ALERT_FATAL, DECRYPT_ERROR, &record->buffer ); - return ret; - } + buffer_t buffer_iv_header; + if( (buffer_length(&record->buffer) < 2*AES_128_BLOCK_SIZE) || ( (buffer_length(&record->buffer) % AES_128_BLOCK_SIZE) != 0 ) ) + { + tls_alert_send( record, TLS_ALERT_FATAL, UNEXPECTED_MESSAGE, &record->buffer ); + return MINITLS_ERR_PROTOCOL_NON_CONFORMANT; + } + buffer_byref(&buffer_iv_header, buffer_current_read_position(&record->buffer), AES_128_BLOCK_SIZE); //Extract IV vector + buffer_n_discard(&record->buffer, AES_128_BLOCK_SIZE); - DBG("Plaintext + MAC + padding + padding length"); - DBG_BLOCK(buffer_dump(&record->buffer);) - - //Check and remove padding - size_t padding_length = *(buffer_current_write_position(&record->buffer) - 1); + //Decrypt message + ret = crypto_aes_128_cbc_decrypt( &record->cipher_rx.aes_128, &buffer_iv_header, &record->buffer ); + if(ret) + { + ERR("Failed to decipher, ret %d", ret); + tls_alert_send( record, TLS_ALERT_FATAL, DECRYPT_ERROR, &record->buffer ); + return ret; + } - if( padding_length + 1 > buffer_length(&record->buffer) ) - { - ERR("Wrong padding length"); - tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer ); - return MINITLS_ERR_CRYPTO; - } + DBG("Plaintext + MAC + padding + padding length"); + DBG_BLOCK(buffer_dump(&record->buffer);) - int p; - //Check each padding byte - for(p = 0; p < padding_length; p++) - { - if( *(buffer_current_write_position(&record->buffer) - 1 - p) != padding_length ) + //Check and remove padding + size_t padding_length = *(buffer_current_write_position(&record->buffer) - 1); + + if( padding_length + 1 > buffer_length(&record->buffer) ) { - ERR("Wrong padding"); + ERR("Wrong padding length"); tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer ); return MINITLS_ERR_CRYPTO; } - } + + int p; + //Check each padding byte + for(p = 0; p < padding_length; p++) + { + if( *(buffer_current_write_position(&record->buffer) - 1 - p) != padding_length ) + { + ERR("Wrong padding"); + tls_alert_send( record, TLS_ALERT_FATAL, BAD_RECORD_MAC, &record->buffer ); + return MINITLS_ERR_CRYPTO; + } + } - //Remove trailing padding + padding length - buffer_set_length(&record->buffer, buffer_length(&record->buffer) - 1 - padding_length); + //Remove trailing padding + padding length + buffer_set_length(&record->buffer, buffer_length(&record->buffer) - 1 - padding_length); + } + else +#endif +#if CRYPTO_ARC4 + if(record->security_type == TLS_SECURITY_TYPE_ARC4_SHA) + { + DBG("Ciphertext"); + DBG_BLOCK(buffer_dump(&record->buffer);) + + //Decrypt message + crypto_arc4_process( &record->cipher_rx.arc4, &record->buffer ); + } + else +#endif + {} DBG("Plaintext + MAC"); DBG_BLOCK(buffer_dump(&record->buffer);) @@ -487,35 +507,54 @@ DBG("Plaintext + MAC"); DBG_BLOCK(buffer_dump(payload);) - //Add padding - size_t padding_length = AES_128_BLOCK_SIZE - (buffer_length(payload) % AES_128_BLOCK_SIZE) - 1; - if(buffer_space(payload) < padding_length) +#if CRYPTO_AES_128 + if(record->security_type == TLS_SECURITY_TYPE_AES_128_CBC_SHA) { - return MINITLS_ERR_BUFFER_TOO_SMALL; - } + + //Add padding + size_t padding_length = AES_128_BLOCK_SIZE - (buffer_length(payload) % AES_128_BLOCK_SIZE) - 1; + if(buffer_space(payload) < padding_length) + { + return MINITLS_ERR_BUFFER_TOO_SMALL; + } - for(padding_item = 0; padding_item < padding_length; padding_item++) - { + for(padding_item = 0; padding_item < padding_length; padding_item++) + { + buffer_nu8_write(payload, padding_length); + } + buffer_nu8_write(payload, padding_length); - } - buffer_nu8_write(payload, padding_length); + DBG("Plaintext + MAC + Padding + Padding Length"); + DBG_BLOCK(buffer_dump(payload);) + + buffer_init( &header_iv, header_iv_data, AES_128_BLOCK_SIZE ); - DBG("Plaintext + MAC + Padding + Padding Length"); - DBG_BLOCK(buffer_dump(payload);) - - buffer_init( &header_iv, header_iv_data, AES_128_BLOCK_SIZE ); - - crypto_prng_get(record->tls_socket->minitls->prng, buffer_current_write_position(&header_iv), AES_128_BLOCK_SIZE); - buffer_n_skip(&header_iv, AES_128_BLOCK_SIZE); + crypto_prng_get(record->tls_socket->minitls->prng, buffer_current_write_position(&header_iv), AES_128_BLOCK_SIZE); + buffer_n_skip(&header_iv, AES_128_BLOCK_SIZE); - //Encrypt message - ret = crypto_aes_128_cbc_encrypt( &record->cipher_tx, &header_iv, payload ); - if(ret) + //Encrypt message + ret = crypto_aes_128_cbc_encrypt( &record->cipher_tx.aes_128, &header_iv, payload ); + if(ret) + { + ERR("Failed to encipher, ret %d", ret); + return ret; + } + } + else +#endif +#if CRYPTO_ARC4 + if(record->security_type == TLS_SECURITY_TYPE_ARC4_SHA) { - ERR("Failed to encipher, ret %d", ret); - return ret; + //No IV + buffer_init( &header_iv, NULL, 0 ); //0 Length + + //Encrypt message + crypto_arc4_process( &record->cipher_tx.arc4, payload ); } + else +#endif + {} DBG("Ciphertext"); DBG_BLOCK(buffer_dump(payload);) @@ -569,7 +608,7 @@ 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, const uint8_t* client_write_cipher_key, const uint8_t* server_write_cipher_key) { - if(security != TLS_SECURITY_TYPE_AES_128_CBC_SHA) + if( (security != TLS_SECURITY_TYPE_AES_128_CBC_SHA) && (security != TLS_SECURITY_TYPE_ARC4_SHA) ) { return MINITLS_ERR_NOT_IMPLEMENTED; } @@ -577,7 +616,7 @@ //Copy keys memcpy(&record->client_write_mac_key, client_write_mac_key, TLS_HMAC_SHA1_KEY_SIZE); memcpy(&record->server_write_mac_key, server_write_mac_key, TLS_HMAC_SHA1_KEY_SIZE); - memcpy(&record->client_write_cipher_key, client_write_cipher_key, AES_128_KEY_SIZE); + memcpy(&record->client_write_cipher_key, client_write_cipher_key, AES_128_KEY_SIZE); //TODO generic key size memcpy(&record->server_write_cipher_key, server_write_cipher_key, AES_128_KEY_SIZE); //Intialize cipher @@ -585,11 +624,27 @@ record->sequence_number_tx = 0; record->sequence_number_rx = 0; - crypto_aes_128_init(&record->cipher_tx, record->client_write_cipher_key, expand_encryption_key); - crypto_aes_128_init(&record->cipher_rx, record->server_write_cipher_key, expand_decryption_key); + switch(security) + { +#if CRYPTO_AES_128 + case TLS_SECURITY_TYPE_AES_128_CBC_SHA: + crypto_aes_128_init(&record->cipher_tx.aes_128, record->client_write_cipher_key, expand_encryption_key); + crypto_aes_128_init(&record->cipher_rx.aes_128, record->server_write_cipher_key, expand_decryption_key); + break; +#endif +#if CRYPTO_ARC4 + case TLS_SECURITY_TYPE_ARC4_SHA: + crypto_arc4_init(&record->cipher_tx.arc4, record->client_write_cipher_key, TLS_ARC4_KEY_SIZE ); + crypto_arc4_init(&record->cipher_rx.arc4, record->server_write_cipher_key, TLS_ARC4_KEY_SIZE); + break; +#endif + default: + break; + } record->security_tx_state = TLS_SECURITY_INTIALIZED; record->security_rx_state = TLS_SECURITY_INTIALIZED; + record->security_type = security; return MINITLS_OK; } @@ -684,7 +739,7 @@ return ret; } - int count = socket_recv(record->socket_fd, buffer_current_write_position(&record->buffer), size - buffer_length(&record->buffer)); + int count = socket_recv(record->socket_fd, buffer_current_write_position(&record->buffer), size /*- buffer_length(&record->buffer)*/); if( count > 0 ) { buffer_n_skip(&record->buffer, count);