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:23:09 2014 +0000
Revision:
4:cbaf466d717d
Parent:
3:eb324ffffd2b
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_socket.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_socket.c"
MiniTLS 2:527a66d0a1a9 28 #endif
MiniTLS 2:527a66d0a1a9 29
MiniTLS 2:527a66d0a1a9 30
MiniTLS 2:527a66d0a1a9 31 #include "core/fwk.h"
MiniTLS 2:527a66d0a1a9 32 #include "inc/minitls_errors.h"
MiniTLS 2:527a66d0a1a9 33
MiniTLS 2:527a66d0a1a9 34 #include "tls_socket.h"
MiniTLS 2:527a66d0a1a9 35
MiniTLS 2:527a66d0a1a9 36 minitls_err_t tls_socket_init(tls_socket_t* socket, minitls_t* minitls,
MiniTLS 2:527a66d0a1a9 37 uint8_t* write_buffer, size_t write_buffer_size, uint8_t* read_buffer, size_t read_buffer_size)
MiniTLS 2:527a66d0a1a9 38 {
MiniTLS 2:527a66d0a1a9 39 socket->minitls = minitls;
MiniTLS 2:527a66d0a1a9 40
MiniTLS 2:527a66d0a1a9 41 socket->events = NULL;
MiniTLS 2:527a66d0a1a9 42
MiniTLS 2:527a66d0a1a9 43 socket->read_buffer = NULL;
MiniTLS 2:527a66d0a1a9 44 buffer_init(&socket->write_buffer, write_buffer, write_buffer_size);
MiniTLS 2:527a66d0a1a9 45
MiniTLS 2:527a66d0a1a9 46 socket->session.session_id_length = 0;
MiniTLS 2:527a66d0a1a9 47
MiniTLS 2:527a66d0a1a9 48 minitls_err_t ret = tls_record_init(&socket->record, socket, read_buffer, read_buffer_size);
MiniTLS 2:527a66d0a1a9 49 if(ret)
MiniTLS 2:527a66d0a1a9 50 {
MiniTLS 2:527a66d0a1a9 51 return ret;
MiniTLS 2:527a66d0a1a9 52 }
MiniTLS 2:527a66d0a1a9 53
MiniTLS 2:527a66d0a1a9 54 ret = tls_handshake_init(&socket->handshake, socket);
MiniTLS 2:527a66d0a1a9 55 if(ret)
MiniTLS 2:527a66d0a1a9 56 {
MiniTLS 2:527a66d0a1a9 57 return ret;
MiniTLS 2:527a66d0a1a9 58 }
MiniTLS 2:527a66d0a1a9 59
MiniTLS 2:527a66d0a1a9 60 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 61 }
MiniTLS 2:527a66d0a1a9 62
MiniTLS 2:527a66d0a1a9 63 minitls_err_t tls_socket_connect(tls_socket_t* socket, const char* hostname, uint16_t port, int timeout)
MiniTLS 2:527a66d0a1a9 64 {
MiniTLS 2:527a66d0a1a9 65 minitls_err_t ret = tls_record_connect(&socket->record, hostname, port);
MiniTLS 2:527a66d0a1a9 66 if(ret)
MiniTLS 2:527a66d0a1a9 67 {
MiniTLS 2:527a66d0a1a9 68 ERR("Could not connect");
MiniTLS 2:527a66d0a1a9 69 return ret;
MiniTLS 2:527a66d0a1a9 70 }
MiniTLS 2:527a66d0a1a9 71
MiniTLS 2:527a66d0a1a9 72 //TODO we could allocate the handshake structure here to save memory
MiniTLS 2:527a66d0a1a9 73
MiniTLS 2:527a66d0a1a9 74 ret = tls_handshake_start(&socket->handshake);
MiniTLS 2:527a66d0a1a9 75 if(ret)
MiniTLS 2:527a66d0a1a9 76 {
MiniTLS 2:527a66d0a1a9 77 ERR("Could not start handshake");
MiniTLS 2:527a66d0a1a9 78 return ret;
MiniTLS 2:527a66d0a1a9 79 }
MiniTLS 2:527a66d0a1a9 80
MiniTLS 2:527a66d0a1a9 81 //Now wait for handshake to finish processing (or fail)
MiniTLS 2:527a66d0a1a9 82 while(!tls_handshake_is_done(&socket->handshake))
MiniTLS 2:527a66d0a1a9 83 {
MiniTLS 2:527a66d0a1a9 84 DBG("Handshaking...");
MiniTLS 2:527a66d0a1a9 85 ret = tls_record_process(&socket->record);
MiniTLS 2:527a66d0a1a9 86 if(ret)
MiniTLS 2:527a66d0a1a9 87 {
MiniTLS 2:527a66d0a1a9 88 ERR("Processing error");
MiniTLS 2:527a66d0a1a9 89 return ret;
MiniTLS 2:527a66d0a1a9 90 }
MiniTLS 2:527a66d0a1a9 91 }
MiniTLS 2:527a66d0a1a9 92
MiniTLS 2:527a66d0a1a9 93 DBG("Connected");
MiniTLS 2:527a66d0a1a9 94
MiniTLS 2:527a66d0a1a9 95 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 96 }
MiniTLS 2:527a66d0a1a9 97
MiniTLS 2:527a66d0a1a9 98 void tls_socket_copy_session(tls_socket_t* to, tls_socket_t* from)
MiniTLS 2:527a66d0a1a9 99 {
MiniTLS 2:527a66d0a1a9 100 memcpy(&to->session, &from->session, sizeof(tls_session_t));
MiniTLS 2:527a66d0a1a9 101 }
MiniTLS 2:527a66d0a1a9 102
MiniTLS 2:527a66d0a1a9 103 //Events API -- select like
MiniTLS 2:527a66d0a1a9 104 minitls_err_t tls_socket_event_list_init(tls_socket_event_list_t* list)
MiniTLS 2:527a66d0a1a9 105 {
MiniTLS 2:527a66d0a1a9 106 list->head = NULL;
MiniTLS 2:527a66d0a1a9 107
MiniTLS 2:527a66d0a1a9 108 //Create semaphore
MiniTLS 2:527a66d0a1a9 109 /* list->sem = rtos_sem_create(1, 0);*/
MiniTLS 2:527a66d0a1a9 110 /*if(list->sem == NULL)
MiniTLS 2:527a66d0a1a9 111 {
MiniTLS 2:527a66d0a1a9 112 return TLS_ERR_MEMORY;
MiniTLS 2:527a66d0a1a9 113 }*/ //FIXME
MiniTLS 2:527a66d0a1a9 114
MiniTLS 2:527a66d0a1a9 115 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 116 }
MiniTLS 2:527a66d0a1a9 117
MiniTLS 2:527a66d0a1a9 118 minitls_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 2:527a66d0a1a9 119 {
MiniTLS 2:527a66d0a1a9 120 //Init event
MiniTLS 2:527a66d0a1a9 121 event->socket = socket;
MiniTLS 2:527a66d0a1a9 122 event->read = read;
MiniTLS 2:527a66d0a1a9 123 event->write = write;
MiniTLS 2:527a66d0a1a9 124 event->list = list;
MiniTLS 2:527a66d0a1a9 125 event->socket_list_next = NULL;
MiniTLS 2:527a66d0a1a9 126 event->event_list_next = NULL;
MiniTLS 2:527a66d0a1a9 127
MiniTLS 2:527a66d0a1a9 128 //Add to select list (tail)
MiniTLS 2:527a66d0a1a9 129 if(list->head != NULL)
MiniTLS 2:527a66d0a1a9 130 {
MiniTLS 2:527a66d0a1a9 131 tls_socket_event_t* previous_event = list->head;
MiniTLS 2:527a66d0a1a9 132 while( previous_event->event_list_next != NULL )
MiniTLS 2:527a66d0a1a9 133 {
MiniTLS 2:527a66d0a1a9 134 previous_event = previous_event->event_list_next;
MiniTLS 2:527a66d0a1a9 135 }
MiniTLS 2:527a66d0a1a9 136 previous_event->event_list_next = event;
MiniTLS 2:527a66d0a1a9 137 }
MiniTLS 2:527a66d0a1a9 138 else
MiniTLS 2:527a66d0a1a9 139 {
MiniTLS 2:527a66d0a1a9 140 list->head = event;
MiniTLS 2:527a66d0a1a9 141 }
MiniTLS 2:527a66d0a1a9 142
MiniTLS 2:527a66d0a1a9 143 //Add to socket's event list (tail)
MiniTLS 2:527a66d0a1a9 144 if(socket->events != NULL)
MiniTLS 2:527a66d0a1a9 145 {
MiniTLS 2:527a66d0a1a9 146 tls_socket_event_t* previous_event = socket->events;
MiniTLS 2:527a66d0a1a9 147 while( previous_event->socket_list_next != NULL )
MiniTLS 2:527a66d0a1a9 148 {
MiniTLS 2:527a66d0a1a9 149 previous_event = previous_event->socket_list_next;
MiniTLS 2:527a66d0a1a9 150 }
MiniTLS 2:527a66d0a1a9 151 previous_event->socket_list_next = event;
MiniTLS 2:527a66d0a1a9 152 }
MiniTLS 2:527a66d0a1a9 153 else
MiniTLS 2:527a66d0a1a9 154 {
MiniTLS 2:527a66d0a1a9 155 socket->events = event;
MiniTLS 2:527a66d0a1a9 156 }
MiniTLS 2:527a66d0a1a9 157
MiniTLS 2:527a66d0a1a9 158 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 159 }
MiniTLS 2:527a66d0a1a9 160
MiniTLS 2:527a66d0a1a9 161 minitls_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 2:527a66d0a1a9 162 {/*
MiniTLS 2:527a66d0a1a9 163 if( rtos_sem_get(list->sem, timeout) ) //FIXME
MiniTLS 2:527a66d0a1a9 164 {*/
MiniTLS 2:527a66d0a1a9 165 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 166 /*}
MiniTLS 2:527a66d0a1a9 167 else
MiniTLS 2:527a66d0a1a9 168 {
MiniTLS 2:527a66d0a1a9 169 return TLS_ERR_TIMEOUT;
MiniTLS 2:527a66d0a1a9 170 }*/
MiniTLS 2:527a66d0a1a9 171 }
MiniTLS 2:527a66d0a1a9 172
MiniTLS 2:527a66d0a1a9 173 //These calls are non-blocking
MiniTLS 2:527a66d0a1a9 174 minitls_err_t tls_socket_read(tls_socket_t* socket, uint8_t* bytes, size_t max_size, size_t* read_size)
MiniTLS 2:527a66d0a1a9 175 {
MiniTLS 2:527a66d0a1a9 176 DBG("Reading at most %d bytes", max_size);
MiniTLS 2:527a66d0a1a9 177 if(socket->read_buffer == NULL) //Socket is not ready
MiniTLS 2:527a66d0a1a9 178 {
MiniTLS 2:527a66d0a1a9 179 WARN("Socket is not ready or has been closed");
MiniTLS 2:527a66d0a1a9 180 *read_size = 0;
MiniTLS 2:527a66d0a1a9 181 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 182 }
MiniTLS 2:527a66d0a1a9 183
MiniTLS 2:527a66d0a1a9 184 size_t length = buffer_length(socket->read_buffer);
MiniTLS 2:527a66d0a1a9 185 *read_size = MIN(max_size, length);
MiniTLS 2:527a66d0a1a9 186
MiniTLS 2:527a66d0a1a9 187 buffer_nbytes_read(socket->read_buffer, bytes, *read_size);
MiniTLS 2:527a66d0a1a9 188
MiniTLS 2:527a66d0a1a9 189 DBG("%d bytes read", *read_size);
MiniTLS 2:527a66d0a1a9 190
MiniTLS 2:527a66d0a1a9 191 //If buffer has been fully read, invalidate read_buffer
MiniTLS 2:527a66d0a1a9 192 if( buffer_length(socket->read_buffer) == 0 )
MiniTLS 2:527a66d0a1a9 193 {
MiniTLS 2:527a66d0a1a9 194 socket->read_buffer = NULL;
MiniTLS 2:527a66d0a1a9 195 }
MiniTLS 2:527a66d0a1a9 196
MiniTLS 2:527a66d0a1a9 197 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 198 }
MiniTLS 2:527a66d0a1a9 199
MiniTLS 2:527a66d0a1a9 200 minitls_err_t tls_socket_write(tls_socket_t* socket, uint8_t* bytes, size_t size, size_t* written_size)
MiniTLS 2:527a66d0a1a9 201 {
MiniTLS 2:527a66d0a1a9 202 size_t length = buffer_space(&socket->write_buffer);
MiniTLS 2:527a66d0a1a9 203 *written_size = MIN(size, length);
MiniTLS 2:527a66d0a1a9 204
MiniTLS 2:527a66d0a1a9 205 buffer_nbytes_write(&socket->write_buffer, bytes, *written_size);
MiniTLS 2:527a66d0a1a9 206
MiniTLS 2:527a66d0a1a9 207 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 208 }
MiniTLS 2:527a66d0a1a9 209
MiniTLS 2:527a66d0a1a9 210 minitls_err_t tls_socket_flush_read(tls_socket_t* socket, int timeout)
MiniTLS 2:527a66d0a1a9 211 {
MiniTLS 2:527a66d0a1a9 212 DBG("Get new bytes");
MiniTLS 2:527a66d0a1a9 213 if( socket->read_buffer != NULL ) //No need to read more bytes
MiniTLS 2:527a66d0a1a9 214 {
MiniTLS 2:527a66d0a1a9 215 WARN("Buffer is already non-empty");
MiniTLS 2:527a66d0a1a9 216 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 217 }
MiniTLS 2:527a66d0a1a9 218
MiniTLS 2:527a66d0a1a9 219 tls_record_set_read_timeout(&socket->record, timeout);
MiniTLS 2:527a66d0a1a9 220
MiniTLS 2:527a66d0a1a9 221 int ret;
MiniTLS 2:527a66d0a1a9 222 do
MiniTLS 2:527a66d0a1a9 223 {
MiniTLS 2:527a66d0a1a9 224 DBG("Processing TLS packet");
MiniTLS 2:527a66d0a1a9 225 ret = tls_record_process(&socket->record);
MiniTLS 2:527a66d0a1a9 226 if(ret)
MiniTLS 2:527a66d0a1a9 227 {
MiniTLS 2:527a66d0a1a9 228 return ret;
MiniTLS 2:527a66d0a1a9 229 }
MiniTLS 2:527a66d0a1a9 230 } while( socket->read_buffer == NULL );
MiniTLS 2:527a66d0a1a9 231
MiniTLS 2:527a66d0a1a9 232 DBG("Buffer has been filled");
MiniTLS 2:527a66d0a1a9 233 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 234 }
MiniTLS 2:527a66d0a1a9 235
MiniTLS 2:527a66d0a1a9 236 minitls_err_t tls_socket_flush_write(tls_socket_t* socket, int timeout)
MiniTLS 2:527a66d0a1a9 237 {
MiniTLS 2:527a66d0a1a9 238 if(buffer_length(&socket->write_buffer) == 0)
MiniTLS 2:527a66d0a1a9 239 {
MiniTLS 2:527a66d0a1a9 240 return MINITLS_OK; //Useless to flush
MiniTLS 2:527a66d0a1a9 241 }
MiniTLS 2:527a66d0a1a9 242
MiniTLS 2:527a66d0a1a9 243 tls_record_set_write_timeout(&socket->record, timeout);
MiniTLS 2:527a66d0a1a9 244
MiniTLS 2:527a66d0a1a9 245 //Pass buffer to record layer
MiniTLS 2:527a66d0a1a9 246 minitls_err_t ret = tls_record_send(&socket->record, TLS_APPLICATION_DATA, &socket->write_buffer);
MiniTLS 2:527a66d0a1a9 247
MiniTLS 2:527a66d0a1a9 248 //TODO: Advertise writeable here
MiniTLS 2:527a66d0a1a9 249
MiniTLS 2:527a66d0a1a9 250 if(ret)
MiniTLS 2:527a66d0a1a9 251 {
MiniTLS 2:527a66d0a1a9 252 return ret;
MiniTLS 2:527a66d0a1a9 253 }
MiniTLS 2:527a66d0a1a9 254
MiniTLS 2:527a66d0a1a9 255 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 256 }
MiniTLS 2:527a66d0a1a9 257
MiniTLS 2:527a66d0a1a9 258 //Called from record layer
MiniTLS 2:527a66d0a1a9 259 minitls_err_t tls_socket_readable_callback(tls_socket_t* socket, buffer_t* buffer)
MiniTLS 2:527a66d0a1a9 260 {
MiniTLS 2:527a66d0a1a9 261 socket->read_buffer = buffer;
MiniTLS 2:527a66d0a1a9 262
MiniTLS 2:527a66d0a1a9 263 //Process events
MiniTLS 2:527a66d0a1a9 264
MiniTLS 2:527a66d0a1a9 265 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 266 }
MiniTLS 2:527a66d0a1a9 267
MiniTLS 2:527a66d0a1a9 268 minitls_err_t tls_socket_close(tls_socket_t* socket)
MiniTLS 2:527a66d0a1a9 269 {
MiniTLS 2:527a66d0a1a9 270 minitls_err_t ret = tls_record_close(&socket->record);
MiniTLS 2:527a66d0a1a9 271 if(ret)
MiniTLS 2:527a66d0a1a9 272 {
MiniTLS 2:527a66d0a1a9 273 return ret;
MiniTLS 2:527a66d0a1a9 274 }
MiniTLS 2:527a66d0a1a9 275 return MINITLS_OK;
MiniTLS 2:527a66d0a1a9 276 }