Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ssl_cookie.c Source File

ssl_cookie.c

00001 /*
00002  *  DTLS cookie callbacks implementation
00003  *
00004  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
00005  *  SPDX-License-Identifier: Apache-2.0
00006  *
00007  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
00008  *  not use this file except in compliance with the License.
00009  *  You may obtain a copy of the License at
00010  *
00011  *  http://www.apache.org/licenses/LICENSE-2.0
00012  *
00013  *  Unless required by applicable law or agreed to in writing, software
00014  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00015  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00016  *  See the License for the specific language governing permissions and
00017  *  limitations under the License.
00018  *
00019  *  This file is part of mbed TLS (https://tls.mbed.org)
00020  */
00021 /*
00022  * These session callbacks use a simple chained list
00023  * to store and retrieve the session information.
00024  */
00025 
00026 #if !defined(MBEDTLS_CONFIG_FILE)
00027 #include "mbedtls/config.h"
00028 #else
00029 #include MBEDTLS_CONFIG_FILE
00030 #endif
00031 
00032 #if defined(MBEDTLS_SSL_COOKIE_C)
00033 
00034 #if defined(MBEDTLS_PLATFORM_C)
00035 #include "mbedtls/platform.h"
00036 #else
00037 #define mbedtls_calloc    calloc
00038 #define mbedtls_free      free
00039 #endif
00040 
00041 #include "mbedtls/ssl_cookie.h"
00042 #include "mbedtls/ssl_internal.h"
00043 
00044 #include <string.h>
00045 
00046 /* Implementation that should never be optimized out by the compiler */
00047 static void mbedtls_zeroize( void *v, size_t n ) {
00048     volatile unsigned char *p = v; while( n-- ) *p++ = 0;
00049 }
00050 
00051 /*
00052  * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is
00053  * available. Try SHA-256 first, 512 wastes resources since we need to stay
00054  * with max 32 bytes of cookie for DTLS 1.0
00055  */
00056 #if defined(MBEDTLS_SHA256_C)
00057 #define COOKIE_MD           MBEDTLS_MD_SHA224
00058 #define COOKIE_MD_OUTLEN    32
00059 #define COOKIE_HMAC_LEN     28
00060 #elif defined(MBEDTLS_SHA512_C)
00061 #define COOKIE_MD           MBEDTLS_MD_SHA384
00062 #define COOKIE_MD_OUTLEN    48
00063 #define COOKIE_HMAC_LEN     28
00064 #elif defined(MBEDTLS_SHA1_C)
00065 #define COOKIE_MD           MBEDTLS_MD_SHA1
00066 #define COOKIE_MD_OUTLEN    20
00067 #define COOKIE_HMAC_LEN     20
00068 #else
00069 #error "DTLS hello verify needs SHA-1 or SHA-2"
00070 #endif
00071 
00072 /*
00073  * Cookies are formed of a 4-bytes timestamp (or serial number) and
00074  * an HMAC of timestemp and client ID.
00075  */
00076 #define COOKIE_LEN      ( 4 + COOKIE_HMAC_LEN )
00077 
00078 void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx )
00079 {
00080     mbedtls_md_init( &ctx->hmac_ctx  );
00081 #if !defined(MBEDTLS_HAVE_TIME)
00082     ctx->serial  = 0;
00083 #endif
00084     ctx->timeout  = MBEDTLS_SSL_COOKIE_TIMEOUT;
00085 
00086 #if defined(MBEDTLS_THREADING_C)
00087     mbedtls_mutex_init( &ctx->mutex );
00088 #endif
00089 }
00090 
00091 void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay )
00092 {
00093     ctx->timeout  = delay;
00094 }
00095 
00096 void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx )
00097 {
00098     mbedtls_md_free( &ctx->hmac_ctx  );
00099 
00100 #if defined(MBEDTLS_THREADING_C)
00101     mbedtls_mutex_free( &ctx->mutex );
00102 #endif
00103 
00104     mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) );
00105 }
00106 
00107 int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx,
00108                       int (*f_rng)(void *, unsigned char *, size_t),
00109                       void *p_rng )
00110 {
00111     int ret;
00112     unsigned char key[COOKIE_MD_OUTLEN];
00113 
00114     if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 )
00115         return( ret );
00116 
00117     ret = mbedtls_md_setup( &ctx->hmac_ctx , mbedtls_md_info_from_type( COOKIE_MD ), 1 );
00118     if( ret != 0 )
00119         return( ret );
00120 
00121     ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx , key, sizeof( key ) );
00122     if( ret != 0 )
00123         return( ret );
00124 
00125     mbedtls_zeroize( key, sizeof( key ) );
00126 
00127     return( 0 );
00128 }
00129 
00130 /*
00131  * Generate the HMAC part of a cookie
00132  */
00133 static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx,
00134                             const unsigned char time[4],
00135                             unsigned char **p, unsigned char *end,
00136                             const unsigned char *cli_id, size_t cli_id_len )
00137 {
00138     unsigned char hmac_out[COOKIE_MD_OUTLEN];
00139 
00140     if( (size_t)( end - *p ) < COOKIE_HMAC_LEN )
00141         return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
00142 
00143     if( mbedtls_md_hmac_reset(  hmac_ctx ) != 0 ||
00144         mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 ||
00145         mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 ||
00146         mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 )
00147     {
00148         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
00149     }
00150 
00151     memcpy( *p, hmac_out, COOKIE_HMAC_LEN );
00152     *p += COOKIE_HMAC_LEN;
00153 
00154     return( 0 );
00155 }
00156 
00157 /*
00158  * Generate cookie for DTLS ClientHello verification
00159  */
00160 int mbedtls_ssl_cookie_write( void *p_ctx,
00161                       unsigned char **p, unsigned char *end,
00162                       const unsigned char *cli_id, size_t cli_id_len )
00163 {
00164     int ret;
00165     mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;
00166     unsigned long t;
00167 
00168     if( ctx == NULL || cli_id == NULL )
00169         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
00170 
00171     if( (size_t)( end - *p ) < COOKIE_LEN )
00172         return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
00173 
00174 #if defined(MBEDTLS_HAVE_TIME)
00175     t = (unsigned long) mbedtls_time( NULL );
00176 #else
00177     t = ctx->serial ++;
00178 #endif
00179 
00180     (*p)[0] = (unsigned char)( t >> 24 );
00181     (*p)[1] = (unsigned char)( t >> 16 );
00182     (*p)[2] = (unsigned char)( t >>  8 );
00183     (*p)[3] = (unsigned char)( t       );
00184     *p += 4;
00185 
00186 #if defined(MBEDTLS_THREADING_C)
00187     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
00188         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret );
00189 #endif
00190 
00191     ret = ssl_cookie_hmac( &ctx->hmac_ctx , *p - 4,
00192                            p, end, cli_id, cli_id_len );
00193 
00194 #if defined(MBEDTLS_THREADING_C)
00195     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
00196         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR +
00197                 MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00198 #endif
00199 
00200     return( ret );
00201 }
00202 
00203 /*
00204  * Check a cookie
00205  */
00206 int mbedtls_ssl_cookie_check( void *p_ctx,
00207                       const unsigned char *cookie, size_t cookie_len,
00208                       const unsigned char *cli_id, size_t cli_id_len )
00209 {
00210     unsigned char ref_hmac[COOKIE_HMAC_LEN];
00211     int ret = 0;
00212     unsigned char *p = ref_hmac;
00213     mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;
00214     unsigned long cur_time, cookie_time;
00215 
00216     if( ctx == NULL || cli_id == NULL )
00217         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
00218 
00219     if( cookie_len != COOKIE_LEN )
00220         return( -1 );
00221 
00222 #if defined(MBEDTLS_THREADING_C)
00223     if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
00224         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret );
00225 #endif
00226 
00227     if( ssl_cookie_hmac( &ctx->hmac_ctx , cookie,
00228                          &p, p + sizeof( ref_hmac ),
00229                          cli_id, cli_id_len ) != 0 )
00230         ret = -1;
00231 
00232 #if defined(MBEDTLS_THREADING_C)
00233     if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
00234         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR +
00235                 MBEDTLS_ERR_THREADING_MUTEX_ERROR );
00236 #endif
00237 
00238     if( ret != 0 )
00239         return( ret );
00240 
00241     if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 )
00242         return( -1 );
00243 
00244 #if defined(MBEDTLS_HAVE_TIME)
00245     cur_time = (unsigned long) mbedtls_time( NULL );
00246 #else
00247     cur_time = ctx->serial ;
00248 #endif
00249 
00250     cookie_time = ( (unsigned long) cookie[0] << 24 ) |
00251                   ( (unsigned long) cookie[1] << 16 ) |
00252                   ( (unsigned long) cookie[2] <<  8 ) |
00253                   ( (unsigned long) cookie[3]       );
00254 
00255     if( ctx->timeout  != 0 && cur_time - cookie_time > ctx->timeout  )
00256         return( -1 );
00257 
00258     return( 0 );
00259 }
00260 #endif /* MBEDTLS_SSL_COOKIE_C */