945b23c46f
We used to include platform.h only when MBEDTLS_PLATFORM_C was enabled, and to define ad hoc replacements for mbedtls_xxx functions on a case-by-case basis when MBEDTLS_PLATFORM_C was disabled. The only reason for this complication was to allow building individual source modules without copying platform.h. This is not something we support or recommend anymore, so get rid of the complication: include platform.h unconditionally. There should be no change in behavior since just including the header should not change the behavior of a program. This commit replaces most occurrences of conditional inclusion of platform.h, using the following code: ``` perl -i -0777 -pe 's!#if.*\n#include "mbedtls/platform.h"\n(#else.*\n(#define (mbedtls|MBEDTLS)_.*\n|#include <(stdarg|stddef|stdio|stdlib|string|time)\.h>\n)*)?#endif.*!#include "mbedtls/platform.h"!mg' $(git grep -l '#include "mbedtls/platform.h"') ``` Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
387 lines
11 KiB
C
387 lines
11 KiB
C
/*
|
|
* DTLS cookie callbacks implementation
|
|
*
|
|
* Copyright The Mbed TLS Contributors
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
* not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
/*
|
|
* These session callbacks use a simple chained list
|
|
* to store and retrieve the session information.
|
|
*/
|
|
|
|
#include "common.h"
|
|
|
|
#if defined(MBEDTLS_SSL_COOKIE_C)
|
|
|
|
#include "mbedtls/platform.h"
|
|
|
|
#include "mbedtls/ssl_cookie.h"
|
|
#include "ssl_misc.h"
|
|
#include "mbedtls/error.h"
|
|
#include "mbedtls/platform_util.h"
|
|
#include "mbedtls/constant_time.h"
|
|
|
|
#include "legacy_or_psa.h"
|
|
|
|
#include <string.h>
|
|
|
|
/*
|
|
* If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is
|
|
* available. Try SHA-256 first, 512 wastes resources
|
|
*/
|
|
#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
|
|
#define COOKIE_MD MBEDTLS_MD_SHA224
|
|
#define COOKIE_MD_OUTLEN 32
|
|
#define COOKIE_HMAC_LEN 28
|
|
#elif defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
|
|
#define COOKIE_MD MBEDTLS_MD_SHA384
|
|
#define COOKIE_MD_OUTLEN 48
|
|
#define COOKIE_HMAC_LEN 28
|
|
#elif defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
|
|
#define COOKIE_MD MBEDTLS_MD_SHA1
|
|
#define COOKIE_MD_OUTLEN 20
|
|
#define COOKIE_HMAC_LEN 20
|
|
#else
|
|
#error "DTLS hello verify needs SHA-1 or SHA-2"
|
|
#endif
|
|
|
|
/*
|
|
* Cookies are formed of a 4-bytes timestamp (or serial number) and
|
|
* an HMAC of timestamp and client ID.
|
|
*/
|
|
#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN )
|
|
|
|
void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx )
|
|
{
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
ctx->psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT;
|
|
#else
|
|
mbedtls_md_init( &ctx->hmac_ctx );
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
|
#if !defined(MBEDTLS_HAVE_TIME)
|
|
ctx->serial = 0;
|
|
#endif
|
|
ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT;
|
|
|
|
#if !defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
#if defined(MBEDTLS_THREADING_C)
|
|
mbedtls_mutex_init( &ctx->mutex );
|
|
#endif
|
|
#endif /* !MBEDTLS_USE_PSA_CRYPTO */
|
|
}
|
|
|
|
void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay )
|
|
{
|
|
ctx->timeout = delay;
|
|
}
|
|
|
|
void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx )
|
|
{
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
psa_destroy_key( ctx->psa_hmac_key );
|
|
#else
|
|
mbedtls_md_free( &ctx->hmac_ctx );
|
|
|
|
#if defined(MBEDTLS_THREADING_C)
|
|
mbedtls_mutex_free( &ctx->mutex );
|
|
#endif
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
|
|
|
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) );
|
|
}
|
|
|
|
int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx,
|
|
int (*f_rng)(void *, unsigned char *, size_t),
|
|
void *p_rng )
|
|
{
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
|
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
|
psa_algorithm_t alg;
|
|
|
|
(void)f_rng;
|
|
(void)p_rng;
|
|
|
|
alg = mbedtls_hash_info_psa_from_md( COOKIE_MD );
|
|
if( alg == 0 )
|
|
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
|
|
|
ctx->psa_hmac_alg = PSA_ALG_TRUNCATED_MAC( PSA_ALG_HMAC( alg ),
|
|
COOKIE_HMAC_LEN );
|
|
|
|
psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_MESSAGE |
|
|
PSA_KEY_USAGE_SIGN_MESSAGE );
|
|
psa_set_key_algorithm( &attributes, ctx->psa_hmac_alg );
|
|
psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC );
|
|
psa_set_key_bits( &attributes, PSA_BYTES_TO_BITS( COOKIE_MD_OUTLEN ) );
|
|
|
|
if( ( status = psa_generate_key( &attributes,
|
|
&ctx->psa_hmac_key ) ) != PSA_SUCCESS )
|
|
{
|
|
return psa_ssl_status_to_mbedtls( status );
|
|
}
|
|
#else
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
|
unsigned char key[COOKIE_MD_OUTLEN];
|
|
|
|
if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 )
|
|
return( ret );
|
|
|
|
ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 );
|
|
if( ret != 0 )
|
|
return( ret );
|
|
|
|
ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) );
|
|
if( ret != 0 )
|
|
return( ret );
|
|
|
|
mbedtls_platform_zeroize( key, sizeof( key ) );
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
|
|
|
return( 0 );
|
|
}
|
|
|
|
#if !defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
/*
|
|
* Generate the HMAC part of a cookie
|
|
*/
|
|
MBEDTLS_CHECK_RETURN_CRITICAL
|
|
static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx,
|
|
const unsigned char time[4],
|
|
unsigned char **p, unsigned char *end,
|
|
const unsigned char *cli_id, size_t cli_id_len )
|
|
{
|
|
unsigned char hmac_out[COOKIE_MD_OUTLEN];
|
|
|
|
MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_HMAC_LEN );
|
|
|
|
if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 ||
|
|
mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 ||
|
|
mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 ||
|
|
mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 )
|
|
{
|
|
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
|
}
|
|
|
|
memcpy( *p, hmac_out, COOKIE_HMAC_LEN );
|
|
*p += COOKIE_HMAC_LEN;
|
|
|
|
return( 0 );
|
|
}
|
|
#endif /* !MBEDTLS_USE_PSA_CRYPTO */
|
|
|
|
/*
|
|
* Generate cookie for DTLS ClientHello verification
|
|
*/
|
|
int mbedtls_ssl_cookie_write( void *p_ctx,
|
|
unsigned char **p, unsigned char *end,
|
|
const unsigned char *cli_id, size_t cli_id_len )
|
|
{
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
|
|
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
|
size_t sign_mac_length = 0;
|
|
#endif
|
|
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
|
mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;
|
|
unsigned long t;
|
|
|
|
if( ctx == NULL || cli_id == NULL )
|
|
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
|
|
|
MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_LEN );
|
|
|
|
#if defined(MBEDTLS_HAVE_TIME)
|
|
t = (unsigned long) mbedtls_time( NULL );
|
|
#else
|
|
t = ctx->serial++;
|
|
#endif
|
|
|
|
MBEDTLS_PUT_UINT32_BE(t, *p, 0);
|
|
*p += 4;
|
|
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
status = psa_mac_sign_setup( &operation, ctx->psa_hmac_key,
|
|
ctx->psa_hmac_alg );
|
|
if( status != PSA_SUCCESS )
|
|
{
|
|
ret = psa_ssl_status_to_mbedtls( status );
|
|
goto exit;
|
|
}
|
|
|
|
status = psa_mac_update( &operation, *p - 4, 4 );
|
|
if( status != PSA_SUCCESS )
|
|
{
|
|
ret = psa_ssl_status_to_mbedtls( status );
|
|
goto exit;
|
|
}
|
|
|
|
status = psa_mac_update( &operation, cli_id, cli_id_len );
|
|
if( status != PSA_SUCCESS )
|
|
{
|
|
ret = psa_ssl_status_to_mbedtls( status );
|
|
goto exit;
|
|
}
|
|
|
|
status = psa_mac_sign_finish( &operation, *p, COOKIE_MD_OUTLEN,
|
|
&sign_mac_length );
|
|
if( status != PSA_SUCCESS )
|
|
{
|
|
ret = psa_ssl_status_to_mbedtls( status );
|
|
goto exit;
|
|
}
|
|
|
|
*p += COOKIE_HMAC_LEN;
|
|
|
|
ret = 0;
|
|
#else
|
|
#if defined(MBEDTLS_THREADING_C)
|
|
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
|
|
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) );
|
|
#endif
|
|
|
|
ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4,
|
|
p, end, cli_id, cli_id_len );
|
|
|
|
#if defined(MBEDTLS_THREADING_C)
|
|
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
|
|
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR,
|
|
MBEDTLS_ERR_THREADING_MUTEX_ERROR ) );
|
|
#endif
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
|
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
exit:
|
|
status = psa_mac_abort( &operation );
|
|
if( status != PSA_SUCCESS )
|
|
ret = psa_ssl_status_to_mbedtls( status );
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
|
return( ret );
|
|
}
|
|
|
|
/*
|
|
* Check a cookie
|
|
*/
|
|
int mbedtls_ssl_cookie_check( void *p_ctx,
|
|
const unsigned char *cookie, size_t cookie_len,
|
|
const unsigned char *cli_id, size_t cli_id_len )
|
|
{
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
|
|
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
|
#else
|
|
unsigned char ref_hmac[COOKIE_HMAC_LEN];
|
|
unsigned char *p = ref_hmac;
|
|
#endif
|
|
int ret = 0;
|
|
mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;
|
|
unsigned long cur_time, cookie_time;
|
|
|
|
if( ctx == NULL || cli_id == NULL )
|
|
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
|
|
|
if( cookie_len != COOKIE_LEN )
|
|
return( -1 );
|
|
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
status = psa_mac_verify_setup( &operation, ctx->psa_hmac_key,
|
|
ctx->psa_hmac_alg );
|
|
if( status != PSA_SUCCESS )
|
|
{
|
|
ret = psa_ssl_status_to_mbedtls( status );
|
|
goto exit;
|
|
}
|
|
|
|
status = psa_mac_update( &operation, cookie, 4 );
|
|
if( status != PSA_SUCCESS )
|
|
{
|
|
ret = psa_ssl_status_to_mbedtls( status );
|
|
goto exit;
|
|
}
|
|
|
|
status = psa_mac_update( &operation, cli_id,
|
|
cli_id_len );
|
|
if( status != PSA_SUCCESS )
|
|
{
|
|
ret = psa_ssl_status_to_mbedtls( status );
|
|
goto exit;
|
|
}
|
|
|
|
status = psa_mac_verify_finish( &operation, cookie + 4,
|
|
COOKIE_HMAC_LEN );
|
|
if( status != PSA_SUCCESS )
|
|
{
|
|
ret = psa_ssl_status_to_mbedtls( status );
|
|
goto exit;
|
|
}
|
|
|
|
ret = 0;
|
|
#else
|
|
#if defined(MBEDTLS_THREADING_C)
|
|
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
|
|
return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) );
|
|
#endif
|
|
|
|
if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie,
|
|
&p, p + sizeof( ref_hmac ),
|
|
cli_id, cli_id_len ) != 0 )
|
|
ret = -1;
|
|
|
|
#if defined(MBEDTLS_THREADING_C)
|
|
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
|
|
{
|
|
ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR,
|
|
MBEDTLS_ERR_THREADING_MUTEX_ERROR );
|
|
}
|
|
#endif
|
|
|
|
if( ret != 0 )
|
|
goto exit;
|
|
|
|
if( mbedtls_ct_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 )
|
|
{
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
|
|
|
#if defined(MBEDTLS_HAVE_TIME)
|
|
cur_time = (unsigned long) mbedtls_time( NULL );
|
|
#else
|
|
cur_time = ctx->serial;
|
|
#endif
|
|
|
|
cookie_time = ( (unsigned long) cookie[0] << 24 ) |
|
|
( (unsigned long) cookie[1] << 16 ) |
|
|
( (unsigned long) cookie[2] << 8 ) |
|
|
( (unsigned long) cookie[3] );
|
|
|
|
if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout )
|
|
{
|
|
ret = -1;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
#if defined(MBEDTLS_USE_PSA_CRYPTO)
|
|
status = psa_mac_abort( &operation );
|
|
if( status != PSA_SUCCESS )
|
|
ret = psa_ssl_status_to_mbedtls( status );
|
|
#else
|
|
mbedtls_platform_zeroize( ref_hmac, sizeof( ref_hmac ) );
|
|
#endif /* MBEDTLS_USE_PSA_CRYPTO */
|
|
return( ret );
|
|
}
|
|
#endif /* MBEDTLS_SSL_COOKIE_C */
|