Skip to content

Commit

Permalink
Merge 7dbbaea into 22806ed
Browse files Browse the repository at this point in the history
  • Loading branch information
tve committed May 30, 2020
2 parents 22806ed + 7dbbaea commit ec73868
Show file tree
Hide file tree
Showing 23 changed files with 2,434 additions and 12 deletions.
44 changes: 44 additions & 0 deletions extmod/mbedtls_errors/README.md
@@ -0,0 +1,44 @@
MBEDTLS Error Strings for MicroPython
=====================================

This directory contains source code and tools to rework the Mbedtls error strings for
micropython to use less space. In short, instead of storing and printing something like
"SSL - Our own certificate(s) is/are too large to send in an SSL message" it prints
the name of the error #define, which would be `MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE` in
this case, and only stores `SSL_CERTIFICATE_TOO_LARGE` in flash. The exact Mbedtls error
defines are used because they're easy to search for to find more detailed information.

Mbedtls defines a specific format for error values and
includes a Perl script to gather all `MBEDTLS_ERR` defines from includes files together with
english error text. From that the Perl script generates `mbedtls_strerror()`. The files in this
directory modify this process to produce a more space efficient error lookup table with
shorter error strings. The files are as follows:
- `generate_errors_orig.pl` - original mbedtls perl script, copied here for reference
- `error_orig.fmt` - original mbedtls code template input to perl script
- `generate_errors.pl` - modified perl script for MicroPython
- `error.fmt` - modified code template for MicroPython
- `esp32_mbedtls_errors.c` - source file with `mbedtls_strerror` for Esp32, this is built
using the include files in ESP-IDF's version of mbedtls
- `do-esp32.sh` - shell script to produce `esp32_mbedtls_errors.c` -- note that as of v4.0
and v3.3.2 ESP-IDF uses the same version of mbedtls
- `mp_mbedtls_errors.c` - source file with `mbedtls_strerror` for ports using MicroPython's
version of mbedtls, this is built using the include files in `$MPY/lib/mbedtls`
- `do-mp.sh` - shell script to produce `mp_mbedtls_errors.c`
- `tester.c` - simple C main to test `mp_mbedtls_errors.c` locally on a dev box
- `do-test.sh` - shell script to produce `mp_mbedtls_errors.c` and compile the `tester` app

### How-to

