Gaurav Aggarwal a9f64006ea Add support for const error description strings
Problem
-------
mbedtls_strerror is a utility function which converts an mbedTLS error code
into a human readable string. It requires the caller to allocate a buffer every
time an error code needs to be converted to a string. It is an overkill and a
waste of RAM for resource constrained microcontrollers - where the most common
use case is to use these strings for logging.

Solution
--------
The proposed commit adds two functions:

* const char * mbedtls_high_level_strerr( int error_code );
* const char * mbedtls_low_level_strerr( int error_code );

The above two functions convert the high level and low level parts of an mbedTLS
error code to human readable strings. They return a const pointer to an
unmodifiable string which is not supposed to be modified by the caller and only
to be used for logging purposes. The caller no longer needs to allocate a
buffer.

Backward Compatibility
----------------------
The proposed change is completely backward compatible as it does not change
the existing mbedtls_strerror function and ensures that it continues to behave
the same way.

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
2020-04-09 01:44:52 -07:00

180 lines
4.2 KiB
Plaintext

/*
* Error message information
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* 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.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
#include <string.h>
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#define mbedtls_snprintf snprintf
#define mbedtls_time_t time_t
#endif
#if defined(MBEDTLS_ERROR_C)
#include <stdio.h>
HEADER_INCLUDED
typedef struct mbedtls_error
{
int code; /* Error code. */
const char * description; /* Error description. */
} mbedtls_error_t;
static mbedtls_error_t high_level_errors[] =
{
HIGH_LEVEL_CODE_CHECKS
};
#define NUM_HIGH_LEVEL_ERRORS ( sizeof(high_level_errors)/sizeof(mbedtls_error_t) )
static mbedtls_error_t low_level_errors[] =
{
LOW_LEVEL_CODE_CHECKS
};
#define NUM_LOW_LEVEL_ERRORS ( sizeof(low_level_errors)/sizeof(mbedtls_error_t) )
const char * mbedtls_high_level_strerr( int error_code )
{
size_t i;
const char *error_description = NULL;
for(i = 0; i < NUM_HIGH_LEVEL_ERRORS; i++ )
{
if( high_level_errors[i].code == error_code )
{
error_description = high_level_errors[i].description;
break;
}
}
return error_description;
}
const char * mbedtls_low_level_strerr( int error_code )
{
size_t i;
const char *error_description = NULL;
for(i = 0; i < NUM_LOW_LEVEL_ERRORS; i++ )
{
if( low_level_errors[i].code == error_code )
{
error_description = low_level_errors[i].description;
break;
}
}
return error_description;
}
void mbedtls_strerror( int ret, char *buf, size_t buflen )
{
size_t len;
int use_ret;
const char * high_level_error_description = NULL;
const char * low_level_error_description = NULL;
if( buflen == 0 )
return;
memset( buf, 0x00, buflen );
if( ret < 0 )
ret = -ret;
if( ret & 0xFF80 )
{
use_ret = ret & 0xFF80;
// Translate high level error code.
high_level_error_description = mbedtls_high_level_strerr(use_ret);
if( high_level_error_description == NULL )
mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
else
mbedtls_snprintf( buf, buflen, "%s", high_level_error_description );
// Early return in case of a fatal error - do not try to translate low
// level code.
if(use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE))
return;
}
use_ret = ret & ~0xFF80;
if( use_ret == 0 )
return;
// If high level code is present, make a concatenation between both
// error strings.
//
len = strlen( buf );
if( len > 0 )
{
if( buflen - len < 5 )
return;
mbedtls_snprintf( buf + len, buflen - len, " : " );
buf += len + 3;
buflen -= len + 3;
}
// Translate low level error code.
low_level_error_description = mbedtls_low_level_strerr( use_ret );
if( low_level_error_description == NULL )
mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
else
mbedtls_snprintf( buf, buflen, "%s", low_level_error_description );
}
#else /* MBEDTLS_ERROR_C */
#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
/*
* Provide an non-function in case MBEDTLS_ERROR_C is not defined
*/
void mbedtls_strerror( int ret, char *buf, size_t buflen )
{
((void) ret);
if( buflen > 0 )
buf[0] = '\0';
}
#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */
#endif /* MBEDTLS_ERROR_C */