Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file tls_record.c
Sergunb 0:8918a71cdbe9 3 * @brief TLS record protocol
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneSSL Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 26 * @version 1.7.6
Sergunb 0:8918a71cdbe9 27 **/
Sergunb 0:8918a71cdbe9 28
Sergunb 0:8918a71cdbe9 29 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 30 #define TRACE_LEVEL TLS_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 31
Sergunb 0:8918a71cdbe9 32 //Dependencies
Sergunb 0:8918a71cdbe9 33 #include <string.h>
Sergunb 0:8918a71cdbe9 34 #include "tls.h"
Sergunb 0:8918a71cdbe9 35 #include "tls_common.h"
Sergunb 0:8918a71cdbe9 36 #include "tls_record.h"
Sergunb 0:8918a71cdbe9 37 #include "tls_misc.h"
Sergunb 0:8918a71cdbe9 38 #include "ssl_common.h"
Sergunb 0:8918a71cdbe9 39 #include "cipher_mode_cbc.h"
Sergunb 0:8918a71cdbe9 40 #include "cipher_mode_ccm.h"
Sergunb 0:8918a71cdbe9 41 #include "cipher_mode_gcm.h"
Sergunb 0:8918a71cdbe9 42 #include "chacha20_poly1305.h"
Sergunb 0:8918a71cdbe9 43 #include "debug.h"
Sergunb 0:8918a71cdbe9 44
Sergunb 0:8918a71cdbe9 45 //Check SSL library configuration
Sergunb 0:8918a71cdbe9 46 #if (TLS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 47
Sergunb 0:8918a71cdbe9 48
Sergunb 0:8918a71cdbe9 49 /**
Sergunb 0:8918a71cdbe9 50 * @brief Write protocol data
Sergunb 0:8918a71cdbe9 51 * @param[in] context Pointer to the TLS context
Sergunb 0:8918a71cdbe9 52 * @param[in] data Pointer to the data buffer
Sergunb 0:8918a71cdbe9 53 * @param[in] length Number of data bytes to be written
Sergunb 0:8918a71cdbe9 54 * @param[in] contentType Higher level protocol
Sergunb 0:8918a71cdbe9 55 * @return Error code
Sergunb 0:8918a71cdbe9 56 **/
Sergunb 0:8918a71cdbe9 57
Sergunb 0:8918a71cdbe9 58 error_t tlsWriteProtocolData(TlsContext *context,
Sergunb 0:8918a71cdbe9 59 const void *data, size_t length, TlsContentType contentType)
Sergunb 0:8918a71cdbe9 60 {
Sergunb 0:8918a71cdbe9 61 error_t error;
Sergunb 0:8918a71cdbe9 62 size_t n;
Sergunb 0:8918a71cdbe9 63 uint8_t *p;
Sergunb 0:8918a71cdbe9 64
Sergunb 0:8918a71cdbe9 65 //Initialize status code
Sergunb 0:8918a71cdbe9 66 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 67
Sergunb 0:8918a71cdbe9 68 //Fragmentation process
Sergunb 0:8918a71cdbe9 69 while(!error)
Sergunb 0:8918a71cdbe9 70 {
Sergunb 0:8918a71cdbe9 71 if(context->txBufferLen == 0)
Sergunb 0:8918a71cdbe9 72 {
Sergunb 0:8918a71cdbe9 73 //Check the length of the data
Sergunb 0:8918a71cdbe9 74 if(length > context->txRecordMaxLen)
Sergunb 0:8918a71cdbe9 75 {
Sergunb 0:8918a71cdbe9 76 //Report an error
Sergunb 0:8918a71cdbe9 77 error = ERROR_MESSAGE_TOO_LONG;
Sergunb 0:8918a71cdbe9 78 }
Sergunb 0:8918a71cdbe9 79 else if(length > 0)
Sergunb 0:8918a71cdbe9 80 {
Sergunb 0:8918a71cdbe9 81 //The hash value is updated for each handshake message,
Sergunb 0:8918a71cdbe9 82 //except for HelloRequest messages
Sergunb 0:8918a71cdbe9 83 if(contentType == TLS_TYPE_HANDSHAKE)
Sergunb 0:8918a71cdbe9 84 tlsUpdateHandshakeHash(context, data, length);
Sergunb 0:8918a71cdbe9 85
Sergunb 0:8918a71cdbe9 86 //Make room for the encryption overhead
Sergunb 0:8918a71cdbe9 87 memmove(context->txBuffer + context->txBufferSize - length, data, length);
Sergunb 0:8918a71cdbe9 88
Sergunb 0:8918a71cdbe9 89 //Save record type
Sergunb 0:8918a71cdbe9 90 context->txBufferType = contentType;
Sergunb 0:8918a71cdbe9 91 //Set the length of the buffer
Sergunb 0:8918a71cdbe9 92 context->txBufferLen = length;
Sergunb 0:8918a71cdbe9 93 //Point to the beginning of the buffer
Sergunb 0:8918a71cdbe9 94 context->txBufferPos = 0;
Sergunb 0:8918a71cdbe9 95 }
Sergunb 0:8918a71cdbe9 96 else
Sergunb 0:8918a71cdbe9 97 {
Sergunb 0:8918a71cdbe9 98 //We are done
Sergunb 0:8918a71cdbe9 99 break;
Sergunb 0:8918a71cdbe9 100 }
Sergunb 0:8918a71cdbe9 101 }
Sergunb 0:8918a71cdbe9 102 else if(context->txBufferPos < context->txBufferLen)
Sergunb 0:8918a71cdbe9 103 {
Sergunb 0:8918a71cdbe9 104 //Number of bytes left to send
Sergunb 0:8918a71cdbe9 105 n = context->txBufferLen - context->txBufferPos;
Sergunb 0:8918a71cdbe9 106 //Point to the current fragment
Sergunb 0:8918a71cdbe9 107 p = context->txBuffer + context->txBufferSize - n;
Sergunb 0:8918a71cdbe9 108 //The record length must not exceed 16384 bytes
Sergunb 0:8918a71cdbe9 109 n = MIN(n, TLS_MAX_RECORD_LENGTH);
Sergunb 0:8918a71cdbe9 110
Sergunb 0:8918a71cdbe9 111 //Send TLS record
Sergunb 0:8918a71cdbe9 112 error = tlsWriteRecord(context, p, n, context->txBufferType);
Sergunb 0:8918a71cdbe9 113
Sergunb 0:8918a71cdbe9 114 //Check status code
Sergunb 0:8918a71cdbe9 115 if(!error)
Sergunb 0:8918a71cdbe9 116 {
Sergunb 0:8918a71cdbe9 117 //Advance data pointer
Sergunb 0:8918a71cdbe9 118 context->txBufferPos += n;
Sergunb 0:8918a71cdbe9 119 }
Sergunb 0:8918a71cdbe9 120 }
Sergunb 0:8918a71cdbe9 121 else
Sergunb 0:8918a71cdbe9 122 {
Sergunb 0:8918a71cdbe9 123 //Prepare to send new protocol data
Sergunb 0:8918a71cdbe9 124 context->txBufferLen = 0;
Sergunb 0:8918a71cdbe9 125 context->txBufferPos = 0;
Sergunb 0:8918a71cdbe9 126
Sergunb 0:8918a71cdbe9 127 //We are done
Sergunb 0:8918a71cdbe9 128 break;
Sergunb 0:8918a71cdbe9 129 }
Sergunb 0:8918a71cdbe9 130 }
Sergunb 0:8918a71cdbe9 131
Sergunb 0:8918a71cdbe9 132 //Return status code
Sergunb 0:8918a71cdbe9 133 return error;
Sergunb 0:8918a71cdbe9 134 }
Sergunb 0:8918a71cdbe9 135
Sergunb 0:8918a71cdbe9 136
Sergunb 0:8918a71cdbe9 137 /**
Sergunb 0:8918a71cdbe9 138 * @brief Read protocol data
Sergunb 0:8918a71cdbe9 139 * @param[in] context Pointer to the TLS context
Sergunb 0:8918a71cdbe9 140 * @param[out] data Pointer to the received data
Sergunb 0:8918a71cdbe9 141 * @param[out] length Number of data bytes that were received
Sergunb 0:8918a71cdbe9 142 * @param[out] contentType Higher level protocol
Sergunb 0:8918a71cdbe9 143 * @return Error code
Sergunb 0:8918a71cdbe9 144 **/
Sergunb 0:8918a71cdbe9 145
Sergunb 0:8918a71cdbe9 146 error_t tlsReadProtocolData(TlsContext *context,
Sergunb 0:8918a71cdbe9 147 void **data, size_t *length, TlsContentType *contentType)
Sergunb 0:8918a71cdbe9 148 {
Sergunb 0:8918a71cdbe9 149 error_t error;
Sergunb 0:8918a71cdbe9 150 size_t n;
Sergunb 0:8918a71cdbe9 151 TlsContentType type;
Sergunb 0:8918a71cdbe9 152 TlsHandshake *message;
Sergunb 0:8918a71cdbe9 153
Sergunb 0:8918a71cdbe9 154 //Initialize status code
Sergunb 0:8918a71cdbe9 155 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 156
Sergunb 0:8918a71cdbe9 157 //Fragment reassembly process
Sergunb 0:8918a71cdbe9 158 do
Sergunb 0:8918a71cdbe9 159 {
Sergunb 0:8918a71cdbe9 160 //Empty receive buffer?
Sergunb 0:8918a71cdbe9 161 if(context->rxBufferLen == 0)
Sergunb 0:8918a71cdbe9 162 {
Sergunb 0:8918a71cdbe9 163 //Read a TLS record
Sergunb 0:8918a71cdbe9 164 error = tlsReadRecord(context, context->rxBuffer,
Sergunb 0:8918a71cdbe9 165 context->rxBufferSize, &n, &type);
Sergunb 0:8918a71cdbe9 166
Sergunb 0:8918a71cdbe9 167 //Check status code
Sergunb 0:8918a71cdbe9 168 if(!error)
Sergunb 0:8918a71cdbe9 169 {
Sergunb 0:8918a71cdbe9 170 //Save record type
Sergunb 0:8918a71cdbe9 171 context->rxBufferType = type;
Sergunb 0:8918a71cdbe9 172 //Number of bytes available for reading
Sergunb 0:8918a71cdbe9 173 context->rxBufferLen = n;
Sergunb 0:8918a71cdbe9 174 //Rewind to the beginning of the buffer
Sergunb 0:8918a71cdbe9 175 context->rxBufferPos = 0;
Sergunb 0:8918a71cdbe9 176 }
Sergunb 0:8918a71cdbe9 177 }
Sergunb 0:8918a71cdbe9 178 //Imcomplete message received?
Sergunb 0:8918a71cdbe9 179 else if(error == ERROR_MORE_DATA_REQUIRED)
Sergunb 0:8918a71cdbe9 180 {
Sergunb 0:8918a71cdbe9 181 //Make room at the end of the buffer
Sergunb 0:8918a71cdbe9 182 if(context->rxBufferPos > 0)
Sergunb 0:8918a71cdbe9 183 {
Sergunb 0:8918a71cdbe9 184 //Move unread data to the beginning of the buffer
Sergunb 0:8918a71cdbe9 185 memmove(context->rxBuffer, context->rxBuffer +
Sergunb 0:8918a71cdbe9 186 context->rxBufferPos, context->rxBufferLen);
Sergunb 0:8918a71cdbe9 187
Sergunb 0:8918a71cdbe9 188 //Rewind to the beginning of the buffer
Sergunb 0:8918a71cdbe9 189 context->rxBufferPos = 0;
Sergunb 0:8918a71cdbe9 190 }
Sergunb 0:8918a71cdbe9 191
Sergunb 0:8918a71cdbe9 192 //Read a TLS record
Sergunb 0:8918a71cdbe9 193 error = tlsReadRecord(context, context->rxBuffer + context->rxBufferLen,
Sergunb 0:8918a71cdbe9 194 context->rxBufferSize - context->rxBufferLen, &n, &type);
Sergunb 0:8918a71cdbe9 195
Sergunb 0:8918a71cdbe9 196 //Check status code
Sergunb 0:8918a71cdbe9 197 if(!error)
Sergunb 0:8918a71cdbe9 198 {
Sergunb 0:8918a71cdbe9 199 //Fragmented records with mixed types cannot be interleaved
Sergunb 0:8918a71cdbe9 200 if(type != context->rxBufferType)
Sergunb 0:8918a71cdbe9 201 error = ERROR_UNEXPECTED_MESSAGE;
Sergunb 0:8918a71cdbe9 202 }
Sergunb 0:8918a71cdbe9 203
Sergunb 0:8918a71cdbe9 204 //Check status code
Sergunb 0:8918a71cdbe9 205 if(!error)
Sergunb 0:8918a71cdbe9 206 {
Sergunb 0:8918a71cdbe9 207 //Number of bytes available for reading
Sergunb 0:8918a71cdbe9 208 context->rxBufferLen += n;
Sergunb 0:8918a71cdbe9 209 }
Sergunb 0:8918a71cdbe9 210 }
Sergunb 0:8918a71cdbe9 211
Sergunb 0:8918a71cdbe9 212 //Check status code
Sergunb 0:8918a71cdbe9 213 if(!error)
Sergunb 0:8918a71cdbe9 214 {
Sergunb 0:8918a71cdbe9 215 //Handshake message received?
Sergunb 0:8918a71cdbe9 216 if(context->rxBufferType == TLS_TYPE_HANDSHAKE)
Sergunb 0:8918a71cdbe9 217 {
Sergunb 0:8918a71cdbe9 218 //A message may be fragmented across several records
Sergunb 0:8918a71cdbe9 219 if(context->rxBufferLen < sizeof(TlsHandshake))
Sergunb 0:8918a71cdbe9 220 {
Sergunb 0:8918a71cdbe9 221 //Read an additional record
Sergunb 0:8918a71cdbe9 222 error = ERROR_MORE_DATA_REQUIRED;
Sergunb 0:8918a71cdbe9 223 }
Sergunb 0:8918a71cdbe9 224 else
Sergunb 0:8918a71cdbe9 225 {
Sergunb 0:8918a71cdbe9 226 //Point to the handshake message
Sergunb 0:8918a71cdbe9 227 message = (TlsHandshake *) (context->rxBuffer + context->rxBufferPos);
Sergunb 0:8918a71cdbe9 228 //Retrieve the length of the handshake message
Sergunb 0:8918a71cdbe9 229 n = sizeof(TlsHandshake) + LOAD24BE(message->length);
Sergunb 0:8918a71cdbe9 230
Sergunb 0:8918a71cdbe9 231 //A message may be fragmented across several records
Sergunb 0:8918a71cdbe9 232 if(context->rxBufferLen < n)
Sergunb 0:8918a71cdbe9 233 {
Sergunb 0:8918a71cdbe9 234 //Read an additional record
Sergunb 0:8918a71cdbe9 235 error = ERROR_MORE_DATA_REQUIRED;
Sergunb 0:8918a71cdbe9 236 }
Sergunb 0:8918a71cdbe9 237 else
Sergunb 0:8918a71cdbe9 238 {
Sergunb 0:8918a71cdbe9 239 //Pass the handshake message to the higher layer
Sergunb 0:8918a71cdbe9 240 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 241 }
Sergunb 0:8918a71cdbe9 242 }
Sergunb 0:8918a71cdbe9 243 }
Sergunb 0:8918a71cdbe9 244 //ChangeCipherSpec message received?
Sergunb 0:8918a71cdbe9 245 else if(context->rxBufferType == TLS_TYPE_CHANGE_CIPHER_SPEC)
Sergunb 0:8918a71cdbe9 246 {
Sergunb 0:8918a71cdbe9 247 //A message may be fragmented across several records
Sergunb 0:8918a71cdbe9 248 if(context->rxBufferLen < sizeof(TlsChangeCipherSpec))
Sergunb 0:8918a71cdbe9 249 {
Sergunb 0:8918a71cdbe9 250 //Read an additional record
Sergunb 0:8918a71cdbe9 251 error = ERROR_MORE_DATA_REQUIRED;
Sergunb 0:8918a71cdbe9 252 }
Sergunb 0:8918a71cdbe9 253 else
Sergunb 0:8918a71cdbe9 254 {
Sergunb 0:8918a71cdbe9 255 //Length of the ChangeCipherSpec message
Sergunb 0:8918a71cdbe9 256 n = sizeof(TlsChangeCipherSpec);
Sergunb 0:8918a71cdbe9 257 //Pass the ChangeCipherSpec message to the higher layer
Sergunb 0:8918a71cdbe9 258 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 259 }
Sergunb 0:8918a71cdbe9 260 }
Sergunb 0:8918a71cdbe9 261 //Alert message received?
Sergunb 0:8918a71cdbe9 262 else if(context->rxBufferType == TLS_TYPE_ALERT)
Sergunb 0:8918a71cdbe9 263 {
Sergunb 0:8918a71cdbe9 264 //A message may be fragmented across several records
Sergunb 0:8918a71cdbe9 265 if(context->rxBufferLen < sizeof(TlsAlert))
Sergunb 0:8918a71cdbe9 266 {
Sergunb 0:8918a71cdbe9 267 //Read an additional record
Sergunb 0:8918a71cdbe9 268 error = ERROR_MORE_DATA_REQUIRED;
Sergunb 0:8918a71cdbe9 269 }
Sergunb 0:8918a71cdbe9 270 else
Sergunb 0:8918a71cdbe9 271 {
Sergunb 0:8918a71cdbe9 272 //Length of the Alert message
Sergunb 0:8918a71cdbe9 273 n = sizeof(TlsAlert);
Sergunb 0:8918a71cdbe9 274 //Pass the Alert message to the higher layer
Sergunb 0:8918a71cdbe9 275 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 276 }
Sergunb 0:8918a71cdbe9 277 }
Sergunb 0:8918a71cdbe9 278 //Application data received?
Sergunb 0:8918a71cdbe9 279 else if(context->rxBufferType == TLS_TYPE_APPLICATION_DATA)
Sergunb 0:8918a71cdbe9 280 {
Sergunb 0:8918a71cdbe9 281 //Length of the application data
Sergunb 0:8918a71cdbe9 282 n = context->rxBufferLen;
Sergunb 0:8918a71cdbe9 283 //Pass the application data to the higher layer
Sergunb 0:8918a71cdbe9 284 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 285 }
Sergunb 0:8918a71cdbe9 286 //Unknown content type?
Sergunb 0:8918a71cdbe9 287 else
Sergunb 0:8918a71cdbe9 288 {
Sergunb 0:8918a71cdbe9 289 //Report an error
Sergunb 0:8918a71cdbe9 290 error = ERROR_UNEXPECTED_MESSAGE;
Sergunb 0:8918a71cdbe9 291 }
Sergunb 0:8918a71cdbe9 292 }
Sergunb 0:8918a71cdbe9 293
Sergunb 0:8918a71cdbe9 294 //Read as many records as necessary to reassemble the data
Sergunb 0:8918a71cdbe9 295 } while(error == ERROR_MORE_DATA_REQUIRED);
Sergunb 0:8918a71cdbe9 296
Sergunb 0:8918a71cdbe9 297 //Successful processing?
Sergunb 0:8918a71cdbe9 298 if(!error)
Sergunb 0:8918a71cdbe9 299 {
Sergunb 0:8918a71cdbe9 300 //Pointer to the received data
Sergunb 0:8918a71cdbe9 301 *data = context->rxBuffer + context->rxBufferPos;
Sergunb 0:8918a71cdbe9 302 //Length, in byte, of the data
Sergunb 0:8918a71cdbe9 303 *length = n;
Sergunb 0:8918a71cdbe9 304 //Protocol type
Sergunb 0:8918a71cdbe9 305 *contentType = context->rxBufferType;
Sergunb 0:8918a71cdbe9 306 }
Sergunb 0:8918a71cdbe9 307
Sergunb 0:8918a71cdbe9 308 //Return status code
Sergunb 0:8918a71cdbe9 309 return error;
Sergunb 0:8918a71cdbe9 310 }
Sergunb 0:8918a71cdbe9 311
Sergunb 0:8918a71cdbe9 312
Sergunb 0:8918a71cdbe9 313 /**
Sergunb 0:8918a71cdbe9 314 * @brief Send a TLS record
Sergunb 0:8918a71cdbe9 315 * @param[in] context Pointer to the TLS context
Sergunb 0:8918a71cdbe9 316 * @param[in] data Pointer to the record data
Sergunb 0:8918a71cdbe9 317 * @param[in] length Length of the record data
Sergunb 0:8918a71cdbe9 318 * @param[in] contentType Record type
Sergunb 0:8918a71cdbe9 319 * @return Error code
Sergunb 0:8918a71cdbe9 320 **/
Sergunb 0:8918a71cdbe9 321
Sergunb 0:8918a71cdbe9 322 error_t tlsWriteRecord(TlsContext *context, const uint8_t *data,
Sergunb 0:8918a71cdbe9 323 size_t length, TlsContentType contentType)
Sergunb 0:8918a71cdbe9 324 {
Sergunb 0:8918a71cdbe9 325 error_t error;
Sergunb 0:8918a71cdbe9 326 size_t n;
Sergunb 0:8918a71cdbe9 327 TlsRecord *record;
Sergunb 0:8918a71cdbe9 328
Sergunb 0:8918a71cdbe9 329 //Point to the TLS record
Sergunb 0:8918a71cdbe9 330 record = (TlsRecord *) context->txBuffer;
Sergunb 0:8918a71cdbe9 331
Sergunb 0:8918a71cdbe9 332 //Initialize status code
Sergunb 0:8918a71cdbe9 333 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 334
Sergunb 0:8918a71cdbe9 335 //Send process
Sergunb 0:8918a71cdbe9 336 while(!error)
Sergunb 0:8918a71cdbe9 337 {
Sergunb 0:8918a71cdbe9 338 //Send as much data as possible
Sergunb 0:8918a71cdbe9 339 if(context->txRecordLen == 0)
Sergunb 0:8918a71cdbe9 340 {
Sergunb 0:8918a71cdbe9 341 //Format TLS record
Sergunb 0:8918a71cdbe9 342 record->type = contentType;
Sergunb 0:8918a71cdbe9 343 record->version = htons(context->version);
Sergunb 0:8918a71cdbe9 344 record->length = htons(length);
Sergunb 0:8918a71cdbe9 345
Sergunb 0:8918a71cdbe9 346 //Copy record data
Sergunb 0:8918a71cdbe9 347 memmove(record->data, data, length);
Sergunb 0:8918a71cdbe9 348
Sergunb 0:8918a71cdbe9 349 //Debug message
Sergunb 0:8918a71cdbe9 350 TRACE_DEBUG("Sending TLS record (%" PRIuSIZE " bytes)...\r\n", length);
Sergunb 0:8918a71cdbe9 351 TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 352
Sergunb 0:8918a71cdbe9 353 //Protect record payload?
Sergunb 0:8918a71cdbe9 354 if(context->changeCipherSpecSent)
Sergunb 0:8918a71cdbe9 355 {
Sergunb 0:8918a71cdbe9 356 //Encrypt TLS record
Sergunb 0:8918a71cdbe9 357 error = tlsEncryptRecord(context, record);
Sergunb 0:8918a71cdbe9 358 }
Sergunb 0:8918a71cdbe9 359
Sergunb 0:8918a71cdbe9 360 //Check status code
Sergunb 0:8918a71cdbe9 361 if(!error)
Sergunb 0:8918a71cdbe9 362 {
Sergunb 0:8918a71cdbe9 363 //Actual length of the record data
Sergunb 0:8918a71cdbe9 364 context->txRecordLen = sizeof(TlsRecord) + ntohs(record->length);
Sergunb 0:8918a71cdbe9 365 //Point to the beginning of the record
Sergunb 0:8918a71cdbe9 366 context->txRecordPos = 0;
Sergunb 0:8918a71cdbe9 367 }
Sergunb 0:8918a71cdbe9 368 }
Sergunb 0:8918a71cdbe9 369 else if(context->txRecordPos < context->txRecordLen)
Sergunb 0:8918a71cdbe9 370 {
Sergunb 0:8918a71cdbe9 371 //Total number of bytes that have been written
Sergunb 0:8918a71cdbe9 372 n = 0;
Sergunb 0:8918a71cdbe9 373
Sergunb 0:8918a71cdbe9 374 //Send more data
Sergunb 0:8918a71cdbe9 375 error = context->sendCallback(context->handle,
Sergunb 0:8918a71cdbe9 376 context->txBuffer + context->txRecordPos,
Sergunb 0:8918a71cdbe9 377 context->txRecordLen - context->txRecordPos, &n, 0);
Sergunb 0:8918a71cdbe9 378
Sergunb 0:8918a71cdbe9 379 //Check status code
Sergunb 0:8918a71cdbe9 380 if(error == NO_ERROR || error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
Sergunb 0:8918a71cdbe9 381 {
Sergunb 0:8918a71cdbe9 382 //Advance data pointer
Sergunb 0:8918a71cdbe9 383 context->txRecordPos += n;
Sergunb 0:8918a71cdbe9 384 }
Sergunb 0:8918a71cdbe9 385 else
Sergunb 0:8918a71cdbe9 386 {
Sergunb 0:8918a71cdbe9 387 //The write operation has failed
Sergunb 0:8918a71cdbe9 388 error = ERROR_WRITE_FAILED;
Sergunb 0:8918a71cdbe9 389 }
Sergunb 0:8918a71cdbe9 390 }
Sergunb 0:8918a71cdbe9 391 else
Sergunb 0:8918a71cdbe9 392 {
Sergunb 0:8918a71cdbe9 393 //Prepare to send the next TLS record
Sergunb 0:8918a71cdbe9 394 context->txRecordLen = 0;
Sergunb 0:8918a71cdbe9 395 context->txRecordPos = 0;
Sergunb 0:8918a71cdbe9 396
Sergunb 0:8918a71cdbe9 397 //We are done
Sergunb 0:8918a71cdbe9 398 break;
Sergunb 0:8918a71cdbe9 399 }
Sergunb 0:8918a71cdbe9 400 }
Sergunb 0:8918a71cdbe9 401
Sergunb 0:8918a71cdbe9 402 //Return status code
Sergunb 0:8918a71cdbe9 403 return error;
Sergunb 0:8918a71cdbe9 404 }
Sergunb 0:8918a71cdbe9 405
Sergunb 0:8918a71cdbe9 406
Sergunb 0:8918a71cdbe9 407 /**
Sergunb 0:8918a71cdbe9 408 * @brief Receive a TLS record
Sergunb 0:8918a71cdbe9 409 * @param[in] context Pointer to the TLS context
Sergunb 0:8918a71cdbe9 410 * @param[out] data Buffer where to store the record data
Sergunb 0:8918a71cdbe9 411 * @param[in] size Maximum acceptable size for the incoming record
Sergunb 0:8918a71cdbe9 412 * @param[out] length Length of the record data
Sergunb 0:8918a71cdbe9 413 * @param[out] contentType Record type
Sergunb 0:8918a71cdbe9 414 * @return Error code
Sergunb 0:8918a71cdbe9 415 **/
Sergunb 0:8918a71cdbe9 416
Sergunb 0:8918a71cdbe9 417 error_t tlsReadRecord(TlsContext *context, uint8_t *data,
Sergunb 0:8918a71cdbe9 418 size_t size, size_t *length, TlsContentType *contentType)
Sergunb 0:8918a71cdbe9 419 {
Sergunb 0:8918a71cdbe9 420 error_t error;
Sergunb 0:8918a71cdbe9 421 size_t n;
Sergunb 0:8918a71cdbe9 422 TlsRecord *record;
Sergunb 0:8918a71cdbe9 423
Sergunb 0:8918a71cdbe9 424 //Point to the buffer where to store the incoming TLS record
Sergunb 0:8918a71cdbe9 425 record = (TlsRecord *) data;
Sergunb 0:8918a71cdbe9 426
Sergunb 0:8918a71cdbe9 427 //Initialize status code
Sergunb 0:8918a71cdbe9 428 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 429
Sergunb 0:8918a71cdbe9 430 //Receive process
Sergunb 0:8918a71cdbe9 431 while(!error)
Sergunb 0:8918a71cdbe9 432 {
Sergunb 0:8918a71cdbe9 433 //Read as much data as possible
Sergunb 0:8918a71cdbe9 434 if(context->rxRecordPos < sizeof(TlsRecord))
Sergunb 0:8918a71cdbe9 435 {
Sergunb 0:8918a71cdbe9 436 //Make sure that the buffer is large enough to hold the record header
Sergunb 0:8918a71cdbe9 437 if(size >= sizeof(TlsRecord))
Sergunb 0:8918a71cdbe9 438 {
Sergunb 0:8918a71cdbe9 439 //Total number of bytes that have been received
Sergunb 0:8918a71cdbe9 440 n = 0;
Sergunb 0:8918a71cdbe9 441
Sergunb 0:8918a71cdbe9 442 //Read TLS record header
Sergunb 0:8918a71cdbe9 443 error = context->receiveCallback(context->handle,
Sergunb 0:8918a71cdbe9 444 data + context->rxRecordPos,
Sergunb 0:8918a71cdbe9 445 sizeof(TlsRecord) - context->rxRecordPos, &n, 0);
Sergunb 0:8918a71cdbe9 446
Sergunb 0:8918a71cdbe9 447 //Check status code
Sergunb 0:8918a71cdbe9 448 if(error == NO_ERROR || error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
Sergunb 0:8918a71cdbe9 449 {
Sergunb 0:8918a71cdbe9 450 //Advance data pointer
Sergunb 0:8918a71cdbe9 451 context->rxRecordPos += n;
Sergunb 0:8918a71cdbe9 452
Sergunb 0:8918a71cdbe9 453 //TLS record header successfully received?
Sergunb 0:8918a71cdbe9 454 if(context->rxRecordPos >= sizeof(TlsRecord))
Sergunb 0:8918a71cdbe9 455 {
Sergunb 0:8918a71cdbe9 456 //Debug message
Sergunb 0:8918a71cdbe9 457 TRACE_DEBUG("Record header received:\r\n");
Sergunb 0:8918a71cdbe9 458 TRACE_DEBUG_ARRAY(" ", record, sizeof(record));
Sergunb 0:8918a71cdbe9 459
Sergunb 0:8918a71cdbe9 460 //Retrieve the length of the TLS record
Sergunb 0:8918a71cdbe9 461 context->rxRecordLen = sizeof(TlsRecord) + ntohs(record->length);
Sergunb 0:8918a71cdbe9 462 }
Sergunb 0:8918a71cdbe9 463 }
Sergunb 0:8918a71cdbe9 464 else
Sergunb 0:8918a71cdbe9 465 {
Sergunb 0:8918a71cdbe9 466 //The read operation has failed
Sergunb 0:8918a71cdbe9 467 error = ERROR_READ_FAILED;
Sergunb 0:8918a71cdbe9 468 }
Sergunb 0:8918a71cdbe9 469 }
Sergunb 0:8918a71cdbe9 470 else
Sergunb 0:8918a71cdbe9 471 {
Sergunb 0:8918a71cdbe9 472 //Report an error
Sergunb 0:8918a71cdbe9 473 error = ERROR_RECORD_OVERFLOW;
Sergunb 0:8918a71cdbe9 474 }
Sergunb 0:8918a71cdbe9 475 }
Sergunb 0:8918a71cdbe9 476 else if(context->rxRecordPos < context->rxRecordLen)
Sergunb 0:8918a71cdbe9 477 {
Sergunb 0:8918a71cdbe9 478 //Make sure that the buffer is large enough to hold the entire record
Sergunb 0:8918a71cdbe9 479 if(size >= context->rxRecordLen)
Sergunb 0:8918a71cdbe9 480 {
Sergunb 0:8918a71cdbe9 481 //Total number of bytes that have been received
Sergunb 0:8918a71cdbe9 482 n = 0;
Sergunb 0:8918a71cdbe9 483
Sergunb 0:8918a71cdbe9 484 //Read TLS record contents
Sergunb 0:8918a71cdbe9 485 error = context->receiveCallback(context->handle,
Sergunb 0:8918a71cdbe9 486 data + context->rxRecordPos,
Sergunb 0:8918a71cdbe9 487 context->rxRecordLen - context->rxRecordPos, &n, 0);
Sergunb 0:8918a71cdbe9 488
Sergunb 0:8918a71cdbe9 489 //Check status code
Sergunb 0:8918a71cdbe9 490 if(error == NO_ERROR || error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
Sergunb 0:8918a71cdbe9 491 {
Sergunb 0:8918a71cdbe9 492 //Advance data pointer
Sergunb 0:8918a71cdbe9 493 context->rxRecordPos += n;
Sergunb 0:8918a71cdbe9 494 }
Sergunb 0:8918a71cdbe9 495 else
Sergunb 0:8918a71cdbe9 496 {
Sergunb 0:8918a71cdbe9 497 //The read operation has failed
Sergunb 0:8918a71cdbe9 498 error = ERROR_READ_FAILED;
Sergunb 0:8918a71cdbe9 499 }
Sergunb 0:8918a71cdbe9 500 }
Sergunb 0:8918a71cdbe9 501 else
Sergunb 0:8918a71cdbe9 502 {
Sergunb 0:8918a71cdbe9 503 //Report an error
Sergunb 0:8918a71cdbe9 504 error = ERROR_RECORD_OVERFLOW;
Sergunb 0:8918a71cdbe9 505 }
Sergunb 0:8918a71cdbe9 506 }
Sergunb 0:8918a71cdbe9 507 else
Sergunb 0:8918a71cdbe9 508 {
Sergunb 0:8918a71cdbe9 509 //Check current state
Sergunb 0:8918a71cdbe9 510 if(context->state > TLS_STATE_SERVER_HELLO)
Sergunb 0:8918a71cdbe9 511 {
Sergunb 0:8918a71cdbe9 512 //Once the server has sent the ServerHello message, enforce
Sergunb 0:8918a71cdbe9 513 //incoming record versions
Sergunb 0:8918a71cdbe9 514 if(ntohs(record->version) != context->version)
Sergunb 0:8918a71cdbe9 515 error = ERROR_VERSION_NOT_SUPPORTED;
Sergunb 0:8918a71cdbe9 516 }
Sergunb 0:8918a71cdbe9 517
Sergunb 0:8918a71cdbe9 518 //Check status code
Sergunb 0:8918a71cdbe9 519 if(!error)
Sergunb 0:8918a71cdbe9 520 {
Sergunb 0:8918a71cdbe9 521 //Record payload is protected?
Sergunb 0:8918a71cdbe9 522 if(context->changeCipherSpecReceived)
Sergunb 0:8918a71cdbe9 523 {
Sergunb 0:8918a71cdbe9 524 //Decrypt TLS record
Sergunb 0:8918a71cdbe9 525 error = tlsDecryptRecord(context, record);
Sergunb 0:8918a71cdbe9 526 }
Sergunb 0:8918a71cdbe9 527 }
Sergunb 0:8918a71cdbe9 528
Sergunb 0:8918a71cdbe9 529 //Check status code
Sergunb 0:8918a71cdbe9 530 if(!error)
Sergunb 0:8918a71cdbe9 531 {
Sergunb 0:8918a71cdbe9 532 //Actual length of the record data
Sergunb 0:8918a71cdbe9 533 *length = ntohs(record->length);
Sergunb 0:8918a71cdbe9 534 //Record type
Sergunb 0:8918a71cdbe9 535 *contentType = (TlsContentType) record->type;
Sergunb 0:8918a71cdbe9 536
Sergunb 0:8918a71cdbe9 537 //Debug message
Sergunb 0:8918a71cdbe9 538 TRACE_DEBUG("TLS record received (%" PRIuSIZE " bytes)...\r\n", *length);
Sergunb 0:8918a71cdbe9 539 TRACE_DEBUG_ARRAY(" ", record, *length + sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 540
Sergunb 0:8918a71cdbe9 541 //Discard record header
Sergunb 0:8918a71cdbe9 542 memmove(data, record->data, *length);
Sergunb 0:8918a71cdbe9 543
Sergunb 0:8918a71cdbe9 544 //Prepare to receive the next TLS record
Sergunb 0:8918a71cdbe9 545 context->rxRecordLen = 0;
Sergunb 0:8918a71cdbe9 546 context->rxRecordPos = 0;
Sergunb 0:8918a71cdbe9 547
Sergunb 0:8918a71cdbe9 548 //We are done
Sergunb 0:8918a71cdbe9 549 break;
Sergunb 0:8918a71cdbe9 550 }
Sergunb 0:8918a71cdbe9 551 }
Sergunb 0:8918a71cdbe9 552 }
Sergunb 0:8918a71cdbe9 553
Sergunb 0:8918a71cdbe9 554 //Return status code
Sergunb 0:8918a71cdbe9 555 return error;
Sergunb 0:8918a71cdbe9 556 }
Sergunb 0:8918a71cdbe9 557
Sergunb 0:8918a71cdbe9 558
Sergunb 0:8918a71cdbe9 559 /**
Sergunb 0:8918a71cdbe9 560 * @brief Encrypt an outgoing TLS record
Sergunb 0:8918a71cdbe9 561 * @param[in] context Pointer to the TLS context
Sergunb 0:8918a71cdbe9 562 * @param[in,out] record TLS record to be encrypted
Sergunb 0:8918a71cdbe9 563 * @return Error code
Sergunb 0:8918a71cdbe9 564 **/
Sergunb 0:8918a71cdbe9 565
Sergunb 0:8918a71cdbe9 566 error_t tlsEncryptRecord(TlsContext *context, TlsRecord *record)
Sergunb 0:8918a71cdbe9 567 {
Sergunb 0:8918a71cdbe9 568 error_t error;
Sergunb 0:8918a71cdbe9 569 size_t length;
Sergunb 0:8918a71cdbe9 570
Sergunb 0:8918a71cdbe9 571 //Convert the length field to host byte order
Sergunb 0:8918a71cdbe9 572 length = ntohs(record->length);
Sergunb 0:8918a71cdbe9 573
Sergunb 0:8918a71cdbe9 574 //Message authentication is required?
Sergunb 0:8918a71cdbe9 575 if(context->hashAlgo != NULL)
Sergunb 0:8918a71cdbe9 576 {
Sergunb 0:8918a71cdbe9 577 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= SSL_VERSION_3_0)
Sergunb 0:8918a71cdbe9 578 //Check whether SSL 3.0 is currently used
Sergunb 0:8918a71cdbe9 579 if(context->version == SSL_VERSION_3_0)
Sergunb 0:8918a71cdbe9 580 {
Sergunb 0:8918a71cdbe9 581 //SSL 3.0 uses an older obsolete version of the HMAC construction
Sergunb 0:8918a71cdbe9 582 error = sslComputeMac(context, context->writeMacKey,
Sergunb 0:8918a71cdbe9 583 context->writeSeqNum, record, record->data, length, record->data + length);
Sergunb 0:8918a71cdbe9 584 //Any error to report?
Sergunb 0:8918a71cdbe9 585 if(error)
Sergunb 0:8918a71cdbe9 586 return error;
Sergunb 0:8918a71cdbe9 587 }
Sergunb 0:8918a71cdbe9 588 else
Sergunb 0:8918a71cdbe9 589 #endif
Sergunb 0:8918a71cdbe9 590 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
Sergunb 0:8918a71cdbe9 591 //Check whether TLS 1.0, TLS 1.1 or TLS 1.2 is currently used
Sergunb 0:8918a71cdbe9 592 if(context->version >= TLS_VERSION_1_0)
Sergunb 0:8918a71cdbe9 593 {
Sergunb 0:8918a71cdbe9 594 //TLS uses a HMAC construction
Sergunb 0:8918a71cdbe9 595 hmacInit(&context->hmacContext, context->hashAlgo,
Sergunb 0:8918a71cdbe9 596 context->writeMacKey, context->macKeyLen);
Sergunb 0:8918a71cdbe9 597
Sergunb 0:8918a71cdbe9 598 //Compute MAC over the sequence number and the record contents
Sergunb 0:8918a71cdbe9 599 hmacUpdate(&context->hmacContext, context->writeSeqNum, sizeof(TlsSequenceNumber));
Sergunb 0:8918a71cdbe9 600 hmacUpdate(&context->hmacContext, record, length + sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 601
Sergunb 0:8918a71cdbe9 602 //Append the resulting MAC to the message
Sergunb 0:8918a71cdbe9 603 hmacFinal(&context->hmacContext, record->data + length);
Sergunb 0:8918a71cdbe9 604 }
Sergunb 0:8918a71cdbe9 605 else
Sergunb 0:8918a71cdbe9 606 #endif
Sergunb 0:8918a71cdbe9 607 //The negotiated TLS version is not valid...
Sergunb 0:8918a71cdbe9 608 {
Sergunb 0:8918a71cdbe9 609 //Report an error
Sergunb 0:8918a71cdbe9 610 return ERROR_INVALID_VERSION;
Sergunb 0:8918a71cdbe9 611 }
Sergunb 0:8918a71cdbe9 612
Sergunb 0:8918a71cdbe9 613 //Debug message
Sergunb 0:8918a71cdbe9 614 TRACE_DEBUG("Write sequence number:\r\n");
Sergunb 0:8918a71cdbe9 615 TRACE_DEBUG_ARRAY(" ", context->writeSeqNum, sizeof(TlsSequenceNumber));
Sergunb 0:8918a71cdbe9 616 TRACE_DEBUG("Computed MAC:\r\n");
Sergunb 0:8918a71cdbe9 617 TRACE_DEBUG_ARRAY(" ", record->data + length, context->hashAlgo->digestSize);
Sergunb 0:8918a71cdbe9 618
Sergunb 0:8918a71cdbe9 619 //Adjust the length of the message
Sergunb 0:8918a71cdbe9 620 length += context->hashAlgo->digestSize;
Sergunb 0:8918a71cdbe9 621 //Fix length field
Sergunb 0:8918a71cdbe9 622 record->length = htons(length);
Sergunb 0:8918a71cdbe9 623
Sergunb 0:8918a71cdbe9 624 //Increment sequence number
Sergunb 0:8918a71cdbe9 625 tlsIncSequenceNumber(context->writeSeqNum);
Sergunb 0:8918a71cdbe9 626 }
Sergunb 0:8918a71cdbe9 627
Sergunb 0:8918a71cdbe9 628 //Encryption is required?
Sergunb 0:8918a71cdbe9 629 if(context->cipherMode != CIPHER_MODE_NULL)
Sergunb 0:8918a71cdbe9 630 {
Sergunb 0:8918a71cdbe9 631 //Debug message
Sergunb 0:8918a71cdbe9 632 TRACE_DEBUG("Record to be encrypted (%" PRIuSIZE " bytes):\r\n", length);
Sergunb 0:8918a71cdbe9 633 TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 634
Sergunb 0:8918a71cdbe9 635 #if (TLS_STREAM_CIPHER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 636 //Stream cipher?
Sergunb 0:8918a71cdbe9 637 if(context->cipherMode == CIPHER_MODE_STREAM)
Sergunb 0:8918a71cdbe9 638 {
Sergunb 0:8918a71cdbe9 639 //Encrypt record contents
Sergunb 0:8918a71cdbe9 640 context->cipherAlgo->encryptStream(context->writeCipherContext,
Sergunb 0:8918a71cdbe9 641 record->data, record->data, length);
Sergunb 0:8918a71cdbe9 642 }
Sergunb 0:8918a71cdbe9 643 else
Sergunb 0:8918a71cdbe9 644 #endif
Sergunb 0:8918a71cdbe9 645 #if (TLS_CBC_CIPHER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 646 //CBC block cipher?
Sergunb 0:8918a71cdbe9 647 if(context->cipherMode == CIPHER_MODE_CBC)
Sergunb 0:8918a71cdbe9 648 {
Sergunb 0:8918a71cdbe9 649 size_t i;
Sergunb 0:8918a71cdbe9 650 size_t paddingLength;
Sergunb 0:8918a71cdbe9 651
Sergunb 0:8918a71cdbe9 652 #if (TLS_MAX_VERSION >= TLS_VERSION_1_1 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
Sergunb 0:8918a71cdbe9 653 //TLS 1.1 and 1.2 use an explicit IV
Sergunb 0:8918a71cdbe9 654 if(context->version >= TLS_VERSION_1_1)
Sergunb 0:8918a71cdbe9 655 {
Sergunb 0:8918a71cdbe9 656 //Make room for the IV at the beginning of the data
Sergunb 0:8918a71cdbe9 657 memmove(record->data + context->recordIvLen, record->data, length);
Sergunb 0:8918a71cdbe9 658
Sergunb 0:8918a71cdbe9 659 //The initialization vector should be chosen at random
Sergunb 0:8918a71cdbe9 660 error = context->prngAlgo->read(context->prngContext,
Sergunb 0:8918a71cdbe9 661 record->data, context->recordIvLen);
Sergunb 0:8918a71cdbe9 662 //Any error to report?
Sergunb 0:8918a71cdbe9 663 if(error)
Sergunb 0:8918a71cdbe9 664 return error;
Sergunb 0:8918a71cdbe9 665
Sergunb 0:8918a71cdbe9 666 //Adjust the length of the message
Sergunb 0:8918a71cdbe9 667 length += context->recordIvLen;
Sergunb 0:8918a71cdbe9 668 }
Sergunb 0:8918a71cdbe9 669 #endif
Sergunb 0:8918a71cdbe9 670 //Get the actual amount of bytes in the last block
Sergunb 0:8918a71cdbe9 671 paddingLength = (length + 1) % context->cipherAlgo->blockSize;
Sergunb 0:8918a71cdbe9 672
Sergunb 0:8918a71cdbe9 673 //Padding is added to force the length of the plaintext to be
Sergunb 0:8918a71cdbe9 674 //an integral multiple of the cipher's block length
Sergunb 0:8918a71cdbe9 675 if(paddingLength > 0)
Sergunb 0:8918a71cdbe9 676 paddingLength = context->cipherAlgo->blockSize - paddingLength;
Sergunb 0:8918a71cdbe9 677
Sergunb 0:8918a71cdbe9 678 //Write padding bytes
Sergunb 0:8918a71cdbe9 679 for(i = 0; i <= paddingLength; i++)
Sergunb 0:8918a71cdbe9 680 record->data[length + i] = (uint8_t) paddingLength;
Sergunb 0:8918a71cdbe9 681
Sergunb 0:8918a71cdbe9 682 //Compute the length of the resulting message
Sergunb 0:8918a71cdbe9 683 length += paddingLength + 1;
Sergunb 0:8918a71cdbe9 684 //Fix length field
Sergunb 0:8918a71cdbe9 685 record->length = htons(length);
Sergunb 0:8918a71cdbe9 686
Sergunb 0:8918a71cdbe9 687 //Debug message
Sergunb 0:8918a71cdbe9 688 TRACE_DEBUG("Record with padding (%" PRIuSIZE " bytes):\r\n", length);
Sergunb 0:8918a71cdbe9 689 TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 690
Sergunb 0:8918a71cdbe9 691 //CBC encryption
Sergunb 0:8918a71cdbe9 692 error = cbcEncrypt(context->cipherAlgo, context->writeCipherContext,
Sergunb 0:8918a71cdbe9 693 context->writeIv, record->data, record->data, length);
Sergunb 0:8918a71cdbe9 694 //Any error to report?
Sergunb 0:8918a71cdbe9 695 if(error)
Sergunb 0:8918a71cdbe9 696 return error;
Sergunb 0:8918a71cdbe9 697 }
Sergunb 0:8918a71cdbe9 698 else
Sergunb 0:8918a71cdbe9 699 #endif
Sergunb 0:8918a71cdbe9 700 #if (TLS_CCM_CIPHER_SUPPORT == ENABLED || TLS_CCM_8_CIPHER_SUPPORT == ENABLED || \
Sergunb 0:8918a71cdbe9 701 TLS_GCM_CIPHER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 702 //CCM or GCM AEAD cipher?
Sergunb 0:8918a71cdbe9 703 if(context->cipherMode == CIPHER_MODE_CCM ||
Sergunb 0:8918a71cdbe9 704 context->cipherMode == CIPHER_MODE_GCM)
Sergunb 0:8918a71cdbe9 705 {
Sergunb 0:8918a71cdbe9 706 uint8_t *data;
Sergunb 0:8918a71cdbe9 707 uint8_t *tag;
Sergunb 0:8918a71cdbe9 708 size_t nonceLength;
Sergunb 0:8918a71cdbe9 709 uint8_t nonce[12];
Sergunb 0:8918a71cdbe9 710 uint8_t a[13];
Sergunb 0:8918a71cdbe9 711
Sergunb 0:8918a71cdbe9 712 //Determine the total length of the nonce
Sergunb 0:8918a71cdbe9 713 nonceLength = context->fixedIvLen + context->recordIvLen;
Sergunb 0:8918a71cdbe9 714 //The salt is the implicit part of the nonce and is not sent in the packet
Sergunb 0:8918a71cdbe9 715 memcpy(nonce, context->writeIv, context->fixedIvLen);
Sergunb 0:8918a71cdbe9 716
Sergunb 0:8918a71cdbe9 717 //The explicit part of the nonce is chosen by the sender
Sergunb 0:8918a71cdbe9 718 error = context->prngAlgo->read(context->prngContext,
Sergunb 0:8918a71cdbe9 719 nonce + context->fixedIvLen, context->recordIvLen);
Sergunb 0:8918a71cdbe9 720 //Any error to report?
Sergunb 0:8918a71cdbe9 721 if(error)
Sergunb 0:8918a71cdbe9 722 return error;
Sergunb 0:8918a71cdbe9 723
Sergunb 0:8918a71cdbe9 724 //Make room for the explicit nonce at the beginning of the record
Sergunb 0:8918a71cdbe9 725 memmove(record->data + context->recordIvLen, record->data, length);
Sergunb 0:8918a71cdbe9 726 //The explicit part of the nonce is carried in each TLS record
Sergunb 0:8918a71cdbe9 727 memcpy(record->data, nonce + context->fixedIvLen, context->recordIvLen);
Sergunb 0:8918a71cdbe9 728
Sergunb 0:8918a71cdbe9 729 //Additional data to be authenticated
Sergunb 0:8918a71cdbe9 730 memcpy(a, context->writeSeqNum, sizeof(TlsSequenceNumber));
Sergunb 0:8918a71cdbe9 731 memcpy(a + sizeof(TlsSequenceNumber), record, sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 732
Sergunb 0:8918a71cdbe9 733 //Point to the plaintext
Sergunb 0:8918a71cdbe9 734 data = record->data + context->recordIvLen;
Sergunb 0:8918a71cdbe9 735 //Point to the buffer where to store the authentication tag
Sergunb 0:8918a71cdbe9 736 tag = data + length;
Sergunb 0:8918a71cdbe9 737
Sergunb 0:8918a71cdbe9 738 #if (TLS_CCM_CIPHER_SUPPORT == ENABLED || TLS_CCM_8_CIPHER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 739 //CCM AEAD cipher?
Sergunb 0:8918a71cdbe9 740 if(context->cipherMode == CIPHER_MODE_CCM)
Sergunb 0:8918a71cdbe9 741 {
Sergunb 0:8918a71cdbe9 742 //Authenticated encryption using CCM
Sergunb 0:8918a71cdbe9 743 error = ccmEncrypt(context->cipherAlgo, context->writeCipherContext,
Sergunb 0:8918a71cdbe9 744 nonce, nonceLength, a, 13, data, data, length, tag, context->authTagLen);
Sergunb 0:8918a71cdbe9 745 }
Sergunb 0:8918a71cdbe9 746 else
Sergunb 0:8918a71cdbe9 747 #endif
Sergunb 0:8918a71cdbe9 748 #if (TLS_GCM_CIPHER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 749 //GCM AEAD cipher?
Sergunb 0:8918a71cdbe9 750 if(context->cipherMode == CIPHER_MODE_GCM)
Sergunb 0:8918a71cdbe9 751 {
Sergunb 0:8918a71cdbe9 752 //Authenticated encryption using GCM
Sergunb 0:8918a71cdbe9 753 error = gcmEncrypt(context->writeGcmContext, nonce, nonceLength,
Sergunb 0:8918a71cdbe9 754 a, 13, data, data, length, tag, context->authTagLen);
Sergunb 0:8918a71cdbe9 755 }
Sergunb 0:8918a71cdbe9 756 else
Sergunb 0:8918a71cdbe9 757 #endif
Sergunb 0:8918a71cdbe9 758 //Invalid cipher mode?
Sergunb 0:8918a71cdbe9 759 {
Sergunb 0:8918a71cdbe9 760 //The specified cipher mode is not supported
Sergunb 0:8918a71cdbe9 761 error = ERROR_UNSUPPORTED_CIPHER_MODE;
Sergunb 0:8918a71cdbe9 762 }
Sergunb 0:8918a71cdbe9 763
Sergunb 0:8918a71cdbe9 764 //Failed to encrypt data?
Sergunb 0:8918a71cdbe9 765 if(error)
Sergunb 0:8918a71cdbe9 766 return error;
Sergunb 0:8918a71cdbe9 767
Sergunb 0:8918a71cdbe9 768 //Compute the length of the resulting message
Sergunb 0:8918a71cdbe9 769 length += context->recordIvLen + context->authTagLen;
Sergunb 0:8918a71cdbe9 770 //Fix length field
Sergunb 0:8918a71cdbe9 771 record->length = htons(length);
Sergunb 0:8918a71cdbe9 772
Sergunb 0:8918a71cdbe9 773 //Increment sequence number
Sergunb 0:8918a71cdbe9 774 tlsIncSequenceNumber(context->writeSeqNum);
Sergunb 0:8918a71cdbe9 775 }
Sergunb 0:8918a71cdbe9 776 else
Sergunb 0:8918a71cdbe9 777 #endif
Sergunb 0:8918a71cdbe9 778 #if (TLS_CHACHA20_POLY1305_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 779 //ChaCha20Poly1305 AEAD cipher?
Sergunb 0:8918a71cdbe9 780 if(context->cipherMode == CIPHER_MODE_CHACHA20_POLY1305)
Sergunb 0:8918a71cdbe9 781 {
Sergunb 0:8918a71cdbe9 782 size_t i;
Sergunb 0:8918a71cdbe9 783 uint8_t *tag;
Sergunb 0:8918a71cdbe9 784 uint8_t nonce[12];
Sergunb 0:8918a71cdbe9 785 uint8_t a[13];
Sergunb 0:8918a71cdbe9 786
Sergunb 0:8918a71cdbe9 787 //The 64-bit record sequence number is serialized as an 8-byte,
Sergunb 0:8918a71cdbe9 788 //big-endian value and padded on the left with four 0x00 bytes
Sergunb 0:8918a71cdbe9 789 memcpy(nonce + 4, context->writeSeqNum, 8);
Sergunb 0:8918a71cdbe9 790 memset(nonce, 0, 4);
Sergunb 0:8918a71cdbe9 791
Sergunb 0:8918a71cdbe9 792 //The padded sequence number is XORed with the write IV to form
Sergunb 0:8918a71cdbe9 793 //the 96-bit nonce
Sergunb 0:8918a71cdbe9 794 for(i = 0; i < context->fixedIvLen; i++)
Sergunb 0:8918a71cdbe9 795 nonce[i] ^= context->writeIv[i];
Sergunb 0:8918a71cdbe9 796
Sergunb 0:8918a71cdbe9 797 //Additional data to be authenticated
Sergunb 0:8918a71cdbe9 798 memcpy(a, context->writeSeqNum, sizeof(TlsSequenceNumber));
Sergunb 0:8918a71cdbe9 799 memcpy(a + sizeof(TlsSequenceNumber), record, sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 800
Sergunb 0:8918a71cdbe9 801 //Point to the buffer where to store the authentication tag
Sergunb 0:8918a71cdbe9 802 tag = record->data + length;
Sergunb 0:8918a71cdbe9 803
Sergunb 0:8918a71cdbe9 804 //Authenticated encryption using ChaCha20Poly1305
Sergunb 0:8918a71cdbe9 805 error = chacha20Poly1305Encrypt(context->writeEncKey, context->encKeyLen,
Sergunb 0:8918a71cdbe9 806 nonce, 12, a, 13, record->data, record->data, length, tag, context->authTagLen);
Sergunb 0:8918a71cdbe9 807 //Failed to encrypt data?
Sergunb 0:8918a71cdbe9 808 if(error)
Sergunb 0:8918a71cdbe9 809 return error;
Sergunb 0:8918a71cdbe9 810
Sergunb 0:8918a71cdbe9 811 //Compute the length of the resulting message
Sergunb 0:8918a71cdbe9 812 length += context->authTagLen;
Sergunb 0:8918a71cdbe9 813 //Fix length field
Sergunb 0:8918a71cdbe9 814 record->length = htons(length);
Sergunb 0:8918a71cdbe9 815
Sergunb 0:8918a71cdbe9 816 //Increment sequence number
Sergunb 0:8918a71cdbe9 817 tlsIncSequenceNumber(context->writeSeqNum);
Sergunb 0:8918a71cdbe9 818 }
Sergunb 0:8918a71cdbe9 819 else
Sergunb 0:8918a71cdbe9 820 #endif
Sergunb 0:8918a71cdbe9 821 //Invalid cipher mode?
Sergunb 0:8918a71cdbe9 822 {
Sergunb 0:8918a71cdbe9 823 //The specified cipher mode is not supported
Sergunb 0:8918a71cdbe9 824 return ERROR_UNSUPPORTED_CIPHER_MODE;
Sergunb 0:8918a71cdbe9 825 }
Sergunb 0:8918a71cdbe9 826
Sergunb 0:8918a71cdbe9 827 //Debug message
Sergunb 0:8918a71cdbe9 828 TRACE_DEBUG("Encrypted record (%" PRIuSIZE " bytes):\r\n", length);
Sergunb 0:8918a71cdbe9 829 TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 830 }
Sergunb 0:8918a71cdbe9 831
Sergunb 0:8918a71cdbe9 832 //Successful encryption
Sergunb 0:8918a71cdbe9 833 return NO_ERROR;
Sergunb 0:8918a71cdbe9 834 }
Sergunb 0:8918a71cdbe9 835
Sergunb 0:8918a71cdbe9 836
Sergunb 0:8918a71cdbe9 837 /**
Sergunb 0:8918a71cdbe9 838 * @brief Decrypt an incoming TLS record
Sergunb 0:8918a71cdbe9 839 * @param[in] context Pointer to the TLS context
Sergunb 0:8918a71cdbe9 840 * @param[in,out] record TLS record to be decrypted
Sergunb 0:8918a71cdbe9 841 * @return Error code
Sergunb 0:8918a71cdbe9 842 **/
Sergunb 0:8918a71cdbe9 843
Sergunb 0:8918a71cdbe9 844 error_t tlsDecryptRecord(TlsContext *context, TlsRecord *record)
Sergunb 0:8918a71cdbe9 845 {
Sergunb 0:8918a71cdbe9 846 error_t error;
Sergunb 0:8918a71cdbe9 847 size_t length;
Sergunb 0:8918a71cdbe9 848
Sergunb 0:8918a71cdbe9 849 //Convert the length field to host byte order
Sergunb 0:8918a71cdbe9 850 length = ntohs(record->length);
Sergunb 0:8918a71cdbe9 851
Sergunb 0:8918a71cdbe9 852 //Decrypt record if necessary
Sergunb 0:8918a71cdbe9 853 if(context->cipherMode != CIPHER_MODE_NULL)
Sergunb 0:8918a71cdbe9 854 {
Sergunb 0:8918a71cdbe9 855 //Debug message
Sergunb 0:8918a71cdbe9 856 TRACE_DEBUG("Record to be decrypted (%" PRIuSIZE " bytes):\r\n", length);
Sergunb 0:8918a71cdbe9 857 TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 858
Sergunb 0:8918a71cdbe9 859 #if (TLS_STREAM_CIPHER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 860 //Stream cipher?
Sergunb 0:8918a71cdbe9 861 if(context->cipherMode == CIPHER_MODE_STREAM)
Sergunb 0:8918a71cdbe9 862 {
Sergunb 0:8918a71cdbe9 863 //Decrypt record contents
Sergunb 0:8918a71cdbe9 864 context->cipherAlgo->decryptStream(context->readCipherContext,
Sergunb 0:8918a71cdbe9 865 record->data, record->data, length);
Sergunb 0:8918a71cdbe9 866 }
Sergunb 0:8918a71cdbe9 867 else
Sergunb 0:8918a71cdbe9 868 #endif
Sergunb 0:8918a71cdbe9 869 #if (TLS_CBC_CIPHER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 870 //CBC block cipher?
Sergunb 0:8918a71cdbe9 871 if(context->cipherMode == CIPHER_MODE_CBC)
Sergunb 0:8918a71cdbe9 872 {
Sergunb 0:8918a71cdbe9 873 size_t i;
Sergunb 0:8918a71cdbe9 874 size_t paddingLength;
Sergunb 0:8918a71cdbe9 875
Sergunb 0:8918a71cdbe9 876 //The length of the data must be a multiple of the block size
Sergunb 0:8918a71cdbe9 877 if((length % context->cipherAlgo->blockSize) != 0)
Sergunb 0:8918a71cdbe9 878 return ERROR_DECODING_FAILED;
Sergunb 0:8918a71cdbe9 879
Sergunb 0:8918a71cdbe9 880 //CBC decryption
Sergunb 0:8918a71cdbe9 881 error = cbcDecrypt(context->cipherAlgo, context->readCipherContext,
Sergunb 0:8918a71cdbe9 882 context->readIv, record->data, record->data, length);
Sergunb 0:8918a71cdbe9 883 //Any error to report?
Sergunb 0:8918a71cdbe9 884 if(error)
Sergunb 0:8918a71cdbe9 885 return error;
Sergunb 0:8918a71cdbe9 886
Sergunb 0:8918a71cdbe9 887 //Debug message
Sergunb 0:8918a71cdbe9 888 TRACE_DEBUG("Record with padding (%" PRIuSIZE " bytes):\r\n", length);
Sergunb 0:8918a71cdbe9 889 TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 890
Sergunb 0:8918a71cdbe9 891 #if (TLS_MAX_VERSION >= TLS_VERSION_1_1 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
Sergunb 0:8918a71cdbe9 892 //TLS 1.1 and 1.2 use an explicit IV
Sergunb 0:8918a71cdbe9 893 if(context->version >= TLS_VERSION_1_1)
Sergunb 0:8918a71cdbe9 894 {
Sergunb 0:8918a71cdbe9 895 //Make sure the message length is acceptable
Sergunb 0:8918a71cdbe9 896 if(length < context->recordIvLen)
Sergunb 0:8918a71cdbe9 897 return ERROR_DECODING_FAILED;
Sergunb 0:8918a71cdbe9 898
Sergunb 0:8918a71cdbe9 899 //Adjust the length of the message
Sergunb 0:8918a71cdbe9 900 length -= context->recordIvLen;
Sergunb 0:8918a71cdbe9 901 //Discard the first cipher block (corresponding to the explicit IV)
Sergunb 0:8918a71cdbe9 902 memmove(record->data, record->data + context->recordIvLen, length);
Sergunb 0:8918a71cdbe9 903 }
Sergunb 0:8918a71cdbe9 904 #endif
Sergunb 0:8918a71cdbe9 905 //Make sure the message length is acceptable
Sergunb 0:8918a71cdbe9 906 if(length < context->cipherAlgo->blockSize)
Sergunb 0:8918a71cdbe9 907 return ERROR_DECODING_FAILED;
Sergunb 0:8918a71cdbe9 908
Sergunb 0:8918a71cdbe9 909 //Compute the length of the padding string
Sergunb 0:8918a71cdbe9 910 paddingLength = record->data[length - 1];
Sergunb 0:8918a71cdbe9 911 //Erroneous padding length?
Sergunb 0:8918a71cdbe9 912 if(paddingLength >= length)
Sergunb 0:8918a71cdbe9 913 return ERROR_BAD_RECORD_MAC;
Sergunb 0:8918a71cdbe9 914
Sergunb 0:8918a71cdbe9 915 //The receiver must check the padding
Sergunb 0:8918a71cdbe9 916 for(i = 0; i <= paddingLength; i++)
Sergunb 0:8918a71cdbe9 917 {
Sergunb 0:8918a71cdbe9 918 //Each byte in the padding data must be filled
Sergunb 0:8918a71cdbe9 919 //with the padding length value
Sergunb 0:8918a71cdbe9 920 if(record->data[length - 1 - i] != paddingLength)
Sergunb 0:8918a71cdbe9 921 return ERROR_BAD_RECORD_MAC;
Sergunb 0:8918a71cdbe9 922 }
Sergunb 0:8918a71cdbe9 923
Sergunb 0:8918a71cdbe9 924 //Remove padding bytes
Sergunb 0:8918a71cdbe9 925 length -= paddingLength + 1;
Sergunb 0:8918a71cdbe9 926 //Fix the length field of the TLS record
Sergunb 0:8918a71cdbe9 927 record->length = htons(length);
Sergunb 0:8918a71cdbe9 928 }
Sergunb 0:8918a71cdbe9 929 else
Sergunb 0:8918a71cdbe9 930 #endif
Sergunb 0:8918a71cdbe9 931 #if (TLS_CCM_CIPHER_SUPPORT == ENABLED || TLS_CCM_8_CIPHER_SUPPORT == ENABLED || \
Sergunb 0:8918a71cdbe9 932 TLS_GCM_CIPHER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 933 //CCM or GCM AEAD cipher?
Sergunb 0:8918a71cdbe9 934 if(context->cipherMode == CIPHER_MODE_CCM ||
Sergunb 0:8918a71cdbe9 935 context->cipherMode == CIPHER_MODE_GCM)
Sergunb 0:8918a71cdbe9 936 {
Sergunb 0:8918a71cdbe9 937 uint8_t *ciphertext;
Sergunb 0:8918a71cdbe9 938 uint8_t *tag;
Sergunb 0:8918a71cdbe9 939 size_t nonceLength;
Sergunb 0:8918a71cdbe9 940 uint8_t nonce[12];
Sergunb 0:8918a71cdbe9 941 uint8_t a[13];
Sergunb 0:8918a71cdbe9 942
Sergunb 0:8918a71cdbe9 943 //Make sure the message length is acceptable
Sergunb 0:8918a71cdbe9 944 if(length < (context->recordIvLen + context->authTagLen))
Sergunb 0:8918a71cdbe9 945 return ERROR_DECODING_FAILED;
Sergunb 0:8918a71cdbe9 946
Sergunb 0:8918a71cdbe9 947 //Determine the total length of the nonce
Sergunb 0:8918a71cdbe9 948 nonceLength = context->fixedIvLen + context->recordIvLen;
Sergunb 0:8918a71cdbe9 949 //The salt is the implicit part of the nonce and is not sent in the packet
Sergunb 0:8918a71cdbe9 950 memcpy(nonce, context->readIv, context->fixedIvLen);
Sergunb 0:8918a71cdbe9 951 //The explicit part of the nonce is chosen by the sender
Sergunb 0:8918a71cdbe9 952 memcpy(nonce + context->fixedIvLen, record->data, context->recordIvLen);
Sergunb 0:8918a71cdbe9 953
Sergunb 0:8918a71cdbe9 954 //Calculate the length of the ciphertext
Sergunb 0:8918a71cdbe9 955 length -= context->recordIvLen + context->authTagLen;
Sergunb 0:8918a71cdbe9 956 //Fix the length field of the TLS record
Sergunb 0:8918a71cdbe9 957 record->length = htons(length);
Sergunb 0:8918a71cdbe9 958
Sergunb 0:8918a71cdbe9 959 //Additional data to be authenticated
Sergunb 0:8918a71cdbe9 960 memcpy(a, context->readSeqNum, sizeof(TlsSequenceNumber));
Sergunb 0:8918a71cdbe9 961 memcpy(a + sizeof(TlsSequenceNumber), record, sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 962
Sergunb 0:8918a71cdbe9 963 //Point to the ciphertext
Sergunb 0:8918a71cdbe9 964 ciphertext = record->data + context->recordIvLen;
Sergunb 0:8918a71cdbe9 965 //Point to the authentication tag
Sergunb 0:8918a71cdbe9 966 tag = ciphertext + length;
Sergunb 0:8918a71cdbe9 967
Sergunb 0:8918a71cdbe9 968 #if (TLS_CCM_CIPHER_SUPPORT == ENABLED || TLS_CCM_8_CIPHER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 969 //CCM AEAD cipher?
Sergunb 0:8918a71cdbe9 970 if(context->cipherMode == CIPHER_MODE_CCM)
Sergunb 0:8918a71cdbe9 971 {
Sergunb 0:8918a71cdbe9 972 //Authenticated decryption using CCM
Sergunb 0:8918a71cdbe9 973 error = ccmDecrypt(context->cipherAlgo, context->readCipherContext,
Sergunb 0:8918a71cdbe9 974 nonce, nonceLength, a, 13, ciphertext, ciphertext, length, tag, context->authTagLen);
Sergunb 0:8918a71cdbe9 975 }
Sergunb 0:8918a71cdbe9 976 else
Sergunb 0:8918a71cdbe9 977 #endif
Sergunb 0:8918a71cdbe9 978 #if (TLS_GCM_CIPHER_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 979 //GCM AEAD cipher?
Sergunb 0:8918a71cdbe9 980 if(context->cipherMode == CIPHER_MODE_GCM)
Sergunb 0:8918a71cdbe9 981 {
Sergunb 0:8918a71cdbe9 982 //Authenticated decryption using GCM
Sergunb 0:8918a71cdbe9 983 error = gcmDecrypt(context->readGcmContext, nonce, nonceLength,
Sergunb 0:8918a71cdbe9 984 a, 13, ciphertext, ciphertext, length, tag, context->authTagLen);
Sergunb 0:8918a71cdbe9 985 }
Sergunb 0:8918a71cdbe9 986 else
Sergunb 0:8918a71cdbe9 987 #endif
Sergunb 0:8918a71cdbe9 988 //Invalid cipher mode?
Sergunb 0:8918a71cdbe9 989 {
Sergunb 0:8918a71cdbe9 990 //The specified cipher mode is not supported
Sergunb 0:8918a71cdbe9 991 error = ERROR_UNSUPPORTED_CIPHER_MODE;
Sergunb 0:8918a71cdbe9 992 }
Sergunb 0:8918a71cdbe9 993
Sergunb 0:8918a71cdbe9 994 //Wrong authentication tag?
Sergunb 0:8918a71cdbe9 995 if(error)
Sergunb 0:8918a71cdbe9 996 return ERROR_BAD_RECORD_MAC;
Sergunb 0:8918a71cdbe9 997
Sergunb 0:8918a71cdbe9 998 //Discard the explicit part of the nonce
Sergunb 0:8918a71cdbe9 999 memmove(record->data, record->data + context->recordIvLen, length);
Sergunb 0:8918a71cdbe9 1000
Sergunb 0:8918a71cdbe9 1001 //Increment sequence number
Sergunb 0:8918a71cdbe9 1002 tlsIncSequenceNumber(context->readSeqNum);
Sergunb 0:8918a71cdbe9 1003 }
Sergunb 0:8918a71cdbe9 1004 else
Sergunb 0:8918a71cdbe9 1005 #endif
Sergunb 0:8918a71cdbe9 1006 #if (TLS_CHACHA20_POLY1305_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 1007 //ChaCha20Poly1305 AEAD cipher?
Sergunb 0:8918a71cdbe9 1008 if(context->cipherMode == CIPHER_MODE_CHACHA20_POLY1305)
Sergunb 0:8918a71cdbe9 1009 {
Sergunb 0:8918a71cdbe9 1010 size_t i;
Sergunb 0:8918a71cdbe9 1011 uint8_t *tag;
Sergunb 0:8918a71cdbe9 1012 uint8_t nonce[12];
Sergunb 0:8918a71cdbe9 1013 uint8_t a[13];
Sergunb 0:8918a71cdbe9 1014
Sergunb 0:8918a71cdbe9 1015 //Make sure the message length is acceptable
Sergunb 0:8918a71cdbe9 1016 if(length < context->authTagLen)
Sergunb 0:8918a71cdbe9 1017 return ERROR_DECODING_FAILED;
Sergunb 0:8918a71cdbe9 1018
Sergunb 0:8918a71cdbe9 1019 //The 64-bit record sequence number is serialized as an 8-byte,
Sergunb 0:8918a71cdbe9 1020 //big-endian value and padded on the left with four 0x00 bytes
Sergunb 0:8918a71cdbe9 1021 memcpy(nonce + 4, context->readSeqNum, 8);
Sergunb 0:8918a71cdbe9 1022 memset(nonce, 0, 4);
Sergunb 0:8918a71cdbe9 1023
Sergunb 0:8918a71cdbe9 1024 //The padded sequence number is XORed with the read IV to form
Sergunb 0:8918a71cdbe9 1025 //the 96-bit nonce
Sergunb 0:8918a71cdbe9 1026 for(i = 0; i < context->fixedIvLen; i++)
Sergunb 0:8918a71cdbe9 1027 nonce[i] ^= context->readIv[i];
Sergunb 0:8918a71cdbe9 1028
Sergunb 0:8918a71cdbe9 1029 //Calculate the length of the ciphertext
Sergunb 0:8918a71cdbe9 1030 length -= context->authTagLen;
Sergunb 0:8918a71cdbe9 1031 //Fix the length field of the TLS record
Sergunb 0:8918a71cdbe9 1032 record->length = htons(length);
Sergunb 0:8918a71cdbe9 1033
Sergunb 0:8918a71cdbe9 1034 //Additional data to be authenticated
Sergunb 0:8918a71cdbe9 1035 memcpy(a, context->readSeqNum, sizeof(TlsSequenceNumber));
Sergunb 0:8918a71cdbe9 1036 memcpy(a + sizeof(TlsSequenceNumber), record, sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 1037
Sergunb 0:8918a71cdbe9 1038 //Point to the authentication tag
Sergunb 0:8918a71cdbe9 1039 tag = record->data + length;
Sergunb 0:8918a71cdbe9 1040
Sergunb 0:8918a71cdbe9 1041 //Authenticated decryption using ChaCha20Poly1305
Sergunb 0:8918a71cdbe9 1042 error = chacha20Poly1305Decrypt(context->readEncKey, context->encKeyLen,
Sergunb 0:8918a71cdbe9 1043 nonce, 12, a, 13, record->data, record->data, length, tag, context->authTagLen);
Sergunb 0:8918a71cdbe9 1044 //Wrong authentication tag?
Sergunb 0:8918a71cdbe9 1045 if(error)
Sergunb 0:8918a71cdbe9 1046 return ERROR_BAD_RECORD_MAC;
Sergunb 0:8918a71cdbe9 1047
Sergunb 0:8918a71cdbe9 1048 //Increment sequence number
Sergunb 0:8918a71cdbe9 1049 tlsIncSequenceNumber(context->readSeqNum);
Sergunb 0:8918a71cdbe9 1050 }
Sergunb 0:8918a71cdbe9 1051 else
Sergunb 0:8918a71cdbe9 1052 #endif
Sergunb 0:8918a71cdbe9 1053 //Invalid cipher mode?
Sergunb 0:8918a71cdbe9 1054 {
Sergunb 0:8918a71cdbe9 1055 //The specified cipher mode is not supported
Sergunb 0:8918a71cdbe9 1056 return ERROR_UNSUPPORTED_CIPHER_MODE;
Sergunb 0:8918a71cdbe9 1057 }
Sergunb 0:8918a71cdbe9 1058
Sergunb 0:8918a71cdbe9 1059 //Debug message
Sergunb 0:8918a71cdbe9 1060 TRACE_DEBUG("Decrypted record (%" PRIuSIZE " bytes):\r\n", length);
Sergunb 0:8918a71cdbe9 1061 TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 1062 }
Sergunb 0:8918a71cdbe9 1063
Sergunb 0:8918a71cdbe9 1064 //Check message authentication code if necessary
Sergunb 0:8918a71cdbe9 1065 if(context->hashAlgo != NULL)
Sergunb 0:8918a71cdbe9 1066 {
Sergunb 0:8918a71cdbe9 1067 //Make sure the message length is acceptable
Sergunb 0:8918a71cdbe9 1068 if(length < context->hashAlgo->digestSize)
Sergunb 0:8918a71cdbe9 1069 return ERROR_DECODING_FAILED;
Sergunb 0:8918a71cdbe9 1070
Sergunb 0:8918a71cdbe9 1071 //Adjust the length of the message
Sergunb 0:8918a71cdbe9 1072 length -= context->hashAlgo->digestSize;
Sergunb 0:8918a71cdbe9 1073 //Fix the length field of the TLS record
Sergunb 0:8918a71cdbe9 1074 record->length = htons(length);
Sergunb 0:8918a71cdbe9 1075
Sergunb 0:8918a71cdbe9 1076 #if (TLS_MAX_VERSION >= SSL_VERSION_3_0 && TLS_MIN_VERSION <= SSL_VERSION_3_0)
Sergunb 0:8918a71cdbe9 1077 //Check whether SSL 3.0 is currently used
Sergunb 0:8918a71cdbe9 1078 if(context->version == SSL_VERSION_3_0)
Sergunb 0:8918a71cdbe9 1079 {
Sergunb 0:8918a71cdbe9 1080 //SSL 3.0 uses an older obsolete version of the HMAC construction
Sergunb 0:8918a71cdbe9 1081 error = sslComputeMac(context, context->readMacKey, context->readSeqNum,
Sergunb 0:8918a71cdbe9 1082 record, record->data, length, context->hmacContext.digest);
Sergunb 0:8918a71cdbe9 1083 //Any error to report?
Sergunb 0:8918a71cdbe9 1084 if(error)
Sergunb 0:8918a71cdbe9 1085 return error;
Sergunb 0:8918a71cdbe9 1086 }
Sergunb 0:8918a71cdbe9 1087 else
Sergunb 0:8918a71cdbe9 1088 #endif
Sergunb 0:8918a71cdbe9 1089 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
Sergunb 0:8918a71cdbe9 1090 //Check whether TLS 1.0, TLS 1.1 or TLS 1.2 is currently used
Sergunb 0:8918a71cdbe9 1091 if(context->version >= TLS_VERSION_1_0)
Sergunb 0:8918a71cdbe9 1092 {
Sergunb 0:8918a71cdbe9 1093 //TLS uses a HMAC construction
Sergunb 0:8918a71cdbe9 1094 hmacInit(&context->hmacContext, context->hashAlgo,
Sergunb 0:8918a71cdbe9 1095 context->readMacKey, context->macKeyLen);
Sergunb 0:8918a71cdbe9 1096
Sergunb 0:8918a71cdbe9 1097 //Compute MAC over the sequence number and the record contents
Sergunb 0:8918a71cdbe9 1098 hmacUpdate(&context->hmacContext, context->readSeqNum, sizeof(TlsSequenceNumber));
Sergunb 0:8918a71cdbe9 1099 hmacUpdate(&context->hmacContext, record, sizeof(TlsRecord));
Sergunb 0:8918a71cdbe9 1100 hmacUpdate(&context->hmacContext, record->data, length);
Sergunb 0:8918a71cdbe9 1101 hmacFinal(&context->hmacContext, NULL);
Sergunb 0:8918a71cdbe9 1102 }
Sergunb 0:8918a71cdbe9 1103 else
Sergunb 0:8918a71cdbe9 1104 #endif
Sergunb 0:8918a71cdbe9 1105 //The negotiated TLS version is not valid...
Sergunb 0:8918a71cdbe9 1106 {
Sergunb 0:8918a71cdbe9 1107 //Report an error
Sergunb 0:8918a71cdbe9 1108 return ERROR_INVALID_VERSION;
Sergunb 0:8918a71cdbe9 1109 }
Sergunb 0:8918a71cdbe9 1110
Sergunb 0:8918a71cdbe9 1111 //Debug message
Sergunb 0:8918a71cdbe9 1112 TRACE_DEBUG("Read sequence number:\r\n");
Sergunb 0:8918a71cdbe9 1113 TRACE_DEBUG_ARRAY(" ", context->readSeqNum, sizeof(TlsSequenceNumber));
Sergunb 0:8918a71cdbe9 1114 TRACE_DEBUG("Computed MAC:\r\n");
Sergunb 0:8918a71cdbe9 1115 TRACE_DEBUG_ARRAY(" ", context->hmacContext.digest, context->hashAlgo->digestSize);
Sergunb 0:8918a71cdbe9 1116
Sergunb 0:8918a71cdbe9 1117 //Check the message authentication code
Sergunb 0:8918a71cdbe9 1118 if(memcmp(record->data + length, context->hmacContext.digest, context->hashAlgo->digestSize))
Sergunb 0:8918a71cdbe9 1119 return ERROR_BAD_RECORD_MAC;
Sergunb 0:8918a71cdbe9 1120
Sergunb 0:8918a71cdbe9 1121 //Increment sequence number
Sergunb 0:8918a71cdbe9 1122 tlsIncSequenceNumber(context->readSeqNum);
Sergunb 0:8918a71cdbe9 1123 }
Sergunb 0:8918a71cdbe9 1124
Sergunb 0:8918a71cdbe9 1125 //Successful decryption
Sergunb 0:8918a71cdbe9 1126 return NO_ERROR;
Sergunb 0:8918a71cdbe9 1127 }
Sergunb 0:8918a71cdbe9 1128
Sergunb 0:8918a71cdbe9 1129
Sergunb 0:8918a71cdbe9 1130 /**
Sergunb 0:8918a71cdbe9 1131 * @brief Increment sequence number
Sergunb 0:8918a71cdbe9 1132 * @param[in] seqNum Sequence number to increment
Sergunb 0:8918a71cdbe9 1133 **/
Sergunb 0:8918a71cdbe9 1134
Sergunb 0:8918a71cdbe9 1135 void tlsIncSequenceNumber(TlsSequenceNumber seqNum)
Sergunb 0:8918a71cdbe9 1136 {
Sergunb 0:8918a71cdbe9 1137 int_t i;
Sergunb 0:8918a71cdbe9 1138
Sergunb 0:8918a71cdbe9 1139 //Sequence numbers are stored MSB first
Sergunb 0:8918a71cdbe9 1140 for(i = 7; i >= 0; i--)
Sergunb 0:8918a71cdbe9 1141 {
Sergunb 0:8918a71cdbe9 1142 //Increment the current byte
Sergunb 0:8918a71cdbe9 1143 seqNum[i]++;
Sergunb 0:8918a71cdbe9 1144 //Propagate the carry if necessary
Sergunb 0:8918a71cdbe9 1145 if(seqNum[i] != 0)
Sergunb 0:8918a71cdbe9 1146 break;
Sergunb 0:8918a71cdbe9 1147 }
Sergunb 0:8918a71cdbe9 1148 }
Sergunb 0:8918a71cdbe9 1149
Sergunb 0:8918a71cdbe9 1150 #endif
Sergunb 0:8918a71cdbe9 1151