Skip to content

Commit

Permalink
Merge pull request #848 from spark/feature/electron/session_move
Browse files Browse the repository at this point in the history
Feature/electron/session move
  • Loading branch information
m-mcgowan committed Feb 1, 2016
2 parents 925b189 + 0a68dc8 commit 7e4ecf9
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 23 deletions.
2 changes: 1 addition & 1 deletion communication/src/coap_channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ ProtocolError CoAPMessageStore::receive(Message& msg, Channel& channel, system_t
if (msg) {
msg->notify_delivered_nak();
}
channel.command(Channel::REFRESH_SESSION, nullptr);
channel.command(Channel::DISCARD_SESSION, nullptr);
}
DEBUG("recieved ACK for message %x", id);
if (!clear_message(id)) { // message didn't exist, means it's already been acknoweldged or is unknown.
Expand Down
55 changes: 39 additions & 16 deletions communication/src/dtls_message_channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ ProtocolError DTLSMessageChannel::init(
this->coap_state = coap_state;
int ret;
this->callbacks = callbacks;

this->device_id = device_id;
keys_checksum = compute_checksum(server_public, server_public_len, core_private, core_private_len);

ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,
Expand Down Expand Up @@ -231,7 +231,28 @@ ProtocolError DTLSMessageChannel::init(

inline int DTLSMessageChannel::send(const uint8_t* data, size_t len)
{
return callbacks.send(data, len, callbacks.tx_context);
if (move_session && len && data[0]==23)
{
uint8_t d[len+DEVICE_ID_LEN+1];
memcpy(d, data, len);
d[0] = 254;
memcpy(d+len, device_id, DEVICE_ID_LEN);
d[len+DEVICE_ID_LEN] = DEVICE_ID_LEN;
int result = callbacks.send(d, len+DEVICE_ID_LEN+1, callbacks.tx_context);
// hide the increased length from DTLS
if (result==int(len+DEVICE_ID_LEN+1))
result = len;
return result;
}
else
return callbacks.send(data, len, callbacks.tx_context);
}

void DTLSMessageChannel::reset_session()
{
cancel_move_session();
mbedtls_ssl_session_reset(&ssl_context);
sessionPersist.clear(callbacks.save);
}

inline int DTLSMessageChannel::recv(uint8_t* data, size_t len)
Expand All @@ -243,7 +264,7 @@ inline int DTLSMessageChannel::recv(uint8_t* data, size_t len)
return size;
}

int DTLSMessageChannel::send_( void *ctx, const unsigned char *buf, size_t len ) {
int DTLSMessageChannel::send_(void *ctx, const unsigned char *buf, size_t len ) {
DTLSMessageChannel* channel = (DTLSMessageChannel*)ctx;
int count = channel->send(buf, len);
if (count == 0)
Expand All @@ -254,9 +275,10 @@ int DTLSMessageChannel::send_( void *ctx, const unsigned char *buf, size_t len )

int DTLSMessageChannel::recv_( void *ctx, unsigned char *buf, size_t len ) {
DTLSMessageChannel* channel = (DTLSMessageChannel*)ctx;

int count = channel->recv(buf, len);
if (count == 0) {
// 0 means EOF in this context
// 0 means no more data available yet
return MBEDTLS_ERR_SSL_WANT_READ;
}
return count;
Expand Down Expand Up @@ -332,8 +354,7 @@ ProtocolError DTLSMessageChannel::establish()
}
else // no session or clear
{
sessionPersist.clear(callbacks.save);
mbedtls_ssl_session_reset(&ssl_context);
reset_session();
ProtocolError error = setup_context();
if (error)
return error;
Expand Down Expand Up @@ -362,9 +383,8 @@ ProtocolError DTLSMessageChannel::establish()

if (ret)
{
mbedtls_ssl_session_reset(&ssl_context);
DEBUG("handshake failed -%x", -ret);
sessionPersist.clear(callbacks.save);
reset_session();
}
else
{
Expand Down Expand Up @@ -402,7 +422,7 @@ ProtocolError DTLSMessageChannel::receive(Message& message)
command(CLOSE);
break;
default:
mbedtls_ssl_session_reset(&ssl_context);
reset_session();
return IO_ERROR;
}
}
Expand Down Expand Up @@ -452,8 +472,8 @@ ProtocolError DTLSMessageChannel::send(Message& message)
int ret = mbedtls_ssl_write(&ssl_context, message.buf(), message.length());
if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
{
mbedtls_ssl_session_reset(&ssl_context);
return IO_ERROR;
reset_session();
return IO_ERROR;
}
sessionPersist.update(&ssl_context, callbacks.save, coap_state ? *coap_state : 0);
return NO_ERROR;
Expand All @@ -470,13 +490,16 @@ ProtocolError DTLSMessageChannel::command(Command command, void* arg)
switch (command)
{
case CLOSE:
sessionPersist.clear(callbacks.save);
mbedtls_ssl_session_reset(&ssl_context);
reset_session();
break;
case REFRESH_SESSION:
sessionPersist.clear(callbacks.save);
mbedtls_ssl_session_reset(&ssl_context);

case DISCARD_SESSION:
reset_session();
return IO_ERROR; //force re-establish

case MOVE_SESSION:
move_session = true;
break;
}
return NO_ERROR;
}
Expand Down
12 changes: 11 additions & 1 deletion communication/src/dtls_message_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ namespace particle
namespace protocol
{

/**
* Please centralize this somewhere else!
*/
const size_t DEVICE_ID_LEN = 12;

/**
* This implements the lightweight and RSA encrypted handshake, AES session encryption over a TCP Stream.
*
Expand Down Expand Up @@ -88,6 +93,8 @@ class DTLSMessageChannel: public BufferMessageChannel<PROTOCOL_BUFFER_SIZE>
* The next message ID for new messages over this channel.
*/
message_id_t* coap_state;
bool move_session;
const uint8_t* device_id;

void init();
void dispose();
Expand All @@ -103,9 +110,12 @@ class DTLSMessageChannel: public BufferMessageChannel<PROTOCOL_BUFFER_SIZE>

ProtocolError setup_context();

void cancel_move_session() { move_session = false; }

void reset_session();

public:
DTLSMessageChannel() : coap_state(nullptr) {}
DTLSMessageChannel() : coap_state(nullptr), move_session(false) {}

ProtocolError init(const uint8_t* core_private, size_t core_private_len,
const uint8_t* core_public, size_t core_public_len,
Expand Down
2 changes: 1 addition & 1 deletion communication/src/dtls_protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ void DTLSProtocol::init(const char *id,
ProtocolError error = channel.init(keys.core_private, determine_der_length(keys.core_private, MAX_DEVICE_PRIVATE_KEY_LENGTH),
extracted_core_public, len,
keys.server_public, determine_der_length(keys.server_public, MAX_SERVER_PUBLIC_KEY_LENGTH),
(const uint8_t*)id, channelCallbacks, &channel.next_id_ref());
(const uint8_t*)device_id, channelCallbacks, &channel.next_id_ref());
if (error)
{
WARN("error initializing DTLS channel: %d", error);
Expand Down
16 changes: 13 additions & 3 deletions communication/src/message_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,19 @@ struct Channel
{
enum Command
{
CLOSE,

REFRESH_SESSION,
CLOSE = 0,

/**
* Discard the current session. This performs a new
* DTLS handshake with the server.
*/
DISCARD_SESSION = 1,

/**
* Sends a special DTLS packet to the server that indicates
* the session has moved.
*/
MOVE_SESSION = 2,
};


Expand Down
8 changes: 7 additions & 1 deletion communication/src/protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ ProtocolError Protocol::handle_key_change(Message& message)
uint8_t option_idx = 7 + (buf[0] & 0xF);
if (buf[option_idx]==1)
{
result = channel.command(MessageChannel::REFRESH_SESSION);
result = channel.command(MessageChannel::DISCARD_SESSION);
}
}
return result;
Expand Down Expand Up @@ -219,6 +219,12 @@ int Protocol::begin()
return error;
}

if (session_resumed)
{
// for now, unconditionally move the session on resumption
channel.command(MessageChannel::MOVE_SESSION, nullptr);
}

// hello not needed because it's already been sent and the server maintains device state
if (session_resumed && channel.is_unreliable() && (flags & SKIP_SESSION_RESUME_HELLO))
{
Expand Down

0 comments on commit 7e4ecf9

Please sign in to comment.