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:
Fri Jun 06 10:49:02 2014 +0000
Revision:
0:35aa5be3b78d
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MiniTLS 0:35aa5be3b78d 1 /*
MiniTLS 0:35aa5be3b78d 2 MuTLS - A super trimmed down TLS/SSL Library for embedded devices
MiniTLS 0:35aa5be3b78d 3 Author: Donatien Garnier
MiniTLS 0:35aa5be3b78d 4 Copyright (C) 2013-2014 AppNearMe Ltd
MiniTLS 0:35aa5be3b78d 5
MiniTLS 0:35aa5be3b78d 6 This program is free software; you can redistribute it and/or
MiniTLS 0:35aa5be3b78d 7 modify it under the terms of the GNU General Public License
MiniTLS 0:35aa5be3b78d 8 as published by the Free Software Foundation; either version 2
MiniTLS 0:35aa5be3b78d 9 of the License, or (at your option) any later version.
MiniTLS 0:35aa5be3b78d 10
MiniTLS 0:35aa5be3b78d 11 This program is distributed in the hope that it will be useful,
MiniTLS 0:35aa5be3b78d 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
MiniTLS 0:35aa5be3b78d 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MiniTLS 0:35aa5be3b78d 14 GNU General Public License for more details.
MiniTLS 0:35aa5be3b78d 15
MiniTLS 0:35aa5be3b78d 16 You should have received a copy of the GNU General Public License
MiniTLS 0:35aa5be3b78d 17 along with this program; if not, write to the Free Software
MiniTLS 0:35aa5be3b78d 18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
MiniTLS 0:35aa5be3b78d 19 *//**
MiniTLS 0:35aa5be3b78d 20 * \file tls_socket.c
MiniTLS 0:35aa5be3b78d 21 * \copyright Copyright (c) AppNearMe Ltd 2013
MiniTLS 0:35aa5be3b78d 22 * \author Donatien Garnier
MiniTLS 0:35aa5be3b78d 23 */
MiniTLS 0:35aa5be3b78d 24
MiniTLS 0:35aa5be3b78d 25 #define __DEBUG__ 0
MiniTLS 0:35aa5be3b78d 26 #ifndef __MODULE__
MiniTLS 0:35aa5be3b78d 27 #define __MODULE__ "tls_socket.c"
MiniTLS 0:35aa5be3b78d 28 #endif
MiniTLS 0:35aa5be3b78d 29
MiniTLS 0:35aa5be3b78d 30
MiniTLS 0:35aa5be3b78d 31 #include "core/fwk.h"
MiniTLS 0:35aa5be3b78d 32 #include "inc/mutls_errors.h"
MiniTLS 0:35aa5be3b78d 33
MiniTLS 0:35aa5be3b78d 34 #include "tls_socket.h"
MiniTLS 0:35aa5be3b78d 35
MiniTLS 0:35aa5be3b78d 36 mutls_err_t tls_socket_init(tls_socket_t* socket, mutls_t* mutls,
MiniTLS 0:35aa5be3b78d 37 uint8_t* write_buffer, size_t write_buffer_size, uint8_t* read_buffer, size_t read_buffer_size)
MiniTLS 0:35aa5be3b78d 38 {
MiniTLS 0:35aa5be3b78d 39 socket->mutls = mutls;
MiniTLS 0:35aa5be3b78d 40
MiniTLS 0:35aa5be3b78d 41 socket->events = NULL;
MiniTLS 0:35aa5be3b78d 42
MiniTLS 0:35aa5be3b78d 43 socket->read_buffer = NULL;
MiniTLS 0:35aa5be3b78d 44 buffer_init(&socket->write_buffer, write_buffer, write_buffer_size);
MiniTLS 0:35aa5be3b78d 45
MiniTLS 0:35aa5be3b78d 46 socket->session.session_id_length = 0;
MiniTLS 0:35aa5be3b78d 47
MiniTLS 0:35aa5be3b78d 48 mutls_err_t ret = tls_record_init(&socket->record, socket, read_buffer, read_buffer_size);
MiniTLS 0:35aa5be3b78d 49 if(ret)
MiniTLS 0:35aa5be3b78d 50 {
MiniTLS 0:35aa5be3b78d 51 return ret;
MiniTLS 0:35aa5be3b78d 52 }
MiniTLS 0:35aa5be3b78d 53
MiniTLS 0:35aa5be3b78d 54 ret = tls_handshake_init(&socket->handshake, socket);
MiniTLS 0:35aa5be3b78d 55 if(ret)
MiniTLS 0:35aa5be3b78d 56 {
MiniTLS 0:35aa5be3b78d 57 return ret;
MiniTLS 0:35aa5be3b78d 58 }
MiniTLS 0:35aa5be3b78d 59
MiniTLS 0:35aa5be3b78d 60 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 61 }
MiniTLS 0:35aa5be3b78d 62
MiniTLS 0:35aa5be3b78d 63 mutls_err_t tls_socket_connect(tls_socket_t* socket, const char* hostname, uint16_t port, int timeout)
MiniTLS 0:35aa5be3b78d 64 {
MiniTLS 0:35aa5be3b78d 65 mutls_err_t ret = tls_record_connect(&socket->record, hostname, port);
MiniTLS 0:35aa5be3b78d 66 if(ret)
MiniTLS 0:35aa5be3b78d 67 {
MiniTLS 0:35aa5be3b78d 68 ERR("Could not connect");
MiniTLS 0:35aa5be3b78d 69 return ret;
MiniTLS 0:35aa5be3b78d 70 }
MiniTLS 0:35aa5be3b78d 71
MiniTLS 0:35aa5be3b78d 72 //TODO we could allocate the handshake structure here to save memory
MiniTLS 0:35aa5be3b78d 73
MiniTLS 0:35aa5be3b78d 74 ret = tls_handshake_start(&socket->handshake);
MiniTLS 0:35aa5be3b78d 75 if(ret)
MiniTLS 0:35aa5be3b78d 76 {
MiniTLS 0:35aa5be3b78d 77 ERR("Could not start handshake");
MiniTLS 0:35aa5be3b78d 78 return ret;
MiniTLS 0:35aa5be3b78d 79 }
MiniTLS 0:35aa5be3b78d 80
MiniTLS 0:35aa5be3b78d 81 //Now wait for handshake to finish processing (or fail)
MiniTLS 0:35aa5be3b78d 82 while(!tls_handshake_is_done(&socket->handshake))
MiniTLS 0:35aa5be3b78d 83 {
MiniTLS 0:35aa5be3b78d 84 DBG("Handshaking...");
MiniTLS 0:35aa5be3b78d 85 ret = tls_record_process(&socket->record);
MiniTLS 0:35aa5be3b78d 86 if(ret)
MiniTLS 0:35aa5be3b78d 87 {
MiniTLS 0:35aa5be3b78d 88 ERR("Processing error");
MiniTLS 0:35aa5be3b78d 89 return ret;
MiniTLS 0:35aa5be3b78d 90 }
MiniTLS 0:35aa5be3b78d 91 }
MiniTLS 0:35aa5be3b78d 92
MiniTLS 0:35aa5be3b78d 93 DBG("Connected");
MiniTLS 0:35aa5be3b78d 94
MiniTLS 0:35aa5be3b78d 95 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 96 }
MiniTLS 0:35aa5be3b78d 97
MiniTLS 0:35aa5be3b78d 98 void tls_socket_copy_session(tls_socket_t* to, tls_socket_t* from)
MiniTLS 0:35aa5be3b78d 99 {
MiniTLS 0:35aa5be3b78d 100 memcpy(&to->session, &from->session, sizeof(tls_session_t));
MiniTLS 0:35aa5be3b78d 101 }
MiniTLS 0:35aa5be3b78d 102
MiniTLS 0:35aa5be3b78d 103 //Events API -- select like
MiniTLS 0:35aa5be3b78d 104 mutls_err_t tls_socket_event_list_init(tls_socket_event_list_t* list)
MiniTLS 0:35aa5be3b78d 105 {
MiniTLS 0:35aa5be3b78d 106 list->head = NULL;
MiniTLS 0:35aa5be3b78d 107
MiniTLS 0:35aa5be3b78d 108 //Create semaphore
MiniTLS 0:35aa5be3b78d 109 /* list->sem = rtos_sem_create(1, 0);*/
MiniTLS 0:35aa5be3b78d 110 /*if(list->sem == NULL)
MiniTLS 0:35aa5be3b78d 111 {
MiniTLS 0:35aa5be3b78d 112 return TLS_ERR_MEMORY;
MiniTLS 0:35aa5be3b78d 113 }*/ //FIXME
MiniTLS 0:35aa5be3b78d 114
MiniTLS 0:35aa5be3b78d 115 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 116 }
MiniTLS 0:35aa5be3b78d 117
MiniTLS 0:35aa5be3b78d 118 mutls_err_t tls_socket_event_init_and_register(tls_socket_event_t* event, tls_socket_event_list_t* list, tls_socket_t* socket, bool read, bool write)
MiniTLS 0:35aa5be3b78d 119 {
MiniTLS 0:35aa5be3b78d 120 //Init event
MiniTLS 0:35aa5be3b78d 121 event->socket = socket;
MiniTLS 0:35aa5be3b78d 122 event->read = read;
MiniTLS 0:35aa5be3b78d 123 event->write = write;
MiniTLS 0:35aa5be3b78d 124 event->list = list;
MiniTLS 0:35aa5be3b78d 125 event->socket_list_next = NULL;
MiniTLS 0:35aa5be3b78d 126 event->event_list_next = NULL;
MiniTLS 0:35aa5be3b78d 127
MiniTLS 0:35aa5be3b78d 128 //Add to select list (tail)
MiniTLS 0:35aa5be3b78d 129 if(list->head != NULL)
MiniTLS 0:35aa5be3b78d 130 {
MiniTLS 0:35aa5be3b78d 131 tls_socket_event_t* previous_event = list->head;
MiniTLS 0:35aa5be3b78d 132 while( previous_event->event_list_next != NULL )
MiniTLS 0:35aa5be3b78d 133 {
MiniTLS 0:35aa5be3b78d 134 previous_event = previous_event->event_list_next;
MiniTLS 0:35aa5be3b78d 135 }
MiniTLS 0:35aa5be3b78d 136 previous_event->event_list_next = event;
MiniTLS 0:35aa5be3b78d 137 }
MiniTLS 0:35aa5be3b78d 138 else
MiniTLS 0:35aa5be3b78d 139 {
MiniTLS 0:35aa5be3b78d 140 list->head = event;
MiniTLS 0:35aa5be3b78d 141 }
MiniTLS 0:35aa5be3b78d 142
MiniTLS 0:35aa5be3b78d 143 //Add to socket's event list (tail)
MiniTLS 0:35aa5be3b78d 144 if(socket->events != NULL)
MiniTLS 0:35aa5be3b78d 145 {
MiniTLS 0:35aa5be3b78d 146 tls_socket_event_t* previous_event = socket->events;
MiniTLS 0:35aa5be3b78d 147 while( previous_event->socket_list_next != NULL )
MiniTLS 0:35aa5be3b78d 148 {
MiniTLS 0:35aa5be3b78d 149 previous_event = previous_event->socket_list_next;
MiniTLS 0:35aa5be3b78d 150 }
MiniTLS 0:35aa5be3b78d 151 previous_event->socket_list_next = event;
MiniTLS 0:35aa5be3b78d 152 }
MiniTLS 0:35aa5be3b78d 153 else
MiniTLS 0:35aa5be3b78d 154 {
MiniTLS 0:35aa5be3b78d 155 socket->events = event;
MiniTLS 0:35aa5be3b78d 156 }
MiniTLS 0:35aa5be3b78d 157
MiniTLS 0:35aa5be3b78d 158 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 159 }
MiniTLS 0:35aa5be3b78d 160
MiniTLS 0:35aa5be3b78d 161 mutls_err_t tls_socket_event_list_wait(tls_socket_event_list_t* list, int timeout) //All events unregistered at the end of wait, timeout in ms, -1 for infinite timeout
MiniTLS 0:35aa5be3b78d 162 {/*
MiniTLS 0:35aa5be3b78d 163 if( rtos_sem_get(list->sem, timeout) ) //FIXME
MiniTLS 0:35aa5be3b78d 164 {*/
MiniTLS 0:35aa5be3b78d 165 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 166 /*}
MiniTLS 0:35aa5be3b78d 167 else
MiniTLS 0:35aa5be3b78d 168 {
MiniTLS 0:35aa5be3b78d 169 return TLS_ERR_TIMEOUT;
MiniTLS 0:35aa5be3b78d 170 }*/
MiniTLS 0:35aa5be3b78d 171 }
MiniTLS 0:35aa5be3b78d 172
MiniTLS 0:35aa5be3b78d 173 //These calls are non-blocking
MiniTLS 0:35aa5be3b78d 174 mutls_err_t tls_socket_read(tls_socket_t* socket, uint8_t* bytes, size_t max_size, size_t* read_size)
MiniTLS 0:35aa5be3b78d 175 {
MiniTLS 0:35aa5be3b78d 176 DBG("Reading at most %d bytes", max_size);
MiniTLS 0:35aa5be3b78d 177 if(socket->read_buffer == NULL) //Socket is not ready
MiniTLS 0:35aa5be3b78d 178 {
MiniTLS 0:35aa5be3b78d 179 WARN("Socket is not ready or has been closed");
MiniTLS 0:35aa5be3b78d 180 *read_size = 0;
MiniTLS 0:35aa5be3b78d 181 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 182 }
MiniTLS 0:35aa5be3b78d 183
MiniTLS 0:35aa5be3b78d 184 size_t length = buffer_length(socket->read_buffer);
MiniTLS 0:35aa5be3b78d 185 *read_size = MIN(max_size, length);
MiniTLS 0:35aa5be3b78d 186
MiniTLS 0:35aa5be3b78d 187 buffer_nbytes_read(socket->read_buffer, bytes, *read_size);
MiniTLS 0:35aa5be3b78d 188
MiniTLS 0:35aa5be3b78d 189 DBG("%d bytes read", *read_size);
MiniTLS 0:35aa5be3b78d 190
MiniTLS 0:35aa5be3b78d 191 //If buffer has been fully read, invalidate read_buffer
MiniTLS 0:35aa5be3b78d 192 if( buffer_length(socket->read_buffer) == 0 )
MiniTLS 0:35aa5be3b78d 193 {
MiniTLS 0:35aa5be3b78d 194 socket->read_buffer = NULL;
MiniTLS 0:35aa5be3b78d 195 }
MiniTLS 0:35aa5be3b78d 196
MiniTLS 0:35aa5be3b78d 197 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 198 }
MiniTLS 0:35aa5be3b78d 199
MiniTLS 0:35aa5be3b78d 200 mutls_err_t tls_socket_write(tls_socket_t* socket, uint8_t* bytes, size_t size, size_t* written_size)
MiniTLS 0:35aa5be3b78d 201 {
MiniTLS 0:35aa5be3b78d 202 size_t length = buffer_space(&socket->write_buffer);
MiniTLS 0:35aa5be3b78d 203 *written_size = MIN(size, length);
MiniTLS 0:35aa5be3b78d 204
MiniTLS 0:35aa5be3b78d 205 buffer_nbytes_write(&socket->write_buffer, bytes, *written_size);
MiniTLS 0:35aa5be3b78d 206
MiniTLS 0:35aa5be3b78d 207 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 208 }
MiniTLS 0:35aa5be3b78d 209
MiniTLS 0:35aa5be3b78d 210 mutls_err_t tls_socket_flush_read(tls_socket_t* socket, int timeout)
MiniTLS 0:35aa5be3b78d 211 {
MiniTLS 0:35aa5be3b78d 212 DBG("Get new bytes");
MiniTLS 0:35aa5be3b78d 213 if( socket->read_buffer != NULL ) //No need to read more bytes
MiniTLS 0:35aa5be3b78d 214 {
MiniTLS 0:35aa5be3b78d 215 WARN("Buffer is already non-empty");
MiniTLS 0:35aa5be3b78d 216 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 217 }
MiniTLS 0:35aa5be3b78d 218
MiniTLS 0:35aa5be3b78d 219 tls_record_set_read_timeout(&socket->record, timeout);
MiniTLS 0:35aa5be3b78d 220
MiniTLS 0:35aa5be3b78d 221 int ret;
MiniTLS 0:35aa5be3b78d 222 do
MiniTLS 0:35aa5be3b78d 223 {
MiniTLS 0:35aa5be3b78d 224 DBG("Processing TLS packet");
MiniTLS 0:35aa5be3b78d 225 ret = tls_record_process(&socket->record);
MiniTLS 0:35aa5be3b78d 226 if(ret)
MiniTLS 0:35aa5be3b78d 227 {
MiniTLS 0:35aa5be3b78d 228 return ret;
MiniTLS 0:35aa5be3b78d 229 }
MiniTLS 0:35aa5be3b78d 230 } while( socket->read_buffer == NULL );
MiniTLS 0:35aa5be3b78d 231
MiniTLS 0:35aa5be3b78d 232 DBG("Buffer has been filled");
MiniTLS 0:35aa5be3b78d 233 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 234 }
MiniTLS 0:35aa5be3b78d 235
MiniTLS 0:35aa5be3b78d 236 mutls_err_t tls_socket_flush_write(tls_socket_t* socket, int timeout)
MiniTLS 0:35aa5be3b78d 237 {
MiniTLS 0:35aa5be3b78d 238 if(buffer_length(&socket->write_buffer) == 0)
MiniTLS 0:35aa5be3b78d 239 {
MiniTLS 0:35aa5be3b78d 240 return MUTLS_OK; //Useless to flush
MiniTLS 0:35aa5be3b78d 241 }
MiniTLS 0:35aa5be3b78d 242
MiniTLS 0:35aa5be3b78d 243 tls_record_set_write_timeout(&socket->record, timeout);
MiniTLS 0:35aa5be3b78d 244
MiniTLS 0:35aa5be3b78d 245 //Pass buffer to record layer
MiniTLS 0:35aa5be3b78d 246 mutls_err_t ret = tls_record_send(&socket->record, TLS_APPLICATION_DATA, &socket->write_buffer);
MiniTLS 0:35aa5be3b78d 247
MiniTLS 0:35aa5be3b78d 248 //TODO: Advertise writeable here
MiniTLS 0:35aa5be3b78d 249
MiniTLS 0:35aa5be3b78d 250 if(ret)
MiniTLS 0:35aa5be3b78d 251 {
MiniTLS 0:35aa5be3b78d 252 return ret;
MiniTLS 0:35aa5be3b78d 253 }
MiniTLS 0:35aa5be3b78d 254
MiniTLS 0:35aa5be3b78d 255 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 256 }
MiniTLS 0:35aa5be3b78d 257
MiniTLS 0:35aa5be3b78d 258 //Called from record layer
MiniTLS 0:35aa5be3b78d 259 mutls_err_t tls_socket_readable_callback(tls_socket_t* socket, buffer_t* buffer)
MiniTLS 0:35aa5be3b78d 260 {
MiniTLS 0:35aa5be3b78d 261 socket->read_buffer = buffer;
MiniTLS 0:35aa5be3b78d 262
MiniTLS 0:35aa5be3b78d 263 //Process events
MiniTLS 0:35aa5be3b78d 264
MiniTLS 0:35aa5be3b78d 265 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 266 }
MiniTLS 0:35aa5be3b78d 267
MiniTLS 0:35aa5be3b78d 268 mutls_err_t tls_socket_close(tls_socket_t* socket)
MiniTLS 0:35aa5be3b78d 269 {
MiniTLS 0:35aa5be3b78d 270 mutls_err_t ret = tls_record_close(&socket->record);
MiniTLS 0:35aa5be3b78d 271 if(ret)
MiniTLS 0:35aa5be3b78d 272 {
MiniTLS 0:35aa5be3b78d 273 return ret;
MiniTLS 0:35aa5be3b78d 274 }
MiniTLS 0:35aa5be3b78d 275 return MUTLS_OK;
MiniTLS 0:35aa5be3b78d 276 }