- To build MicroPython all that is needed is to include the `xx_mbedtls_errors.c` into the build
(the Makefiles do this automatically). Note that Perl is not needed for routine MicroPython
builds.
- When a new version of Mbedtls is pulled-in the appropriate `do_` script(s) should be run and
a diff using the `_orig` files can show whether Mbedtls changed something in the error
formatting.
- The `tester` app doesn't need to be run unless changes to the string handling in `error.fmt`
are made: it really just tests that there is not an off-by-one error in the string
copying/appending, etc.
- To include/exclude `mbedtls_strerror` error strings in a specific MicroPython build use the
`??` macro. Excluding causes `mbedtls_strerror` to produce a string with the raw error code.
On the esp32, define/undefine `MBEDTLS_ERROR_C` in the ESP-IDF
`components/mbedtls/port/include/mbedtls/esp_config.h`.
5 changes: 5 additions & 0 deletions extmod/mbedtls_errors/do-esp32.sh
@@ -0,0 +1,5 @@
#! /bin/bash -e
# Generate esp32_mbedtls_errors.c for use in the Esp32 port, with the ESP-IDF version of mbedtls
# The ESPIDF env var must be set to the top-level dir of ESPIDF
echo "ESPIDF=$ESPIDF"
./generate_errors.pl $ESPIDF/components/mbedtls/mbedtls/include/mbedtls . esp32_mbedtls_errors.c
3 changes: 3 additions & 0 deletions extmod/mbedtls_errors/do-mp.sh
@@ -0,0 +1,3 @@
#! /bin/bash -e
# Generate mp_mbedtls_errors.c for inclusion in ports that use $MPY/lib/mbedtls
./generate_errors.pl ../../lib/mbedtls/include/mbedtls . mp_mbedtls_errors.c
4 changes: 4 additions & 0 deletions extmod/mbedtls_errors/do-test.sh
@@ -0,0 +1,4 @@
#! /bin/bash -e
# Generate mp_mbedtls_errors.c and build the tester app
./do-mp.sh
cc -o tester -I../../lib/mbedtls/include/mbedtls/ mp_mbedtls_errors.c tester.c
165 changes: 165 additions & 0 deletions extmod/mbedtls_errors/error.fmt
@@ -0,0 +1,165 @@
/*
* 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_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
#include "mbedtls/error.h"
#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

// Error code table type
struct ssl_errs {
int16_t errnum;
const char *errstr;
};

// Table of high level error codes
static const struct ssl_errs mbedtls_high_level_error_tab[] = {
// BEGIN generated code
HIGH_LEVEL_CODE_CHECKS
// END generated code
};

static const struct ssl_errs mbedtls_low_level_error_tab[] = {
// Low level error codes
//
// BEGIN generated code
LOW_LEVEL_CODE_CHECKS
// END generated code
};

static const char *mbedtls_err_prefix = "MBEDTLS_ERR_";
#define MBEDTLS_ERR_PREFIX_LEN ( sizeof("MBEDTLS_ERR_")-1 )

// copy error text into buffer, ensure null termination, return strlen of result
static size_t mbedtls_err_to_str(int err, const struct ssl_errs tab[], int tab_len, char *buf, size_t buflen) {
if (buflen == 0) return 0;

// prefix for all error names
strncpy(buf, mbedtls_err_prefix, buflen);
if (buflen <= MBEDTLS_ERR_PREFIX_LEN+1) {
buf[buflen-1] = 0;
return buflen-1;
}

// append error name from table
for (int i = 0; i < tab_len; i++) {
if (tab[i].errnum == err) {
strncpy(buf+MBEDTLS_ERR_PREFIX_LEN, tab[i].errstr, buflen-MBEDTLS_ERR_PREFIX_LEN);
buf[buflen-1] = 0;
return strlen(buf);
}
}

mbedtls_snprintf(buf+MBEDTLS_ERR_PREFIX_LEN, buflen-MBEDTLS_ERR_PREFIX_LEN, "UNKNOWN (0x%04X)",
err);
return strlen(buf);
}

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

void mbedtls_strerror(int ret, char *buf, size_t buflen) {
int use_ret;

if (buflen == 0) return;

buf[buflen-1] = 0;

if (ret < 0) ret = -ret;

//
// High-level error codes
//
uint8_t got_hl = (ret & 0xFF80) != 0;
if (got_hl) {
use_ret = ret & 0xFF80;

// special case
#if defined(MBEDTLS_SSL_TLS_C)
if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
strncpy(buf, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE", buflen);
buf[buflen-1] = 0;
return;
}
#endif

size_t len = mbedtls_err_to_str(use_ret, mbedtls_high_level_error_tab,
ARRAY_SIZE(mbedtls_high_level_error_tab), buf, buflen);

buf += len;
buflen -= len;
if (buflen == 0) return;
}

//
// Low-level error codes
//
use_ret = ret & ~0xFF80;

if (use_ret == 0) return;

// If high level code is present, make a concatenation between both error strings.
if (got_hl) {
if (buflen < 2) return;
*buf++ = '+';
buflen--;
}

mbedtls_err_to_str(use_ret, mbedtls_low_level_error_tab,
ARRAY_SIZE(mbedtls_low_level_error_tab), buf, buflen);
}

#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 */
123 changes: 123 additions & 0 deletions extmod/mbedtls_errors/error_orig.fmt
@@ -0,0 +1,123 @@
/*
* 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_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
#include "mbedtls/error.h"
#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

void mbedtls_strerror( int ret, char *buf, size_t buflen )
{
size_t len;
int use_ret;

if( buflen == 0 )
return;

memset( buf, 0x00, buflen );

if( ret < 0 )
ret = -ret;

if( ret & 0xFF80 )
{
use_ret = ret & 0xFF80;

// High level error codes
//
// BEGIN generated code
HIGH_LEVEL_CODE_CHECKS
// END generated code

if( strlen( buf ) == 0 )
mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
}

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;
}

// Low level error codes
//
// BEGIN generated code
LOW_LEVEL_CODE_CHECKS
// END generated code

if( strlen( buf ) != 0 )
return;

mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret );
}

#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 */

0 comments on commit ec73868

Please sign in to comment.