mbed client lightswitch demo

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Fork of mbed-client-classic-example-lwip by Austin Blackstone

Committer:
mbedAustin
Date:
Thu Jun 09 17:08:36 2016 +0000
Revision:
11:cada08fc8a70
Commit for public Consumption

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbedAustin 11:cada08fc8a70 1 /*
mbedAustin 11:cada08fc8a70 2 * TLS server tickets callbacks implementation
mbedAustin 11:cada08fc8a70 3 *
mbedAustin 11:cada08fc8a70 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
mbedAustin 11:cada08fc8a70 5 * SPDX-License-Identifier: Apache-2.0
mbedAustin 11:cada08fc8a70 6 *
mbedAustin 11:cada08fc8a70 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
mbedAustin 11:cada08fc8a70 8 * not use this file except in compliance with the License.
mbedAustin 11:cada08fc8a70 9 * You may obtain a copy of the License at
mbedAustin 11:cada08fc8a70 10 *
mbedAustin 11:cada08fc8a70 11 * http://www.apache.org/licenses/LICENSE-2.0
mbedAustin 11:cada08fc8a70 12 *
mbedAustin 11:cada08fc8a70 13 * Unless required by applicable law or agreed to in writing, software
mbedAustin 11:cada08fc8a70 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
mbedAustin 11:cada08fc8a70 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbedAustin 11:cada08fc8a70 16 * See the License for the specific language governing permissions and
mbedAustin 11:cada08fc8a70 17 * limitations under the License.
mbedAustin 11:cada08fc8a70 18 *
mbedAustin 11:cada08fc8a70 19 * This file is part of mbed TLS (https://tls.mbed.org)
mbedAustin 11:cada08fc8a70 20 */
mbedAustin 11:cada08fc8a70 21
mbedAustin 11:cada08fc8a70 22 #if !defined(MBEDTLS_CONFIG_FILE)
mbedAustin 11:cada08fc8a70 23 #include "mbedtls/config.h"
mbedAustin 11:cada08fc8a70 24 #else
mbedAustin 11:cada08fc8a70 25 #include MBEDTLS_CONFIG_FILE
mbedAustin 11:cada08fc8a70 26 #endif
mbedAustin 11:cada08fc8a70 27
mbedAustin 11:cada08fc8a70 28 #if defined(MBEDTLS_SSL_TICKET_C)
mbedAustin 11:cada08fc8a70 29
mbedAustin 11:cada08fc8a70 30 #include "mbedtls/ssl_ticket.h"
mbedAustin 11:cada08fc8a70 31
mbedAustin 11:cada08fc8a70 32 #if defined(MBEDTLS_PLATFORM_C)
mbedAustin 11:cada08fc8a70 33 #include "mbedtls/platform.h"
mbedAustin 11:cada08fc8a70 34 #else
mbedAustin 11:cada08fc8a70 35 #include <stdlib.h>
mbedAustin 11:cada08fc8a70 36 #define mbedtls_calloc calloc
mbedAustin 11:cada08fc8a70 37 #define mbedtls_free free
mbedAustin 11:cada08fc8a70 38 #endif
mbedAustin 11:cada08fc8a70 39
mbedAustin 11:cada08fc8a70 40 #include <string.h>
mbedAustin 11:cada08fc8a70 41
mbedAustin 11:cada08fc8a70 42 /* Implementation that should never be optimized out by the compiler */
mbedAustin 11:cada08fc8a70 43 static void mbedtls_zeroize( void *v, size_t n ) {
mbedAustin 11:cada08fc8a70 44 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
mbedAustin 11:cada08fc8a70 45 }
mbedAustin 11:cada08fc8a70 46
mbedAustin 11:cada08fc8a70 47 /*
mbedAustin 11:cada08fc8a70 48 * Initialze context
mbedAustin 11:cada08fc8a70 49 */
mbedAustin 11:cada08fc8a70 50 void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx )
mbedAustin 11:cada08fc8a70 51 {
mbedAustin 11:cada08fc8a70 52 memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) );
mbedAustin 11:cada08fc8a70 53
mbedAustin 11:cada08fc8a70 54 #if defined(MBEDTLS_THREADING_C)
mbedAustin 11:cada08fc8a70 55 mbedtls_mutex_init( &ctx->mutex );
mbedAustin 11:cada08fc8a70 56 #endif
mbedAustin 11:cada08fc8a70 57 }
mbedAustin 11:cada08fc8a70 58
mbedAustin 11:cada08fc8a70 59 #define MAX_KEY_BYTES 32 /* 256 bits */
mbedAustin 11:cada08fc8a70 60
mbedAustin 11:cada08fc8a70 61 /*
mbedAustin 11:cada08fc8a70 62 * Generate/update a key
mbedAustin 11:cada08fc8a70 63 */
mbedAustin 11:cada08fc8a70 64 static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
mbedAustin 11:cada08fc8a70 65 unsigned char index )
mbedAustin 11:cada08fc8a70 66 {
mbedAustin 11:cada08fc8a70 67 int ret;
mbedAustin 11:cada08fc8a70 68 unsigned char buf[MAX_KEY_BYTES];
mbedAustin 11:cada08fc8a70 69 mbedtls_ssl_ticket_key *key = ctx->keys + index;
mbedAustin 11:cada08fc8a70 70
mbedAustin 11:cada08fc8a70 71 #if defined(MBEDTLS_HAVE_TIME)
mbedAustin 11:cada08fc8a70 72 key->generation_time = (uint32_t) time( NULL );
mbedAustin 11:cada08fc8a70 73 #endif
mbedAustin 11:cada08fc8a70 74
mbedAustin 11:cada08fc8a70 75 if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 )
mbedAustin 11:cada08fc8a70 76 return( ret );
mbedAustin 11:cada08fc8a70 77
mbedAustin 11:cada08fc8a70 78 if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 )
mbedAustin 11:cada08fc8a70 79 return( ret );
mbedAustin 11:cada08fc8a70 80
mbedAustin 11:cada08fc8a70 81 /* With GCM and CCM, same context can encrypt & decrypt */
mbedAustin 11:cada08fc8a70 82 ret = mbedtls_cipher_setkey( &key->ctx, buf,
mbedAustin 11:cada08fc8a70 83 mbedtls_cipher_get_key_bitlen( &key->ctx ),
mbedAustin 11:cada08fc8a70 84 MBEDTLS_ENCRYPT );
mbedAustin 11:cada08fc8a70 85
mbedAustin 11:cada08fc8a70 86 mbedtls_zeroize( buf, sizeof( buf ) );
mbedAustin 11:cada08fc8a70 87
mbedAustin 11:cada08fc8a70 88 return( ret );
mbedAustin 11:cada08fc8a70 89 }
mbedAustin 11:cada08fc8a70 90
mbedAustin 11:cada08fc8a70 91 /*
mbedAustin 11:cada08fc8a70 92 * Rotate/generate keys if necessary
mbedAustin 11:cada08fc8a70 93 */
mbedAustin 11:cada08fc8a70 94 static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
mbedAustin 11:cada08fc8a70 95 {
mbedAustin 11:cada08fc8a70 96 #if !defined(MBEDTLS_HAVE_TIME)
mbedAustin 11:cada08fc8a70 97 ((void) ctx);
mbedAustin 11:cada08fc8a70 98 #else
mbedAustin 11:cada08fc8a70 99 if( ctx->ticket_lifetime != 0 )
mbedAustin 11:cada08fc8a70 100 {
mbedAustin 11:cada08fc8a70 101 uint32_t current_time = (uint32_t) time( NULL );
mbedAustin 11:cada08fc8a70 102 uint32_t key_time = ctx->keys[ctx->active].generation_time;
mbedAustin 11:cada08fc8a70 103
mbedAustin 11:cada08fc8a70 104 if( current_time > key_time &&
mbedAustin 11:cada08fc8a70 105 current_time - key_time < ctx->ticket_lifetime )
mbedAustin 11:cada08fc8a70 106 {
mbedAustin 11:cada08fc8a70 107 return( 0 );
mbedAustin 11:cada08fc8a70 108 }
mbedAustin 11:cada08fc8a70 109
mbedAustin 11:cada08fc8a70 110 ctx->active = 1 - ctx->active;
mbedAustin 11:cada08fc8a70 111
mbedAustin 11:cada08fc8a70 112 return( ssl_ticket_gen_key( ctx, ctx->active ) );
mbedAustin 11:cada08fc8a70 113 }
mbedAustin 11:cada08fc8a70 114 else
mbedAustin 11:cada08fc8a70 115 #endif /* MBEDTLS_HAVE_TIME */
mbedAustin 11:cada08fc8a70 116 return( 0 );
mbedAustin 11:cada08fc8a70 117 }
mbedAustin 11:cada08fc8a70 118
mbedAustin 11:cada08fc8a70 119 /*
mbedAustin 11:cada08fc8a70 120 * Setup context for actual use
mbedAustin 11:cada08fc8a70 121 */
mbedAustin 11:cada08fc8a70 122 int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx,
mbedAustin 11:cada08fc8a70 123 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
mbedAustin 11:cada08fc8a70 124 mbedtls_cipher_type_t cipher,
mbedAustin 11:cada08fc8a70 125 uint32_t lifetime )
mbedAustin 11:cada08fc8a70 126 {
mbedAustin 11:cada08fc8a70 127 int ret;
mbedAustin 11:cada08fc8a70 128 const mbedtls_cipher_info_t *cipher_info;
mbedAustin 11:cada08fc8a70 129
mbedAustin 11:cada08fc8a70 130 ctx->f_rng = f_rng;
mbedAustin 11:cada08fc8a70 131 ctx->p_rng = p_rng;
mbedAustin 11:cada08fc8a70 132
mbedAustin 11:cada08fc8a70 133 ctx->ticket_lifetime = lifetime;
mbedAustin 11:cada08fc8a70 134
mbedAustin 11:cada08fc8a70 135 cipher_info = mbedtls_cipher_info_from_type( cipher);
mbedAustin 11:cada08fc8a70 136 if( cipher_info == NULL )
mbedAustin 11:cada08fc8a70 137 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedAustin 11:cada08fc8a70 138
mbedAustin 11:cada08fc8a70 139 if( cipher_info->mode != MBEDTLS_MODE_GCM &&
mbedAustin 11:cada08fc8a70 140 cipher_info->mode != MBEDTLS_MODE_CCM )
mbedAustin 11:cada08fc8a70 141 {
mbedAustin 11:cada08fc8a70 142 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedAustin 11:cada08fc8a70 143 }
mbedAustin 11:cada08fc8a70 144
mbedAustin 11:cada08fc8a70 145 if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES )
mbedAustin 11:cada08fc8a70 146 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedAustin 11:cada08fc8a70 147
mbedAustin 11:cada08fc8a70 148 if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 ||
mbedAustin 11:cada08fc8a70 149 ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 )
mbedAustin 11:cada08fc8a70 150 {
mbedAustin 11:cada08fc8a70 151 return( ret );
mbedAustin 11:cada08fc8a70 152 }
mbedAustin 11:cada08fc8a70 153
mbedAustin 11:cada08fc8a70 154 if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 ||
mbedAustin 11:cada08fc8a70 155 ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 )
mbedAustin 11:cada08fc8a70 156 {
mbedAustin 11:cada08fc8a70 157 return( ret );
mbedAustin 11:cada08fc8a70 158 }
mbedAustin 11:cada08fc8a70 159
mbedAustin 11:cada08fc8a70 160 return( 0 );
mbedAustin 11:cada08fc8a70 161 }
mbedAustin 11:cada08fc8a70 162
mbedAustin 11:cada08fc8a70 163 /*
mbedAustin 11:cada08fc8a70 164 * Serialize a session in the following format:
mbedAustin 11:cada08fc8a70 165 * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session)
mbedAustin 11:cada08fc8a70 166 * n . n+2 peer_cert length = m (0 if no certificate)
mbedAustin 11:cada08fc8a70 167 * n+3 . n+2+m peer cert ASN.1
mbedAustin 11:cada08fc8a70 168 */
mbedAustin 11:cada08fc8a70 169 static int ssl_save_session( const mbedtls_ssl_session *session,
mbedAustin 11:cada08fc8a70 170 unsigned char *buf, size_t buf_len,
mbedAustin 11:cada08fc8a70 171 size_t *olen )
mbedAustin 11:cada08fc8a70 172 {
mbedAustin 11:cada08fc8a70 173 unsigned char *p = buf;
mbedAustin 11:cada08fc8a70 174 size_t left = buf_len;
mbedAustin 11:cada08fc8a70 175 #if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedAustin 11:cada08fc8a70 176 size_t cert_len;
mbedAustin 11:cada08fc8a70 177 #endif /* MBEDTLS_X509_CRT_PARSE_C */
mbedAustin 11:cada08fc8a70 178
mbedAustin 11:cada08fc8a70 179 if( left < sizeof( mbedtls_ssl_session ) )
mbedAustin 11:cada08fc8a70 180 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
mbedAustin 11:cada08fc8a70 181
mbedAustin 11:cada08fc8a70 182 memcpy( p, session, sizeof( mbedtls_ssl_session ) );
mbedAustin 11:cada08fc8a70 183 p += sizeof( mbedtls_ssl_session );
mbedAustin 11:cada08fc8a70 184 left -= sizeof( mbedtls_ssl_session );
mbedAustin 11:cada08fc8a70 185
mbedAustin 11:cada08fc8a70 186 #if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedAustin 11:cada08fc8a70 187 if( session->peer_cert == NULL )
mbedAustin 11:cada08fc8a70 188 cert_len = 0;
mbedAustin 11:cada08fc8a70 189 else
mbedAustin 11:cada08fc8a70 190 cert_len = session->peer_cert->raw.len;
mbedAustin 11:cada08fc8a70 191
mbedAustin 11:cada08fc8a70 192 if( left < 3 + cert_len )
mbedAustin 11:cada08fc8a70 193 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
mbedAustin 11:cada08fc8a70 194
mbedAustin 11:cada08fc8a70 195 *p++ = (unsigned char)( cert_len >> 16 & 0xFF );
mbedAustin 11:cada08fc8a70 196 *p++ = (unsigned char)( cert_len >> 8 & 0xFF );
mbedAustin 11:cada08fc8a70 197 *p++ = (unsigned char)( cert_len & 0xFF );
mbedAustin 11:cada08fc8a70 198
mbedAustin 11:cada08fc8a70 199 if( session->peer_cert != NULL )
mbedAustin 11:cada08fc8a70 200 memcpy( p, session->peer_cert->raw.p, cert_len );
mbedAustin 11:cada08fc8a70 201
mbedAustin 11:cada08fc8a70 202 p += cert_len;
mbedAustin 11:cada08fc8a70 203 #endif /* MBEDTLS_X509_CRT_PARSE_C */
mbedAustin 11:cada08fc8a70 204
mbedAustin 11:cada08fc8a70 205 *olen = p - buf;
mbedAustin 11:cada08fc8a70 206
mbedAustin 11:cada08fc8a70 207 return( 0 );
mbedAustin 11:cada08fc8a70 208 }
mbedAustin 11:cada08fc8a70 209
mbedAustin 11:cada08fc8a70 210 /*
mbedAustin 11:cada08fc8a70 211 * Unserialise session, see ssl_save_session()
mbedAustin 11:cada08fc8a70 212 */
mbedAustin 11:cada08fc8a70 213 static int ssl_load_session( mbedtls_ssl_session *session,
mbedAustin 11:cada08fc8a70 214 const unsigned char *buf, size_t len )
mbedAustin 11:cada08fc8a70 215 {
mbedAustin 11:cada08fc8a70 216 const unsigned char *p = buf;
mbedAustin 11:cada08fc8a70 217 const unsigned char * const end = buf + len;
mbedAustin 11:cada08fc8a70 218 #if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedAustin 11:cada08fc8a70 219 size_t cert_len;
mbedAustin 11:cada08fc8a70 220 #endif /* MBEDTLS_X509_CRT_PARSE_C */
mbedAustin 11:cada08fc8a70 221
mbedAustin 11:cada08fc8a70 222 if( p + sizeof( mbedtls_ssl_session ) > end )
mbedAustin 11:cada08fc8a70 223 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedAustin 11:cada08fc8a70 224
mbedAustin 11:cada08fc8a70 225 memcpy( session, p, sizeof( mbedtls_ssl_session ) );
mbedAustin 11:cada08fc8a70 226 p += sizeof( mbedtls_ssl_session );
mbedAustin 11:cada08fc8a70 227
mbedAustin 11:cada08fc8a70 228 #if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedAustin 11:cada08fc8a70 229 if( p + 3 > end )
mbedAustin 11:cada08fc8a70 230 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedAustin 11:cada08fc8a70 231
mbedAustin 11:cada08fc8a70 232 cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2];
mbedAustin 11:cada08fc8a70 233 p += 3;
mbedAustin 11:cada08fc8a70 234
mbedAustin 11:cada08fc8a70 235 if( cert_len == 0 )
mbedAustin 11:cada08fc8a70 236 {
mbedAustin 11:cada08fc8a70 237 session->peer_cert = NULL;
mbedAustin 11:cada08fc8a70 238 }
mbedAustin 11:cada08fc8a70 239 else
mbedAustin 11:cada08fc8a70 240 {
mbedAustin 11:cada08fc8a70 241 int ret;
mbedAustin 11:cada08fc8a70 242
mbedAustin 11:cada08fc8a70 243 if( p + cert_len > end )
mbedAustin 11:cada08fc8a70 244 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedAustin 11:cada08fc8a70 245
mbedAustin 11:cada08fc8a70 246 session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
mbedAustin 11:cada08fc8a70 247
mbedAustin 11:cada08fc8a70 248 if( session->peer_cert == NULL )
mbedAustin 11:cada08fc8a70 249 return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
mbedAustin 11:cada08fc8a70 250
mbedAustin 11:cada08fc8a70 251 mbedtls_x509_crt_init( session->peer_cert );
mbedAustin 11:cada08fc8a70 252
mbedAustin 11:cada08fc8a70 253 if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert,
mbedAustin 11:cada08fc8a70 254 p, cert_len ) ) != 0 )
mbedAustin 11:cada08fc8a70 255 {
mbedAustin 11:cada08fc8a70 256 mbedtls_x509_crt_free( session->peer_cert );
mbedAustin 11:cada08fc8a70 257 mbedtls_free( session->peer_cert );
mbedAustin 11:cada08fc8a70 258 session->peer_cert = NULL;
mbedAustin 11:cada08fc8a70 259 return( ret );
mbedAustin 11:cada08fc8a70 260 }
mbedAustin 11:cada08fc8a70 261
mbedAustin 11:cada08fc8a70 262 p += cert_len;
mbedAustin 11:cada08fc8a70 263 }
mbedAustin 11:cada08fc8a70 264 #endif /* MBEDTLS_X509_CRT_PARSE_C */
mbedAustin 11:cada08fc8a70 265
mbedAustin 11:cada08fc8a70 266 if( p != end )
mbedAustin 11:cada08fc8a70 267 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedAustin 11:cada08fc8a70 268
mbedAustin 11:cada08fc8a70 269 return( 0 );
mbedAustin 11:cada08fc8a70 270 }
mbedAustin 11:cada08fc8a70 271
mbedAustin 11:cada08fc8a70 272 /*
mbedAustin 11:cada08fc8a70 273 * Create session ticket, with the following structure:
mbedAustin 11:cada08fc8a70 274 *
mbedAustin 11:cada08fc8a70 275 * struct {
mbedAustin 11:cada08fc8a70 276 * opaque key_name[4];
mbedAustin 11:cada08fc8a70 277 * opaque iv[12];
mbedAustin 11:cada08fc8a70 278 * opaque encrypted_state<0..2^16-1>;
mbedAustin 11:cada08fc8a70 279 * opaque tag[16];
mbedAustin 11:cada08fc8a70 280 * } ticket;
mbedAustin 11:cada08fc8a70 281 *
mbedAustin 11:cada08fc8a70 282 * The key_name, iv, and length of encrypted_state are the additional
mbedAustin 11:cada08fc8a70 283 * authenticated data.
mbedAustin 11:cada08fc8a70 284 */
mbedAustin 11:cada08fc8a70 285 int mbedtls_ssl_ticket_write( void *p_ticket,
mbedAustin 11:cada08fc8a70 286 const mbedtls_ssl_session *session,
mbedAustin 11:cada08fc8a70 287 unsigned char *start,
mbedAustin 11:cada08fc8a70 288 const unsigned char *end,
mbedAustin 11:cada08fc8a70 289 size_t *tlen,
mbedAustin 11:cada08fc8a70 290 uint32_t *ticket_lifetime )
mbedAustin 11:cada08fc8a70 291 {
mbedAustin 11:cada08fc8a70 292 int ret;
mbedAustin 11:cada08fc8a70 293 mbedtls_ssl_ticket_context *ctx = p_ticket;
mbedAustin 11:cada08fc8a70 294 mbedtls_ssl_ticket_key *key;
mbedAustin 11:cada08fc8a70 295 unsigned char *key_name = start;
mbedAustin 11:cada08fc8a70 296 unsigned char *iv = start + 4;
mbedAustin 11:cada08fc8a70 297 unsigned char *state_len_bytes = iv + 12;
mbedAustin 11:cada08fc8a70 298 unsigned char *state = state_len_bytes + 2;
mbedAustin 11:cada08fc8a70 299 unsigned char *tag;
mbedAustin 11:cada08fc8a70 300 size_t clear_len, ciph_len;
mbedAustin 11:cada08fc8a70 301
mbedAustin 11:cada08fc8a70 302 *tlen = 0;
mbedAustin 11:cada08fc8a70 303
mbedAustin 11:cada08fc8a70 304 if( ctx == NULL || ctx->f_rng == NULL )
mbedAustin 11:cada08fc8a70 305 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedAustin 11:cada08fc8a70 306
mbedAustin 11:cada08fc8a70 307 /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag,
mbedAustin 11:cada08fc8a70 308 * in addition to session itself, that will be checked when writing it. */
mbedAustin 11:cada08fc8a70 309 if( end - start < 4 + 12 + 2 + 16 )
mbedAustin 11:cada08fc8a70 310 return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
mbedAustin 11:cada08fc8a70 311
mbedAustin 11:cada08fc8a70 312 #if defined(MBEDTLS_THREADING_C)
mbedAustin 11:cada08fc8a70 313 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
mbedAustin 11:cada08fc8a70 314 return( ret );
mbedAustin 11:cada08fc8a70 315 #endif
mbedAustin 11:cada08fc8a70 316
mbedAustin 11:cada08fc8a70 317 if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 )
mbedAustin 11:cada08fc8a70 318 goto cleanup;
mbedAustin 11:cada08fc8a70 319
mbedAustin 11:cada08fc8a70 320 key = &ctx->keys[ctx->active];
mbedAustin 11:cada08fc8a70 321
mbedAustin 11:cada08fc8a70 322 *ticket_lifetime = ctx->ticket_lifetime;
mbedAustin 11:cada08fc8a70 323
mbedAustin 11:cada08fc8a70 324 memcpy( key_name, key->name, 4 );
mbedAustin 11:cada08fc8a70 325
mbedAustin 11:cada08fc8a70 326 if( ( ret = ctx->f_rng( ctx->p_rng, iv, 12 ) ) != 0 )
mbedAustin 11:cada08fc8a70 327 goto cleanup;
mbedAustin 11:cada08fc8a70 328
mbedAustin 11:cada08fc8a70 329 /* Dump session state */
mbedAustin 11:cada08fc8a70 330 if( ( ret = ssl_save_session( session,
mbedAustin 11:cada08fc8a70 331 state, end - state, &clear_len ) ) != 0 ||
mbedAustin 11:cada08fc8a70 332 (unsigned long) clear_len > 65535 )
mbedAustin 11:cada08fc8a70 333 {
mbedAustin 11:cada08fc8a70 334 goto cleanup;
mbedAustin 11:cada08fc8a70 335 }
mbedAustin 11:cada08fc8a70 336 state_len_bytes[0] = ( clear_len >> 8 ) & 0xff;
mbedAustin 11:cada08fc8a70 337 state_len_bytes[1] = ( clear_len ) & 0xff;
mbedAustin 11:cada08fc8a70 338
mbedAustin 11:cada08fc8a70 339 /* Encrypt and authenticate */
mbedAustin 11:cada08fc8a70 340 tag = state + clear_len;
mbedAustin 11:cada08fc8a70 341 if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx,
mbedAustin 11:cada08fc8a70 342 iv, 12, key_name, 4 + 12 + 2,
mbedAustin 11:cada08fc8a70 343 state, clear_len, state, &ciph_len, tag, 16 ) ) != 0 )
mbedAustin 11:cada08fc8a70 344 {
mbedAustin 11:cada08fc8a70 345 goto cleanup;
mbedAustin 11:cada08fc8a70 346 }
mbedAustin 11:cada08fc8a70 347 if( ciph_len != clear_len )
mbedAustin 11:cada08fc8a70 348 {
mbedAustin 11:cada08fc8a70 349 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
mbedAustin 11:cada08fc8a70 350 goto cleanup;
mbedAustin 11:cada08fc8a70 351 }
mbedAustin 11:cada08fc8a70 352
mbedAustin 11:cada08fc8a70 353 *tlen = 4 + 12 + 2 + 16 + ciph_len;
mbedAustin 11:cada08fc8a70 354
mbedAustin 11:cada08fc8a70 355 cleanup:
mbedAustin 11:cada08fc8a70 356 #if defined(MBEDTLS_THREADING_C)
mbedAustin 11:cada08fc8a70 357 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
mbedAustin 11:cada08fc8a70 358 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
mbedAustin 11:cada08fc8a70 359 #endif
mbedAustin 11:cada08fc8a70 360
mbedAustin 11:cada08fc8a70 361 return( ret );
mbedAustin 11:cada08fc8a70 362 }
mbedAustin 11:cada08fc8a70 363
mbedAustin 11:cada08fc8a70 364 /*
mbedAustin 11:cada08fc8a70 365 * Select key based on name
mbedAustin 11:cada08fc8a70 366 */
mbedAustin 11:cada08fc8a70 367 static mbedtls_ssl_ticket_key *ssl_ticket_select_key(
mbedAustin 11:cada08fc8a70 368 mbedtls_ssl_ticket_context *ctx,
mbedAustin 11:cada08fc8a70 369 const unsigned char name[4] )
mbedAustin 11:cada08fc8a70 370 {
mbedAustin 11:cada08fc8a70 371 unsigned char i;
mbedAustin 11:cada08fc8a70 372
mbedAustin 11:cada08fc8a70 373 for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ )
mbedAustin 11:cada08fc8a70 374 if( memcmp( name, ctx->keys[i].name, 4 ) == 0 )
mbedAustin 11:cada08fc8a70 375 return( &ctx->keys[i] );
mbedAustin 11:cada08fc8a70 376
mbedAustin 11:cada08fc8a70 377 return( NULL );
mbedAustin 11:cada08fc8a70 378 }
mbedAustin 11:cada08fc8a70 379
mbedAustin 11:cada08fc8a70 380 /*
mbedAustin 11:cada08fc8a70 381 * Load session ticket (see mbedtls_ssl_ticket_write for structure)
mbedAustin 11:cada08fc8a70 382 */
mbedAustin 11:cada08fc8a70 383 int mbedtls_ssl_ticket_parse( void *p_ticket,
mbedAustin 11:cada08fc8a70 384 mbedtls_ssl_session *session,
mbedAustin 11:cada08fc8a70 385 unsigned char *buf,
mbedAustin 11:cada08fc8a70 386 size_t len )
mbedAustin 11:cada08fc8a70 387 {
mbedAustin 11:cada08fc8a70 388 int ret;
mbedAustin 11:cada08fc8a70 389 mbedtls_ssl_ticket_context *ctx = p_ticket;
mbedAustin 11:cada08fc8a70 390 mbedtls_ssl_ticket_key *key;
mbedAustin 11:cada08fc8a70 391 unsigned char *key_name = buf;
mbedAustin 11:cada08fc8a70 392 unsigned char *iv = buf + 4;
mbedAustin 11:cada08fc8a70 393 unsigned char *enc_len_p = iv + 12;
mbedAustin 11:cada08fc8a70 394 unsigned char *ticket = enc_len_p + 2;
mbedAustin 11:cada08fc8a70 395 unsigned char *tag;
mbedAustin 11:cada08fc8a70 396 size_t enc_len, clear_len;
mbedAustin 11:cada08fc8a70 397
mbedAustin 11:cada08fc8a70 398 if( ctx == NULL || ctx->f_rng == NULL )
mbedAustin 11:cada08fc8a70 399 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedAustin 11:cada08fc8a70 400
mbedAustin 11:cada08fc8a70 401 /* See mbedtls_ssl_ticket_write() */
mbedAustin 11:cada08fc8a70 402 if( len < 4 + 12 + 2 + 16 )
mbedAustin 11:cada08fc8a70 403 return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
mbedAustin 11:cada08fc8a70 404
mbedAustin 11:cada08fc8a70 405 #if defined(MBEDTLS_THREADING_C)
mbedAustin 11:cada08fc8a70 406 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
mbedAustin 11:cada08fc8a70 407 return( ret );
mbedAustin 11:cada08fc8a70 408 #endif
mbedAustin 11:cada08fc8a70 409
mbedAustin 11:cada08fc8a70 410 if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 )
mbedAustin 11:cada08fc8a70 411 goto cleanup;
mbedAustin 11:cada08fc8a70 412
mbedAustin 11:cada08fc8a70 413 enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1];
mbedAustin 11:cada08fc8a70 414 tag = ticket + enc_len;
mbedAustin 11:cada08fc8a70 415
mbedAustin 11:cada08fc8a70 416 if( len != 4 + 12 + 2 + enc_len + 16 )
mbedAustin 11:cada08fc8a70 417 {
mbedAustin 11:cada08fc8a70 418 ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
mbedAustin 11:cada08fc8a70 419 goto cleanup;
mbedAustin 11:cada08fc8a70 420 }
mbedAustin 11:cada08fc8a70 421
mbedAustin 11:cada08fc8a70 422 /* Select key */
mbedAustin 11:cada08fc8a70 423 if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL )
mbedAustin 11:cada08fc8a70 424 {
mbedAustin 11:cada08fc8a70 425 /* We can't know for sure but this is a likely option unless we're
mbedAustin 11:cada08fc8a70 426 * under attack - this is only informative anyway */
mbedAustin 11:cada08fc8a70 427 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
mbedAustin 11:cada08fc8a70 428 goto cleanup;
mbedAustin 11:cada08fc8a70 429 }
mbedAustin 11:cada08fc8a70 430
mbedAustin 11:cada08fc8a70 431 /* Decrypt and authenticate */
mbedAustin 11:cada08fc8a70 432 if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, iv, 12,
mbedAustin 11:cada08fc8a70 433 key_name, 4 + 12 + 2, ticket, enc_len,
mbedAustin 11:cada08fc8a70 434 ticket, &clear_len, tag, 16 ) ) != 0 )
mbedAustin 11:cada08fc8a70 435 {
mbedAustin 11:cada08fc8a70 436 if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
mbedAustin 11:cada08fc8a70 437 ret = MBEDTLS_ERR_SSL_INVALID_MAC;
mbedAustin 11:cada08fc8a70 438
mbedAustin 11:cada08fc8a70 439 goto cleanup;
mbedAustin 11:cada08fc8a70 440 }
mbedAustin 11:cada08fc8a70 441 if( clear_len != enc_len )
mbedAustin 11:cada08fc8a70 442 {
mbedAustin 11:cada08fc8a70 443 ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
mbedAustin 11:cada08fc8a70 444 goto cleanup;
mbedAustin 11:cada08fc8a70 445 }
mbedAustin 11:cada08fc8a70 446
mbedAustin 11:cada08fc8a70 447 /* Actually load session */
mbedAustin 11:cada08fc8a70 448 if( ( ret = ssl_load_session( session, ticket, clear_len ) ) != 0 )
mbedAustin 11:cada08fc8a70 449 goto cleanup;
mbedAustin 11:cada08fc8a70 450
mbedAustin 11:cada08fc8a70 451 #if defined(MBEDTLS_HAVE_TIME)
mbedAustin 11:cada08fc8a70 452 {
mbedAustin 11:cada08fc8a70 453 /* Check for expiration */
mbedAustin 11:cada08fc8a70 454 time_t current_time = time( NULL );
mbedAustin 11:cada08fc8a70 455
mbedAustin 11:cada08fc8a70 456 if( current_time < session->start ||
mbedAustin 11:cada08fc8a70 457 (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime )
mbedAustin 11:cada08fc8a70 458 {
mbedAustin 11:cada08fc8a70 459 ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
mbedAustin 11:cada08fc8a70 460 goto cleanup;
mbedAustin 11:cada08fc8a70 461 }
mbedAustin 11:cada08fc8a70 462 }
mbedAustin 11:cada08fc8a70 463 #endif
mbedAustin 11:cada08fc8a70 464
mbedAustin 11:cada08fc8a70 465 cleanup:
mbedAustin 11:cada08fc8a70 466 #if defined(MBEDTLS_THREADING_C)
mbedAustin 11:cada08fc8a70 467 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
mbedAustin 11:cada08fc8a70 468 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
mbedAustin 11:cada08fc8a70 469 #endif
mbedAustin 11:cada08fc8a70 470
mbedAustin 11:cada08fc8a70 471 return( ret );
mbedAustin 11:cada08fc8a70 472 }
mbedAustin 11:cada08fc8a70 473
mbedAustin 11:cada08fc8a70 474 /*
mbedAustin 11:cada08fc8a70 475 * Free context
mbedAustin 11:cada08fc8a70 476 */
mbedAustin 11:cada08fc8a70 477 void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx )
mbedAustin 11:cada08fc8a70 478 {
mbedAustin 11:cada08fc8a70 479 mbedtls_cipher_free( &ctx->keys[0].ctx );
mbedAustin 11:cada08fc8a70 480 mbedtls_cipher_free( &ctx->keys[1].ctx );
mbedAustin 11:cada08fc8a70 481
mbedAustin 11:cada08fc8a70 482 #if defined(MBEDTLS_THREADING_C)
mbedAustin 11:cada08fc8a70 483 mbedtls_mutex_free( &ctx->mutex );
mbedAustin 11:cada08fc8a70 484 #endif
mbedAustin 11:cada08fc8a70 485
mbedAustin 11:cada08fc8a70 486 mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) );
mbedAustin 11:cada08fc8a70 487 }
mbedAustin 11:cada08fc8a70 488
mbedAustin 11:cada08fc8a70 489 #endif /* MBEDTLS_SSL_TICKET_C */