Merge pull request #6999 from jepler/picow-ssl

pico_w: implement ssl with caveats
This commit is contained in:
Dan Halbert 2022-10-06 10:51:36 -04:00 committed by GitHub
commit e0517c7379
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 2573 additions and 35 deletions

5
.gitmodules vendored
View File

@ -148,7 +148,7 @@
url = https://github.com/adafruit/esp-idf.git
branch = circuitpython8
[submodule "ports/espressif/certificates/nina-fw"]
path = ports/espressif/certificates/nina-fw
path = lib/certificates/nina-fw
url = https://github.com/adafruit/nina-fw.git
[submodule "frozen/Adafruit_CircuitPython_ST7789"]
path = frozen/Adafruit_CircuitPython_ST7789
@ -316,3 +316,6 @@
[submodule "ports/raspberrypi/lib/lwip"]
path = ports/raspberrypi/lib/lwip
url = https://github.com/lwip-tcpip/lwip.git
[submodule "lib/mbedtls"]
path = lib/mbedtls
url = https://github.com/ARMmbed/mbedtls.git

View File

@ -10,7 +10,7 @@ repos:
- id: end-of-file-fixer
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/espressif/esp-idf-config/.*|ports/espressif/boards/.*/sdkconfig)'
- id: trailing-whitespace
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*)'
exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|lib/mbedtls_errors/.*)'
- repo: local
hooks:
- id: translations

1
lib/mbedtls Submodule

@ -0,0 +1 @@
Subproject commit 1bc2c9cb8b8fe4659bd94b8ebba5a4c02029b7fa

View File

@ -0,0 +1,42 @@
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 value #defines 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.diff` - diff for original mbedtls perl script
- `error.fmt` - modified code template for MicroPython
- `mp_mbedtls_errors.c` - source file with `mbedtls_strerror` this is built using the include
files in `../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
- `do-esp32.sh` - shell script to produce `esp32_mbedtls_errors.c` -- see below
In order not to store multiple copies of `mbedtls_errors.c`
([https://github.com/micropython/micropython/pull/5819#discussion_r445528006](see))
it is assumed that all ports use the same version of mbedtls with the same error #defines.
This is true as of MP v1.13, and ESP-IDF versions 3.3.2 and 4.0.1. If anything changes in the
future the `do-esp32.sh` script can be used to generate an esp32-specific version.
### How-to
- To build MicroPython all that is needed is to include the `mp_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 `do-mp.sh` script should be run to
re-generate `mp_mbedtls_errors.c`.
- The `tester` app should be run if changes to the string handling in `error.fmt` are made:
it tests that there is not an off-by-one error in the string copying/appending, etc.
- To include `mbedtls_strerror` error strings define `MBEDTLS_ERROR_C` in the build.

7
lib/mbedtls_errors/do-esp32.sh Executable file
View File

@ -0,0 +1,7 @@
#! /bin/bash -e
# Generate esp32_mbedtls_errors.c for use in the Esp32 port, with the ESP-IDF version of mbedtls
# The IDF_PATH env var must be set to the top-level dir of ESPIDF
echo "IDF_PATH=$IDF_PATH"
MBEDTLS=$IDF_PATH/components/mbedtls/mbedtls
patch -o esp32_generate_errors.pl $MBEDTLS/scripts/generate_errors.pl <generate_errors.diff
perl ./esp32_generate_errors.pl $MBEDTLS/include/mbedtls . esp32_mbedtls_errors.c

4
lib/mbedtls_errors/do-mp.sh Executable file
View File

@ -0,0 +1,4 @@
#! /bin/bash -e
# Generate mp_mbedtls_errors.c for inclusion in ports that use $MPY/lib/mbedtls
patch -o mp_generate_errors.pl ../mbedtls/scripts/generate_errors.pl <generate_errors.diff
perl ./mp_generate_errors.pl ../mbedtls/include/mbedtls . mp_mbedtls_errors.c

4
lib/mbedtls_errors/do-test.sh Executable file
View File

@ -0,0 +1,4 @@
#! /bin/bash -e
# Generate mp_mbedtls_errors.c and build the tester app
./do-mp.sh
cc -o tester -I../mbedtls/include/ mp_mbedtls_errors.c tester.c

View File

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

View File

@ -0,0 +1,22 @@
--- generate_errors_orig.pl 2020-06-20 08:40:38.819060379 -0700
+++ generate_errors.pl 2020-06-20 08:47:26.511163591 -0700
@@ -162,16 +162,12 @@
if ($error_name eq "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE")
{
- ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n".
- "${white_space}\{\n".
- "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n".
- "${white_space} return;\n".
- "${white_space}}\n"
+ # no-op, this case is hard-coded in error.fmt
}
else
{
- ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n".
- "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n"
+ my $error_text = $error_name =~ s/^MBEDTLS_ERR_//r;
+ ${$code_check} .= "${white_space}{ -($error_name), \"$error_text\" },\n"
}
};

View File

@ -0,0 +1,705 @@
/*
* 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>
#if defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
#endif
#if defined(MBEDTLS_ARC4_C)
#include "mbedtls/arc4.h"
#endif
#if defined(MBEDTLS_ARIA_C)
#include "mbedtls/aria.h"
#endif
#if defined(MBEDTLS_BASE64_C)
#include "mbedtls/base64.h"
#endif
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#endif
#if defined(MBEDTLS_BLOWFISH_C)
#include "mbedtls/blowfish.h"
#endif
#if defined(MBEDTLS_CAMELLIA_C)
#include "mbedtls/camellia.h"
#endif
#if defined(MBEDTLS_CCM_C)
#include "mbedtls/ccm.h"
#endif
#if defined(MBEDTLS_CHACHA20_C)
#include "mbedtls/chacha20.h"
#endif
#if defined(MBEDTLS_CHACHAPOLY_C)
#include "mbedtls/chachapoly.h"
#endif
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher.h"
#endif
#if defined(MBEDTLS_CMAC_C)
#include "mbedtls/cmac.h"
#endif
#if defined(MBEDTLS_CTR_DRBG_C)
#include "mbedtls/ctr_drbg.h"
#endif
#if defined(MBEDTLS_DES_C)
#include "mbedtls/des.h"
#endif
#if defined(MBEDTLS_DHM_C)
#include "mbedtls/dhm.h"
#endif
#if defined(MBEDTLS_ECP_C)
#include "mbedtls/ecp.h"
#endif
#if defined(MBEDTLS_ENTROPY_C)
#include "mbedtls/entropy.h"
#endif
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
#if defined(MBEDTLS_HKDF_C)
#include "mbedtls/hkdf.h"
#endif
#if defined(MBEDTLS_HMAC_DRBG_C)
#include "mbedtls/hmac_drbg.h"
#endif
#if defined(MBEDTLS_MD_C)
#include "mbedtls/md.h"
#endif
#if defined(MBEDTLS_MD2_C)
#include "mbedtls/md2.h"
#endif
#if defined(MBEDTLS_MD4_C)
#include "mbedtls/md4.h"
#endif
#if defined(MBEDTLS_MD5_C)
#include "mbedtls/md5.h"
#endif
#if defined(MBEDTLS_NET_C)
#include "mbedtls/net_sockets.h"
#endif
#if defined(MBEDTLS_OID_C)
#include "mbedtls/oid.h"
#endif
#if defined(MBEDTLS_PADLOCK_C)
#include "mbedtls/padlock.h"
#endif
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
#include "mbedtls/pem.h"
#endif
#if defined(MBEDTLS_PK_C)
#include "mbedtls/pk.h"
#endif
#if defined(MBEDTLS_PKCS12_C)
#include "mbedtls/pkcs12.h"
#endif
#if defined(MBEDTLS_PKCS5_C)
#include "mbedtls/pkcs5.h"
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#endif
#if defined(MBEDTLS_POLY1305_C)
#include "mbedtls/poly1305.h"
#endif
#if defined(MBEDTLS_RIPEMD160_C)
#include "mbedtls/ripemd160.h"
#endif
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
#endif
#if defined(MBEDTLS_SHA1_C)
#include "mbedtls/sha1.h"
#endif
#if defined(MBEDTLS_SHA256_C)
#include "mbedtls/sha256.h"
#endif
#if defined(MBEDTLS_SHA512_C)
#include "mbedtls/sha512.h"
#endif
#if defined(MBEDTLS_SSL_TLS_C)
#include "mbedtls/ssl.h"
#endif
#if defined(MBEDTLS_THREADING_C)
#include "mbedtls/threading.h"
#endif
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
#include "mbedtls/x509.h"
#endif
#if defined(MBEDTLS_XTEA_C)
#include "mbedtls/xtea.h"
#endif
// 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
#if defined(MBEDTLS_CIPHER_C)
{ -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE), "CIPHER_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA), "CIPHER_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED), "CIPHER_ALLOC_FAILED" },
{ -(MBEDTLS_ERR_CIPHER_INVALID_PADDING), "CIPHER_INVALID_PADDING" },
{ -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED), "CIPHER_FULL_BLOCK_EXPECTED" },
{ -(MBEDTLS_ERR_CIPHER_AUTH_FAILED), "CIPHER_AUTH_FAILED" },
{ -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT), "CIPHER_INVALID_CONTEXT" },
{ -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED), "CIPHER_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_CIPHER_C */
#if defined(MBEDTLS_DHM_C)
{ -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA), "DHM_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED), "DHM_READ_PARAMS_FAILED" },
{ -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED), "DHM_MAKE_PARAMS_FAILED" },
{ -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED), "DHM_READ_PUBLIC_FAILED" },
{ -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED), "DHM_MAKE_PUBLIC_FAILED" },
{ -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED), "DHM_CALC_SECRET_FAILED" },
{ -(MBEDTLS_ERR_DHM_INVALID_FORMAT), "DHM_INVALID_FORMAT" },
{ -(MBEDTLS_ERR_DHM_ALLOC_FAILED), "DHM_ALLOC_FAILED" },
{ -(MBEDTLS_ERR_DHM_FILE_IO_ERROR), "DHM_FILE_IO_ERROR" },
{ -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED), "DHM_HW_ACCEL_FAILED" },
{ -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED), "DHM_SET_GROUP_FAILED" },
#endif /* MBEDTLS_DHM_C */
#if defined(MBEDTLS_ECP_C)
{ -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA), "ECP_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL), "ECP_BUFFER_TOO_SMALL" },
{ -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE), "ECP_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_ECP_VERIFY_FAILED), "ECP_VERIFY_FAILED" },
{ -(MBEDTLS_ERR_ECP_ALLOC_FAILED), "ECP_ALLOC_FAILED" },
{ -(MBEDTLS_ERR_ECP_RANDOM_FAILED), "ECP_RANDOM_FAILED" },
{ -(MBEDTLS_ERR_ECP_INVALID_KEY), "ECP_INVALID_KEY" },
{ -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH), "ECP_SIG_LEN_MISMATCH" },
{ -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED), "ECP_HW_ACCEL_FAILED" },
{ -(MBEDTLS_ERR_ECP_IN_PROGRESS), "ECP_IN_PROGRESS" },
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_MD_C)
{ -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE), "MD_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_MD_BAD_INPUT_DATA), "MD_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_MD_ALLOC_FAILED), "MD_ALLOC_FAILED" },
{ -(MBEDTLS_ERR_MD_FILE_IO_ERROR), "MD_FILE_IO_ERROR" },
{ -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED), "MD_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_MD_C */
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
{ -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT), "PEM_NO_HEADER_FOOTER_PRESENT" },
{ -(MBEDTLS_ERR_PEM_INVALID_DATA), "PEM_INVALID_DATA" },
{ -(MBEDTLS_ERR_PEM_ALLOC_FAILED), "PEM_ALLOC_FAILED" },
{ -(MBEDTLS_ERR_PEM_INVALID_ENC_IV), "PEM_INVALID_ENC_IV" },
{ -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG), "PEM_UNKNOWN_ENC_ALG" },
{ -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED), "PEM_PASSWORD_REQUIRED" },
{ -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH), "PEM_PASSWORD_MISMATCH" },
{ -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE), "PEM_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA), "PEM_BAD_INPUT_DATA" },
#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */
#if defined(MBEDTLS_PK_C)
{ -(MBEDTLS_ERR_PK_ALLOC_FAILED), "PK_ALLOC_FAILED" },
{ -(MBEDTLS_ERR_PK_TYPE_MISMATCH), "PK_TYPE_MISMATCH" },
{ -(MBEDTLS_ERR_PK_BAD_INPUT_DATA), "PK_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_PK_FILE_IO_ERROR), "PK_FILE_IO_ERROR" },
{ -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION), "PK_KEY_INVALID_VERSION" },
{ -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT), "PK_KEY_INVALID_FORMAT" },
{ -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG), "PK_UNKNOWN_PK_ALG" },
{ -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED), "PK_PASSWORD_REQUIRED" },
{ -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH), "PK_PASSWORD_MISMATCH" },
{ -(MBEDTLS_ERR_PK_INVALID_PUBKEY), "PK_INVALID_PUBKEY" },
{ -(MBEDTLS_ERR_PK_INVALID_ALG), "PK_INVALID_ALG" },
{ -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE), "PK_UNKNOWN_NAMED_CURVE" },
{ -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE), "PK_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH), "PK_SIG_LEN_MISMATCH" },
{ -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED), "PK_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_PK_C */
#if defined(MBEDTLS_PKCS12_C)
{ -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA), "PKCS12_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE), "PKCS12_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT), "PKCS12_PBE_INVALID_FORMAT" },
{ -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH), "PKCS12_PASSWORD_MISMATCH" },
#endif /* MBEDTLS_PKCS12_C */
#if defined(MBEDTLS_PKCS5_C)
{ -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA), "PKCS5_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT), "PKCS5_INVALID_FORMAT" },
{ -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE), "PKCS5_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH), "PKCS5_PASSWORD_MISMATCH" },
#endif /* MBEDTLS_PKCS5_C */
#if defined(MBEDTLS_RSA_C)
{ -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA), "RSA_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_RSA_INVALID_PADDING), "RSA_INVALID_PADDING" },
{ -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED), "RSA_KEY_GEN_FAILED" },
{ -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED), "RSA_KEY_CHECK_FAILED" },
{ -(MBEDTLS_ERR_RSA_PUBLIC_FAILED), "RSA_PUBLIC_FAILED" },
{ -(MBEDTLS_ERR_RSA_PRIVATE_FAILED), "RSA_PRIVATE_FAILED" },
{ -(MBEDTLS_ERR_RSA_VERIFY_FAILED), "RSA_VERIFY_FAILED" },
{ -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE), "RSA_OUTPUT_TOO_LARGE" },
{ -(MBEDTLS_ERR_RSA_RNG_FAILED), "RSA_RNG_FAILED" },
{ -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION), "RSA_UNSUPPORTED_OPERATION" },
{ -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED), "RSA_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_SSL_TLS_C)
{ -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE), "SSL_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA), "SSL_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_SSL_INVALID_MAC), "SSL_INVALID_MAC" },
{ -(MBEDTLS_ERR_SSL_INVALID_RECORD), "SSL_INVALID_RECORD" },
{ -(MBEDTLS_ERR_SSL_CONN_EOF), "SSL_CONN_EOF" },
{ -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER), "SSL_UNKNOWN_CIPHER" },
{ -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN), "SSL_NO_CIPHER_CHOSEN" },
{ -(MBEDTLS_ERR_SSL_NO_RNG), "SSL_NO_RNG" },
{ -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE), "SSL_NO_CLIENT_CERTIFICATE" },
{ -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE), "SSL_CERTIFICATE_TOO_LARGE" },
{ -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED), "SSL_CERTIFICATE_REQUIRED" },
{ -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED), "SSL_PRIVATE_KEY_REQUIRED" },
{ -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED), "SSL_CA_CHAIN_REQUIRED" },
{ -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE), "SSL_UNEXPECTED_MESSAGE" },
{ -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED), "SSL_PEER_VERIFY_FAILED" },
{ -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY), "SSL_PEER_CLOSE_NOTIFY" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO), "SSL_BAD_HS_CLIENT_HELLO" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO), "SSL_BAD_HS_SERVER_HELLO" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE), "SSL_BAD_HS_CERTIFICATE" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST), "SSL_BAD_HS_CERTIFICATE_REQUEST" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE), "SSL_BAD_HS_SERVER_KEY_EXCHANGE" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE), "SSL_BAD_HS_SERVER_HELLO_DONE" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY), "SSL_BAD_HS_CERTIFICATE_VERIFY" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC), "SSL_BAD_HS_CHANGE_CIPHER_SPEC" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED), "SSL_BAD_HS_FINISHED" },
{ -(MBEDTLS_ERR_SSL_ALLOC_FAILED), "SSL_ALLOC_FAILED" },
{ -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED), "SSL_HW_ACCEL_FAILED" },
{ -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH), "SSL_HW_ACCEL_FALLTHROUGH" },
{ -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED), "SSL_COMPRESSION_FAILED" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION), "SSL_BAD_HS_PROTOCOL_VERSION" },
{ -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET), "SSL_BAD_HS_NEW_SESSION_TICKET" },
{ -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED), "SSL_SESSION_TICKET_EXPIRED" },
{ -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH), "SSL_PK_TYPE_MISMATCH" },
{ -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY), "SSL_UNKNOWN_IDENTITY" },
{ -(MBEDTLS_ERR_SSL_INTERNAL_ERROR), "SSL_INTERNAL_ERROR" },
{ -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING), "SSL_COUNTER_WRAPPING" },
{ -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO), "SSL_WAITING_SERVER_HELLO_RENEGO" },
{ -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED), "SSL_HELLO_VERIFY_REQUIRED" },
{ -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL), "SSL_BUFFER_TOO_SMALL" },
{ -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE), "SSL_NO_USABLE_CIPHERSUITE" },
{ -(MBEDTLS_ERR_SSL_WANT_READ), "SSL_WANT_READ" },
{ -(MBEDTLS_ERR_SSL_WANT_WRITE), "SSL_WANT_WRITE" },
{ -(MBEDTLS_ERR_SSL_TIMEOUT), "SSL_TIMEOUT" },
{ -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT), "SSL_CLIENT_RECONNECT" },
{ -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD), "SSL_UNEXPECTED_RECORD" },
{ -(MBEDTLS_ERR_SSL_NON_FATAL), "SSL_NON_FATAL" },
{ -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH), "SSL_INVALID_VERIFY_HASH" },
{ -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING), "SSL_CONTINUE_PROCESSING" },
{ -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS), "SSL_ASYNC_IN_PROGRESS" },
{ -(MBEDTLS_ERR_SSL_EARLY_MESSAGE), "SSL_EARLY_MESSAGE" },
{ -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS), "SSL_CRYPTO_IN_PROGRESS" },
#endif /* MBEDTLS_SSL_TLS_C */
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
{ -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE), "X509_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_X509_UNKNOWN_OID), "X509_UNKNOWN_OID" },
{ -(MBEDTLS_ERR_X509_INVALID_FORMAT), "X509_INVALID_FORMAT" },
{ -(MBEDTLS_ERR_X509_INVALID_VERSION), "X509_INVALID_VERSION" },
{ -(MBEDTLS_ERR_X509_INVALID_SERIAL), "X509_INVALID_SERIAL" },
{ -(MBEDTLS_ERR_X509_INVALID_ALG), "X509_INVALID_ALG" },
{ -(MBEDTLS_ERR_X509_INVALID_NAME), "X509_INVALID_NAME" },
{ -(MBEDTLS_ERR_X509_INVALID_DATE), "X509_INVALID_DATE" },
{ -(MBEDTLS_ERR_X509_INVALID_SIGNATURE), "X509_INVALID_SIGNATURE" },
{ -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS), "X509_INVALID_EXTENSIONS" },
{ -(MBEDTLS_ERR_X509_UNKNOWN_VERSION), "X509_UNKNOWN_VERSION" },
{ -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG), "X509_UNKNOWN_SIG_ALG" },
{ -(MBEDTLS_ERR_X509_SIG_MISMATCH), "X509_SIG_MISMATCH" },
{ -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED), "X509_CERT_VERIFY_FAILED" },
{ -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT), "X509_CERT_UNKNOWN_FORMAT" },
{ -(MBEDTLS_ERR_X509_BAD_INPUT_DATA), "X509_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_X509_ALLOC_FAILED), "X509_ALLOC_FAILED" },
{ -(MBEDTLS_ERR_X509_FILE_IO_ERROR), "X509_FILE_IO_ERROR" },
{ -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL), "X509_BUFFER_TOO_SMALL" },
{ -(MBEDTLS_ERR_X509_FATAL_ERROR), "X509_FATAL_ERROR" },
#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
// END generated code
};
static const struct ssl_errs mbedtls_low_level_error_tab[] = {
// Low level error codes
//
// BEGIN generated code
#if defined(MBEDTLS_AES_C)
{ -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH), "AES_INVALID_KEY_LENGTH" },
{ -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH), "AES_INVALID_INPUT_LENGTH" },
{ -(MBEDTLS_ERR_AES_BAD_INPUT_DATA), "AES_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE), "AES_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED), "AES_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_AES_C */
#if defined(MBEDTLS_ARC4_C)
{ -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED), "ARC4_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_ARC4_C */
#if defined(MBEDTLS_ARIA_C)
{ -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA), "ARIA_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH), "ARIA_INVALID_INPUT_LENGTH" },
{ -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE), "ARIA_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED), "ARIA_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_ARIA_C */
#if defined(MBEDTLS_ASN1_PARSE_C)
{ -(MBEDTLS_ERR_ASN1_OUT_OF_DATA), "ASN1_OUT_OF_DATA" },
{ -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG), "ASN1_UNEXPECTED_TAG" },
{ -(MBEDTLS_ERR_ASN1_INVALID_LENGTH), "ASN1_INVALID_LENGTH" },
{ -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH), "ASN1_LENGTH_MISMATCH" },
{ -(MBEDTLS_ERR_ASN1_INVALID_DATA), "ASN1_INVALID_DATA" },
{ -(MBEDTLS_ERR_ASN1_ALLOC_FAILED), "ASN1_ALLOC_FAILED" },
{ -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL), "ASN1_BUF_TOO_SMALL" },
#endif /* MBEDTLS_ASN1_PARSE_C */
#if defined(MBEDTLS_BASE64_C)
{ -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL), "BASE64_BUFFER_TOO_SMALL" },
{ -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER), "BASE64_INVALID_CHARACTER" },
#endif /* MBEDTLS_BASE64_C */
#if defined(MBEDTLS_BIGNUM_C)
{ -(MBEDTLS_ERR_MPI_FILE_IO_ERROR), "MPI_FILE_IO_ERROR" },
{ -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA), "MPI_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_MPI_INVALID_CHARACTER), "MPI_INVALID_CHARACTER" },
{ -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL), "MPI_BUFFER_TOO_SMALL" },
{ -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE), "MPI_NEGATIVE_VALUE" },
{ -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO), "MPI_DIVISION_BY_ZERO" },
{ -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE), "MPI_NOT_ACCEPTABLE" },
{ -(MBEDTLS_ERR_MPI_ALLOC_FAILED), "MPI_ALLOC_FAILED" },
#endif /* MBEDTLS_BIGNUM_C */
#if defined(MBEDTLS_BLOWFISH_C)
{ -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA), "BLOWFISH_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH), "BLOWFISH_INVALID_INPUT_LENGTH" },
{ -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED), "BLOWFISH_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_BLOWFISH_C */
#if defined(MBEDTLS_CAMELLIA_C)
{ -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA), "CAMELLIA_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH), "CAMELLIA_INVALID_INPUT_LENGTH" },
{ -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED), "CAMELLIA_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_CAMELLIA_C */
#if defined(MBEDTLS_CCM_C)
{ -(MBEDTLS_ERR_CCM_BAD_INPUT), "CCM_BAD_INPUT" },
{ -(MBEDTLS_ERR_CCM_AUTH_FAILED), "CCM_AUTH_FAILED" },
{ -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED), "CCM_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_CCM_C */
#if defined(MBEDTLS_CHACHA20_C)
{ -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA), "CHACHA20_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE), "CHACHA20_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED), "CHACHA20_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_CHACHA20_C */
#if defined(MBEDTLS_CHACHAPOLY_C)
{ -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE), "CHACHAPOLY_BAD_STATE" },
{ -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED), "CHACHAPOLY_AUTH_FAILED" },
#endif /* MBEDTLS_CHACHAPOLY_C */
#if defined(MBEDTLS_CMAC_C)
{ -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED), "CMAC_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_CMAC_C */
#if defined(MBEDTLS_CTR_DRBG_C)
{ -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED), "CTR_DRBG_ENTROPY_SOURCE_FAILED" },
{ -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG), "CTR_DRBG_REQUEST_TOO_BIG" },
{ -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG), "CTR_DRBG_INPUT_TOO_BIG" },
{ -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR), "CTR_DRBG_FILE_IO_ERROR" },
#endif /* MBEDTLS_CTR_DRBG_C */
#if defined(MBEDTLS_DES_C)
{ -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH), "DES_INVALID_INPUT_LENGTH" },
{ -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED), "DES_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_ENTROPY_C)
{ -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED), "ENTROPY_SOURCE_FAILED" },
{ -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES), "ENTROPY_MAX_SOURCES" },
{ -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED), "ENTROPY_NO_SOURCES_DEFINED" },
{ -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE), "ENTROPY_NO_STRONG_SOURCE" },
{ -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR), "ENTROPY_FILE_IO_ERROR" },
#endif /* MBEDTLS_ENTROPY_C */
#if defined(MBEDTLS_GCM_C)
{ -(MBEDTLS_ERR_GCM_AUTH_FAILED), "GCM_AUTH_FAILED" },
{ -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED), "GCM_HW_ACCEL_FAILED" },
{ -(MBEDTLS_ERR_GCM_BAD_INPUT), "GCM_BAD_INPUT" },
#endif /* MBEDTLS_GCM_C */
#if defined(MBEDTLS_HKDF_C)
{ -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA), "HKDF_BAD_INPUT_DATA" },
#endif /* MBEDTLS_HKDF_C */
#if defined(MBEDTLS_HMAC_DRBG_C)
{ -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG), "HMAC_DRBG_REQUEST_TOO_BIG" },
{ -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG), "HMAC_DRBG_INPUT_TOO_BIG" },
{ -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR), "HMAC_DRBG_FILE_IO_ERROR" },
{ -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED), "HMAC_DRBG_ENTROPY_SOURCE_FAILED" },
#endif /* MBEDTLS_HMAC_DRBG_C */
#if defined(MBEDTLS_MD2_C)
{ -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED), "MD2_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_MD2_C */
#if defined(MBEDTLS_MD4_C)
{ -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED), "MD4_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_MD4_C */
#if defined(MBEDTLS_MD5_C)
{ -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED), "MD5_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_MD5_C */
#if defined(MBEDTLS_NET_C)
{ -(MBEDTLS_ERR_NET_SOCKET_FAILED), "NET_SOCKET_FAILED" },
{ -(MBEDTLS_ERR_NET_CONNECT_FAILED), "NET_CONNECT_FAILED" },
{ -(MBEDTLS_ERR_NET_BIND_FAILED), "NET_BIND_FAILED" },
{ -(MBEDTLS_ERR_NET_LISTEN_FAILED), "NET_LISTEN_FAILED" },
{ -(MBEDTLS_ERR_NET_ACCEPT_FAILED), "NET_ACCEPT_FAILED" },
{ -(MBEDTLS_ERR_NET_RECV_FAILED), "NET_RECV_FAILED" },
{ -(MBEDTLS_ERR_NET_SEND_FAILED), "NET_SEND_FAILED" },
{ -(MBEDTLS_ERR_NET_CONN_RESET), "NET_CONN_RESET" },
{ -(MBEDTLS_ERR_NET_UNKNOWN_HOST), "NET_UNKNOWN_HOST" },
{ -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL), "NET_BUFFER_TOO_SMALL" },
{ -(MBEDTLS_ERR_NET_INVALID_CONTEXT), "NET_INVALID_CONTEXT" },
{ -(MBEDTLS_ERR_NET_POLL_FAILED), "NET_POLL_FAILED" },
{ -(MBEDTLS_ERR_NET_BAD_INPUT_DATA), "NET_BAD_INPUT_DATA" },
#endif /* MBEDTLS_NET_C */
#if defined(MBEDTLS_OID_C)
{ -(MBEDTLS_ERR_OID_NOT_FOUND), "OID_NOT_FOUND" },
{ -(MBEDTLS_ERR_OID_BUF_TOO_SMALL), "OID_BUF_TOO_SMALL" },
#endif /* MBEDTLS_OID_C */
#if defined(MBEDTLS_PADLOCK_C)
{ -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED), "PADLOCK_DATA_MISALIGNED" },
#endif /* MBEDTLS_PADLOCK_C */
#if defined(MBEDTLS_PLATFORM_C)
{ -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED), "PLATFORM_HW_ACCEL_FAILED" },
{ -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED), "PLATFORM_FEATURE_UNSUPPORTED" },
#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_POLY1305_C)
{ -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA), "POLY1305_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE), "POLY1305_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED), "POLY1305_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_POLY1305_C */
#if defined(MBEDTLS_RIPEMD160_C)
{ -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED), "RIPEMD160_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_RIPEMD160_C */
#if defined(MBEDTLS_SHA1_C)
{ -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED), "SHA1_HW_ACCEL_FAILED" },
{ -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA), "SHA1_BAD_INPUT_DATA" },
#endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA256_C)
{ -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED), "SHA256_HW_ACCEL_FAILED" },
{ -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA), "SHA256_BAD_INPUT_DATA" },
#endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C)
{ -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED), "SHA512_HW_ACCEL_FAILED" },
{ -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA), "SHA512_BAD_INPUT_DATA" },
#endif /* MBEDTLS_SHA512_C */
#if defined(MBEDTLS_THREADING_C)
{ -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE), "THREADING_FEATURE_UNAVAILABLE" },
{ -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA), "THREADING_BAD_INPUT_DATA" },
{ -(MBEDTLS_ERR_THREADING_MUTEX_ERROR), "THREADING_MUTEX_ERROR" },
#endif /* MBEDTLS_THREADING_C */
#if defined(MBEDTLS_XTEA_C)
{ -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH), "XTEA_INVALID_INPUT_LENGTH" },
{ -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED), "XTEA_HW_ACCEL_FAILED" },
#endif /* MBEDTLS_XTEA_C */
// 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 */

View File

@ -0,0 +1,58 @@
#include "mbedtls/error.h"
#include <string.h>
#include <stdio.h>
// test_code checks that the provided code results in the provided error string for any size
// buffer. It calls mbedtls_strerror() to fill a buffer that is from 1 to 100 bytes in length
// and then checks that the buffer contents is OK and that a few guard bytes before and after
// the buffer were not overwritten.
int test_code(int code, char *str) {
char buf[100];
int ok = 1;
int res;
// test zero-length buffer
memset(buf, -3, 100);
mbedtls_strerror(code, buf + 4, 0);
for (int i = 0; i < 10; i++) {
if (buf[i] != -3) {
printf("Error: guard overwritten buflen=0 i=%d buf[i]=%d\n", i, buf[i]);
ok = 0;
}
}
// test
for (size_t buflen = 1; buflen < 90; buflen++) {
memset(buf, -3, 100);
mbedtls_strerror(code, buf + 4, buflen);
for (int i = 0; i < 4; i++) {
if (buf[i] != -3) {
printf("Error: pre-guard overwritten buflen=%d i=%d buf[i]=%d\n", buflen, i, buf[i]);
ok = 0;
}
}
for (int i = 4 + buflen; i < 100; i++) {
if (buf[i] != -3) {
printf("Error: post-guard overwritten buflen=%d i=%d buf[i]=%d\n", buflen, i, buf[i]);
ok = 0;
}
}
char exp[100];
strncpy(exp, str, buflen);
exp[buflen - 1] = 0;
if (strcmp(buf + 4, exp) != 0) {
printf("Error: expected %s, got %s\n", exp, buf);
ok = 0;
}
}
printf("Test %x -> %s is %s\n", code, str, ok?"OK":"*** BAD ***");
}
int main() {
test_code(0x7200, "MBEDTLS_ERR_SSL_INVALID_RECORD");
test_code(0x7780, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE");
test_code(0x0074, "MBEDTLS_ERR_SHA256_BAD_INPUT_DATA");
test_code(0x6600 | 0x0074, "MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH+MBEDTLS_ERR_SHA256_BAD_INPUT_DATA");
test_code(103, "MBEDTLS_ERR_UNKNOWN (0x0067)");
}

View File

@ -152,14 +152,6 @@ msgstr ""
msgid "%q must be >= %d"
msgstr ""
#: py/argcheck.c
msgid "%q must be >= 0"
msgstr ""
#: shared-bindings/vectorio/Circle.c shared-bindings/vectorio/Rectangle.c
msgid "%q must be >= 1"
msgstr ""
#: shared-bindings/analogbufio/BufferedIn.c
#: shared-bindings/audiocore/RawSample.c
msgid "%q must be a bytearray or array of type 'h', 'H', 'b', or 'B'"
@ -910,8 +902,7 @@ msgstr ""
msgid "Error: Failure to bind"
msgstr ""
#: ports/raspberrypi/bindings/rp2pio/StateMachine.c py/enum.c
#: shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c
#: py/enum.c shared-bindings/_bleio/__init__.c shared-bindings/aesio/aes.c
#: shared-bindings/alarm/__init__.c shared-bindings/busio/SPI.c
#: shared-bindings/microcontroller/Pin.c
#: shared-bindings/neopixel_write/__init__.c
@ -1243,6 +1234,7 @@ msgid "Invalid size"
msgstr ""
#: ports/espressif/common-hal/ssl/SSLContext.c
#: ports/raspberrypi/common-hal/ssl/SSLSocket.c
msgid "Invalid socket for TLS"
msgstr ""
@ -1569,10 +1561,12 @@ msgid "Only 8 or 16 bit mono with "
msgstr ""
#: ports/espressif/common-hal/wifi/__init__.c
#: ports/raspberrypi/common-hal/wifi/__init__.c
msgid "Only IPv4 addresses supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Only IPv4 sockets supported"
msgstr ""
@ -1642,6 +1636,7 @@ msgid "Out of memory"
msgstr ""
#: ports/espressif/common-hal/socketpool/Socket.c
#: ports/raspberrypi/common-hal/socketpool/Socket.c
msgid "Out of sockets"
msgstr ""
@ -1696,7 +1691,6 @@ msgid "Pin interrupt already in use"
msgstr ""
#: shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c
#: shared-bindings/digitalio/DigitalInOut.c
msgid "Pin is input only"
msgstr ""
@ -1916,6 +1910,7 @@ msgid "Slices not supported"
msgstr ""
#: ports/espressif/common-hal/socketpool/SocketPool.c
#: ports/raspberrypi/common-hal/socketpool/SocketPool.c
msgid "SocketPool can only be used with wifi.radio"
msgstr ""
@ -2341,10 +2336,6 @@ msgstr ""
msgid "a bytes-like object is required"
msgstr ""
#: shared-bindings/i2ctarget/I2CTarget.c
msgid "address out of bounds"
msgstr ""
#: shared-bindings/i2ctarget/I2CTarget.c
msgid "addresses is empty"
msgstr ""
@ -2814,10 +2805,6 @@ msgstr ""
msgid "destination buffer must be an array of type 'H' for bit_depth = 16"
msgstr ""
#: shared-bindings/audiobusio/PDMIn.c
msgid "destination_length must be an int >= 0"
msgstr ""
#: py/objdict.c
msgid "dict update sequence has wrong length"
msgstr ""
@ -3241,6 +3228,10 @@ msgstr ""
msgid "invalid bits_per_pixel %d, must be, 1, 2, 4, 8, 16, 24, or 32"
msgstr ""
#: ports/raspberrypi/common-hal/ssl/SSLSocket.c
msgid "invalid cert"
msgstr ""
#: shared-bindings/bitmaptools/__init__.c
#, c-format
msgid "invalid element size %d for bits_per_pixel %d\n"
@ -3267,6 +3258,10 @@ msgstr ""
msgid "invalid hostname"
msgstr ""
#: ports/raspberrypi/common-hal/ssl/SSLSocket.c
msgid "invalid key"
msgstr ""
#: py/compile.c
msgid "invalid micropython decorator"
msgstr ""

View File

@ -96,7 +96,7 @@ bool common_hal_ssl_sslsocket_listen(ssl_sslsocket_obj_t *self, int backlog) {
return common_hal_socketpool_socket_listen(self->sock, backlog);
}
mp_uint_t common_hal_ssl_sslsocket_recv_into(ssl_sslsocket_obj_t *self, const uint8_t *buf, uint32_t len) {
mp_uint_t common_hal_ssl_sslsocket_recv_into(ssl_sslsocket_obj_t *self, uint8_t *buf, uint32_t len) {
int received = 0;
bool timed_out = false;
int status = 0;
@ -158,7 +158,7 @@ mp_uint_t common_hal_ssl_sslsocket_send(ssl_sslsocket_obj_t *self, const uint8_t
if (err == ESP_ERR_MBEDTLS_SSL_SETUP_FAILED) {
mp_raise_espidf_MemoryError();
} else if (ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED) {
} else if (err == ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED) {
mp_raise_OSError_msg_varg(translate("Failed SSL handshake"));
} else {
mp_raise_OSError_msg_varg(translate("Unhandled ESP TLS error %d %d %x %d"), esp_tls_code, flags, err, sent);

View File

@ -795,7 +795,7 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y
# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE=y
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certificates/nina-fw/data/roots.pem"
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="../../lib/certificates/nina-fw/data/roots.pem"
# end of Certificate Bundle
CONFIG_MBEDTLS_ECP_RESTARTABLE=y

View File

@ -572,7 +572,7 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y
# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE=y
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="certificates/nina-fw/data/roots.pem"
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="../../lib/certificates/nina-fw/data/roots.pem"
# end of Certificate Bundle
CONFIG_MBEDTLS_ECP_RESTARTABLE=y

View File

@ -276,6 +276,93 @@ SRC_C += \
$(SRC_CYW43) \
$(SRC_LWIP) \
ifeq ($(CIRCUITPY_SSL),1)
CFLAGS += -isystem $(TOP)/mbedtls/include
SRC_MBEDTLS := $(addprefix lib/mbedtls/library/, \
aes.c \
aesni.c \
arc4.c \
asn1parse.c \
asn1write.c \
base64.c \
bignum.c \
blowfish.c \
camellia.c \
ccm.c \
certs.c \
chacha20.c \
chachapoly.c \
cipher.c \
cipher_wrap.c \
cmac.c \
ctr_drbg.c \
debug.c \
des.c \
dhm.c \
ecdh.c \
ecdsa.c \
ecjpake.c \
ecp.c \
ecp_curves.c \
entropy.c \
entropy_poll.c \
gcm.c \
havege.c \
hmac_drbg.c \
md2.c \
md4.c \
md5.c \
md.c \
md_wrap.c \
oid.c \
padlock.c \
pem.c \
pk.c \
pkcs11.c \
pkcs12.c \
pkcs5.c \
pkparse.c \
pk_wrap.c \
pkwrite.c \
platform.c \
platform_util.c \
poly1305.c \
ripemd160.c \
rsa.c \
rsa_internal.c \
sha1.c \
sha256.c \
sha512.c \
ssl_cache.c \
ssl_ciphersuites.c \
ssl_cli.c \
ssl_cookie.c \
ssl_srv.c \
ssl_ticket.c \
ssl_tls.c \
timing.c \
x509.c \
x509_create.c \
x509_crl.c \
x509_crt.c \
x509_csr.c \
x509write_crt.c \
x509write_csr.c \
xtea.c \
)
SRC_C += $(SRC_MBEDTLS) mbedtls/mbedtls_port.c mbedtls/crt_bundle.c
CFLAGS += \
-isystem $(TOP)/lib/mbedtls/include \
-DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"' \
$(BUILD)/x509_crt_bundle.S: $(TOP)/lib/certificates/nina-fw/data/roots.pem $(TOP)/tools/gen_crt_bundle.py
$(Q)$(PYTHON) $(TOP)/tools/gen_crt_bundle.py -i $< -o $@ --asm
OBJ_MBEDTLS := $(BUILD)/x509_crt_bundle.o
$(patsubst %.c,$(BUILD)/%.o,$(SRC_MBEDTLS))): CFLAGS += -Wno-suggest-attribute=format
else
OBJ_MBEDTLS :=
endif
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
$(addprefix common-hal/, $(SRC_COMMON_HAL))
@ -314,9 +401,9 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S_UPPER:.S=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
OBJ += $(BUILD)/boot2_padded_checksummed.o
OBJ += $(OBJ_CYW43)
OBJ += $(OBJ_CYW43) $(OBJ_MBEDTLS)
$(BUILD)/boot2_padded_checksummed.o: $(BUILD)/boot2_padded_checksummed.S
$(BUILD)/%.o: $(BUILD)/%.S
$(STEPECHO) "CC $<"
$(Q)$(CC) $(CFLAGS) -c -o $@ $<

View File

@ -11,7 +11,8 @@ EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ"
CIRCUITPY__EVE = 1
CIRCUITPY_CYW43 = 1
CIRCUITPY_SSL = 0
CIRCUITPY_SSL = 1
CIRCUITPY_SSL_MBEDTLS = 1
CIRCUITPY_HASHLIB = 0
CIRCUITPY_WEB_WORKFLOW = 0
CIRCUITPY_MDNS = 0
@ -19,3 +20,5 @@ CIRCUITPY_SOCKETPOOL = 1
CIRCUITPY_WIFI = 1
CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0
# Must be accompanied by a linker script change
CFLAGS += -DRESERVED_FLASH='(1792 * 1024)'

View File

@ -0,0 +1,63 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/ssl/SSLContext.h"
#include "shared-bindings/ssl/SSLSocket.h"
#include "shared-bindings/socketpool/SocketPool.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "mbedtls/crt_bundle.h"
void common_hal_ssl_sslcontext_construct(ssl_sslcontext_obj_t *self) {
common_hal_ssl_sslcontext_set_default_verify_paths(self);
}
void common_hal_ssl_sslcontext_load_verify_locations(ssl_sslcontext_obj_t *self,
const char *cadata) {
mp_raise_NotImplementedError(NULL);
// self->crt_bundle_attach = NULL;
// self->use_global_ca_store = false;
// self->cacert_buf = (const unsigned char *)cadata;
// self->cacert_bytes = strlen(cadata) + 1;
}
void common_hal_ssl_sslcontext_set_default_verify_paths(ssl_sslcontext_obj_t *self) {
self->crt_bundle_attach = crt_bundle_attach;
self->use_global_ca_store = true;
self->cacert_buf = NULL;
self->cacert_bytes = 0;
}
bool common_hal_ssl_sslcontext_get_check_hostname(ssl_sslcontext_obj_t *self) {
return self->check_name;
}
void common_hal_ssl_sslcontext_set_check_hostname(ssl_sslcontext_obj_t *self, bool value) {
self->check_name = value;
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
#include "mbedtls/ssl.h"
typedef struct {
mp_obj_base_t base;
bool check_name, use_global_ca_store;
const unsigned char *cacert_buf;
size_t cacert_bytes;
int (*crt_bundle_attach)(mbedtls_ssl_config *conf);
} ssl_sslcontext_obj_t;

View File

@ -0,0 +1,335 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Linaro Ltd.
* Copyright (c) 2019 Paul Sokolovsky
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/ssl/SSLSocket.h"
#include "shared-bindings/socketpool/Socket.h"
#include "shared-bindings/ssl/SSLContext.h"
#include "shared-bindings/socketpool/SocketPool.h"
#include "shared-bindings/socketpool/Socket.h"
#include "shared/runtime/interrupt_char.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "supervisor/shared/tick.h"
#if defined(MBEDTLS_ERROR_C)
#include "../../lib/mbedtls_errors/mp_mbedtls_errors.c"
#endif
#ifdef MBEDTLS_DEBUG_C
#include "mbedtls/debug.h"
STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
(void)ctx;
(void)level;
mp_printf(&mp_plat_print, "DBG:%s:%04d: %s\n", file, line, str);
}
#define DEBUG(fmt, ...) mp_printf(&mp_plat_print, "DBG:%s:%04d: " fmt "\n", __FILE__, __LINE__,##__VA_ARGS__)
#else
#define DEBUG(...) do {} while (0)
#endif
STATIC NORETURN void mbedtls_raise_error(int err) {
// _mbedtls_ssl_send and _mbedtls_ssl_recv (below) turn positive error codes from the
// underlying socket into negative codes to pass them through mbedtls. Here we turn them
// positive again so they get interpreted as the OSError they really are. The
// cut-off of -256 is a bit hacky, sigh.
if (err < 0 && err > -256) {
mp_raise_OSError(-err);
}
#if defined(MBEDTLS_ERROR_C)
// Including mbedtls_strerror takes about 1.5KB due to the error strings.
// MBEDTLS_ERROR_C is the define used by mbedtls to conditionally include mbedtls_strerror.
// It is set/unset in the MBEDTLS_CONFIG_FILE which is defined in the Makefile.
// Try to allocate memory for the message
#define ERR_STR_MAX 80 // mbedtls_strerror truncates if it doesn't fit
mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t);
byte *o_str_buf = m_new_maybe(byte, ERR_STR_MAX);
if (o_str == NULL || o_str_buf == NULL) {
mp_raise_OSError(err);
}
// print the error message into the allocated buffer
mbedtls_strerror(err, (char *)o_str_buf, ERR_STR_MAX);
size_t len = strlen((char *)o_str_buf);
// Put the exception object together
o_str->base.type = &mp_type_str;
o_str->data = o_str_buf;
o_str->len = len;
o_str->hash = qstr_compute_hash(o_str->data, o_str->len);
// raise
mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(err), MP_OBJ_FROM_PTR(o_str)};
nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args));
#else
// mbedtls is compiled without error strings so we simply return the err number
mp_raise_OSError(err); // err is typically a large negative number
#endif
}
STATIC int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
mp_obj_t sock = *(mp_obj_t *)ctx;
// mp_uint_t out_sz = sock_stream->write(sock, buf, len, &err);
mp_int_t out_sz = common_hal_socketpool_socket_send(sock, buf, len);
DEBUG("socket_send() -> %d", out_sz);
if (out_sz < 0) {
int err = -out_sz;
DEBUG("sock_stream->write() -> %d nonblocking? %d", out_sz, mp_is_nonblocking_error(err));
if (mp_is_nonblocking_error(err)) {
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
return -err; // convert an MP_ERRNO to something mbedtls passes through as error
} else {
return out_sz;
}
}
// _mbedtls_ssl_recv is called by mbedtls to receive bytes from the underlying socket
STATIC int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
mp_obj_t sock = *(mp_obj_t *)ctx;
mp_int_t out_sz = common_hal_socketpool_socket_recv_into(sock, buf, len);
DEBUG("socket_recv() -> %d", out_sz);
if (out_sz < 0) {
int err = -out_sz;
if (mp_is_nonblocking_error(err)) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
return -err;
} else {
return out_sz;
}
}
ssl_sslsocket_obj_t *common_hal_ssl_sslcontext_wrap_socket(ssl_sslcontext_obj_t *self,
socketpool_socket_obj_t *socket, bool server_side, const char *server_hostname) {
if (socket->type != SOCKETPOOL_SOCK_STREAM) {
mp_raise_RuntimeError(translate("Invalid socket for TLS"));
}
ssl_sslsocket_obj_t *o = m_new_obj_with_finaliser(ssl_sslsocket_obj_t);
o->base.type = &ssl_sslsocket_type;
o->ssl_context = self;
o->sock = socket;
mbedtls_ssl_init(&o->ssl);
mbedtls_ssl_config_init(&o->conf);
mbedtls_x509_crt_init(&o->cacert);
mbedtls_x509_crt_init(&o->cert);
mbedtls_pk_init(&o->pkey);
mbedtls_ctr_drbg_init(&o->ctr_drbg);
#ifdef MBEDTLS_DEBUG_C
// Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose
mbedtls_debug_set_threshold(4);
#endif
mbedtls_entropy_init(&o->entropy);
const byte seed[] = "upy";
int ret = mbedtls_ctr_drbg_seed(&o->ctr_drbg, mbedtls_entropy_func, &o->entropy, seed, sizeof(seed));
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_ssl_config_defaults(&o->conf,
server_side ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT);
if (ret != 0) {
goto cleanup;
}
if (self->crt_bundle_attach != NULL) {
mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
self->crt_bundle_attach(&o->conf);
// } else if(self->cacert_buf && self->cacert_bytes) { // TODO: user bundle
} else {
mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE);
}
mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg);
#ifdef MBEDTLS_DEBUG_C
mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL);
#endif
ret = mbedtls_ssl_setup(&o->ssl, &o->conf);
if (ret != 0) {
goto cleanup;
}
if (server_hostname != NULL) {
ret = mbedtls_ssl_set_hostname(&o->ssl, server_hostname);
if (ret != 0) {
goto cleanup;
}
}
mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
return o;
cleanup:
mbedtls_pk_free(&o->pkey);
mbedtls_x509_crt_free(&o->cert);
mbedtls_x509_crt_free(&o->cacert);
mbedtls_ssl_free(&o->ssl);
mbedtls_ssl_config_free(&o->conf);
mbedtls_ctr_drbg_free(&o->ctr_drbg);
mbedtls_entropy_free(&o->entropy);
if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) {
mp_raise_OSError(MP_ENOMEM);
} else if (ret == MBEDTLS_ERR_PK_BAD_INPUT_DATA) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid key"));
} else if (ret == MBEDTLS_ERR_X509_BAD_INPUT_DATA) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid cert"));
} else {
mbedtls_raise_error(ret);
}
}
mp_uint_t common_hal_ssl_sslsocket_recv_into(ssl_sslsocket_obj_t *self, uint8_t *buf, uint32_t len) {
int ret = mbedtls_ssl_read(&self->ssl, buf, len);
DEBUG("recv_into mbedtls_ssl_read() -> %d\n", ret);
if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
DEBUG("returning %d\n", 0);
// end of stream
return 0;
}
if (ret >= 0) {
DEBUG("returning %d\n", ret);
return ret;
}
if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
ret = MP_EWOULDBLOCK;
} else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
// If handshake is not finished, read attempt may end up in protocol
// wanting to write next handshake message. The same may happen with
// renegotation.
ret = MP_EWOULDBLOCK;
}
DEBUG("returning [error case] %d\n", -ret);
return -ret;
}
mp_uint_t common_hal_ssl_sslsocket_send(ssl_sslsocket_obj_t *self, const uint8_t *buf, uint32_t len) {
int ret = mbedtls_ssl_write(&self->ssl, buf, len);
DEBUG("send mbedtls_ssl_write() -> %d\n", ret);
if (ret >= 0) {
DEBUG("returning %d\n", ret);
return ret;
}
if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
ret = MP_EWOULDBLOCK;
} else if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
// If handshake is not finished, write attempt may end up in protocol
// wanting to read next handshake message. The same may happen with
// renegotation.
ret = MP_EWOULDBLOCK;
}
DEBUG("returning [error case] %d\n", -ret);
return -ret;
}
bool common_hal_ssl_sslsocket_bind(ssl_sslsocket_obj_t *self, const char *host, size_t hostlen, uint32_t port) {
mp_raise_NotImplementedError(NULL);
}
void common_hal_ssl_sslsocket_close(ssl_sslsocket_obj_t *self) {
self->closed = true;
common_hal_socketpool_socket_close(self->sock);
mbedtls_pk_free(&self->pkey);
mbedtls_x509_crt_free(&self->cert);
mbedtls_x509_crt_free(&self->cacert);
mbedtls_ssl_free(&self->ssl);
mbedtls_ssl_config_free(&self->conf);
mbedtls_ctr_drbg_free(&self->ctr_drbg);
mbedtls_entropy_free(&self->entropy);
}
void common_hal_ssl_sslsocket_connect(ssl_sslsocket_obj_t *self, const char *host, size_t hostlen, uint32_t port) {
common_hal_socketpool_socket_connect(self->sock, host, hostlen, port);
int ret;
while ((ret = mbedtls_ssl_handshake(&self->ssl)) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
goto cleanup;
}
RUN_BACKGROUND_TASKS;
if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) {
mp_handle_pending(true);
}
mp_hal_delay_ms(1);
}
return;
cleanup:
self->closed = true;
mbedtls_pk_free(&self->pkey);
mbedtls_x509_crt_free(&self->cert);
mbedtls_x509_crt_free(&self->cacert);
mbedtls_ssl_free(&self->ssl);
mbedtls_ssl_config_free(&self->conf);
mbedtls_ctr_drbg_free(&self->ctr_drbg);
mbedtls_entropy_free(&self->entropy);
if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) {
mp_raise_OSError(MP_ENOMEM);
} else if (ret == MBEDTLS_ERR_PK_BAD_INPUT_DATA) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid key"));
} else if (ret == MBEDTLS_ERR_X509_BAD_INPUT_DATA) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid cert"));
} else {
mbedtls_raise_error(ret);
}
}
bool common_hal_ssl_sslsocket_get_closed(ssl_sslsocket_obj_t *self) {
return self->closed;
}
bool common_hal_ssl_sslsocket_get_connected(ssl_sslsocket_obj_t *self) {
return !self->closed;
}
bool common_hal_ssl_sslsocket_listen(ssl_sslsocket_obj_t *self, int backlog) {
mp_raise_NotImplementedError(NULL);
}
ssl_sslsocket_obj_t *common_hal_ssl_sslsocket_accept(ssl_sslsocket_obj_t *self, uint8_t *ip, uint32_t *port) {
mp_raise_NotImplementedError(NULL);
}
void common_hal_ssl_sslsocket_settimeout(ssl_sslsocket_obj_t *self, uint32_t timeout_ms) {
self->sock->timeout = timeout_ms;
}

View File

@ -0,0 +1,54 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Lucian Copeland for Adafruit Industries
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
#include "py/obj.h"
#include "common-hal/ssl/SSLContext.h"
#include "common-hal/socketpool/Socket.h"
#include "mbedtls/platform.h"
#include "mbedtls/ssl.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/pk.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
typedef struct {
mp_obj_base_t base;
socketpool_socket_obj_t *sock;
ssl_sslcontext_obj_t *ssl_context;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt cacert;
mbedtls_x509_crt cert;
mbedtls_pk_context pkey;
bool closed;
} ssl_sslsocket_obj_t;

View File

@ -0,0 +1,39 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "common-hal/ssl/__init__.h"
#include "shared-bindings/ssl/__init__.h"
#include "shared-bindings/ssl/SSLContext.h"
#include "mbedtls/crt_bundle.h"
void common_hal_ssl_create_default_context(ssl_sslcontext_obj_t *self) {
common_hal_ssl_sslcontext_construct(self);
}
void ssl_reset(void) {
crt_bundle_detach(NULL);
}

View File

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#pragma once
void ssl_reset(void);

View File

@ -0,0 +1,255 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
// Copyright 2022 Jeff Epler for Adafruit Industries
//
// 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.
#define BUNDLE_MAX_CERTS (200)
#include <string.h>
#include "py/runtime.h"
#include "py/mperrno.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/crt_bundle.h"
#define BUNDLE_HEADER_OFFSET 2
#define CRT_HEADER_OFFSET 4
/* a dummy certificate so that
* cacert_ptr passes non-NULL check during handshake */
static mbedtls_x509_crt s_dummy_crt;
#define TAG "x509-crt-bundle"
#define LOGE(tag, fmt, ...) mp_printf(&mp_plat_print, tag ":" fmt "\n",##__VA_ARGS__)
#if 0
#define LOGI(tag, fmt, ...) mp_printf(&mp_plat_print, tag ":" fmt "\n",##__VA_ARGS__)
#define LOGD(tag, fmt, ...) mp_printf(&mp_plat_print, tag ":" fmt "\n",##__VA_ARGS__)
#else
#define LOGI(tag, fmt, ...) do {} while (0)
#define LOGD(tag, fmt, ...) do {} while (0)
#endif
extern const uint8_t x509_crt_imported_bundle_bin_start[] asm ("_binary_x509_crt_bundle_start");
extern const uint8_t x509_crt_imported_bundle_bin_end[] asm ("_binary_x509_crt_bundle_end");
typedef struct crt_bundle_t {
const uint8_t **crts;
uint16_t num_certs;
size_t x509_crt_bundle_len;
} crt_bundle_t;
static crt_bundle_t s_crt_bundle;
static int crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_key_buf, size_t pub_key_len);
static int crt_check_signature(mbedtls_x509_crt *child, const uint8_t *pub_key_buf, size_t pub_key_len) {
int ret = 0;
mbedtls_x509_crt parent;
const mbedtls_md_info_t *md_info;
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
mbedtls_x509_crt_init(&parent);
if ((ret = mbedtls_pk_parse_public_key(&parent.pk, pub_key_buf, pub_key_len)) != 0) {
LOGE(TAG, "PK parse failed with error %X", ret);
goto cleanup;
}
// Fast check to avoid expensive computations when not necessary
if (!mbedtls_pk_can_do(&parent.pk, child->sig_pk)) {
LOGE(TAG, "Simple compare failed");
ret = -1;
goto cleanup;
}
md_info = mbedtls_md_info_from_type(child->sig_md);
if ((ret = mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash)) != 0) {
LOGE(TAG, "Internal mbedTLS error %X", ret);
goto cleanup;
}
if ((ret = mbedtls_pk_verify_ext(child->sig_pk, child->sig_opts, &parent.pk,
child->sig_md, hash, mbedtls_md_get_size(md_info),
child->sig.p, child->sig.len)) != 0) {
LOGE(TAG, "PK verify failed with error %X", ret);
goto cleanup;
}
cleanup:
mbedtls_x509_crt_free(&parent);
return ret;
}
/* This callback is called for every certificate in the chain. If the chain
* is proper each intermediate certificate is validated through its parent
* in the x509_crt_verify_chain() function. So this callback should
* only verify the first untrusted link in the chain is signed by the
* root certificate in the trusted bundle
*/
static int crt_verify_callback(void *buf, mbedtls_x509_crt *crt, int depth, uint32_t *flags) {
mbedtls_x509_crt *child = crt;
/* It's OK for a trusted cert to have a weak signature hash alg.
as we already trust this certificate */
uint32_t flags_filtered = *flags & ~(MBEDTLS_X509_BADCERT_BAD_MD);
if (flags_filtered != MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
return 0;
}
if (s_crt_bundle.crts == NULL) {
LOGE(TAG, "No certificates in bundle");
return MBEDTLS_ERR_X509_FATAL_ERROR;
}
LOGD(TAG, "%d certificates in bundle", s_crt_bundle.num_certs);
size_t name_len = 0;
const uint8_t *crt_name;
bool crt_found = false;
int start = 0;
int end = s_crt_bundle.num_certs - 1;
int middle = (end - start) / 2;
/* Look for the certificate using binary search on subject name */
while (start <= end) {
name_len = s_crt_bundle.crts[middle][0] << 8 | s_crt_bundle.crts[middle][1];
crt_name = s_crt_bundle.crts[middle] + CRT_HEADER_OFFSET;
int cmp_res = memcmp(child->issuer_raw.p, crt_name, name_len);
if (cmp_res == 0) {
crt_found = true;
break;
} else if (cmp_res < 0) {
end = middle - 1;
} else {
start = middle + 1;
}
middle = (start + end) / 2;
}
int ret = MBEDTLS_ERR_X509_FATAL_ERROR;
if (crt_found) {
size_t key_len = s_crt_bundle.crts[middle][2] << 8 | s_crt_bundle.crts[middle][3];
ret = crt_check_signature(child, s_crt_bundle.crts[middle] + CRT_HEADER_OFFSET + name_len, key_len);
}
if (ret == 0) {
LOGI(TAG, "Certificate validated");
*flags = 0;
return 0;
}
LOGE(TAG, "Failed to verify certificate");
return MBEDTLS_ERR_X509_FATAL_ERROR;
}
/* Initialize the bundle into an array so we can do binary search for certs,
the bundle generated by the python utility is already presorted by subject name
*/
static err_t crt_bundle_init(const uint8_t *x509_bundle, size_t bundle_size) {
if (bundle_size < BUNDLE_HEADER_OFFSET + CRT_HEADER_OFFSET) {
LOGE(TAG, "Invalid certificate bundle");
return -MP_EINVAL;
}
uint16_t num_certs = (x509_bundle[0] << 8) | x509_bundle[1];
if (num_certs > BUNDLE_MAX_CERTS) {
// No. of certs in the certificate bundle = %d exceeds\n"
// Max allowed certificates in the certificate bundle = %d\n"
// Please update the menuconfig option with appropriate value", num_certs, BUNDLE_MAX_CERTS
return -MP_E2BIG;
}
const uint8_t **crts = m_tracked_calloc(num_certs, sizeof(x509_bundle));
if (crts == NULL) {
LOGE(TAG, "Unable to allocate memory for bundle");
return -MP_ENOMEM;
}
const uint8_t *cur_crt;
/* This is the maximum region that is allowed to access */
const uint8_t *bundle_end = x509_bundle + bundle_size;
cur_crt = x509_bundle + BUNDLE_HEADER_OFFSET;
for (int i = 0; i < num_certs; i++) {
crts[i] = cur_crt;
if (cur_crt + CRT_HEADER_OFFSET > bundle_end) {
LOGE(TAG, "Invalid certificate bundle");
m_tracked_free(crts);
return -MP_EINVAL;
}
size_t name_len = cur_crt[0] << 8 | cur_crt[1];
size_t key_len = cur_crt[2] << 8 | cur_crt[3];
cur_crt = cur_crt + CRT_HEADER_OFFSET + name_len + key_len;
}
if (cur_crt > bundle_end) {
LOGE(TAG, "Invalid certificate bundle");
m_tracked_free(crts);
return -MP_EINVAL;
}
/* The previous crt bundle is only updated when initialization of the
* current crt_bundle is successful */
/* Free previous crt_bundle */
m_tracked_free(s_crt_bundle.crts);
s_crt_bundle.num_certs = num_certs;
s_crt_bundle.crts = crts;
return 0;
}
int crt_bundle_attach(mbedtls_ssl_config *ssl_conf) {
int ret = 0;
// If no bundle has been set by the user then use the bundle embedded in the binary
if (s_crt_bundle.crts == NULL) {
ret = crt_bundle_init(x509_crt_imported_bundle_bin_start, x509_crt_imported_bundle_bin_end - x509_crt_imported_bundle_bin_start);
}
if (ret != 0) {
return ret;
}
if (ssl_conf) {
/* point to a dummy certificate
* This is only required so that the
* cacert_ptr passes non-NULL check during handshake
*/
mbedtls_x509_crt_init(&s_dummy_crt);
mbedtls_ssl_conf_ca_chain(ssl_conf, &s_dummy_crt, NULL);
mbedtls_ssl_conf_verify(ssl_conf, crt_verify_callback, NULL);
}
return ret;
}
void crt_bundle_detach(mbedtls_ssl_config *conf) {
m_tracked_free(s_crt_bundle.crts);
s_crt_bundle.crts = NULL;
if (conf) {
mbedtls_ssl_conf_verify(conf, NULL, NULL);
}
}
int crt_bundle_set(const uint8_t *x509_bundle, size_t bundle_size) {
return crt_bundle_init(x509_bundle, bundle_size);
}

View File

@ -0,0 +1,21 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
// Copyright 2022 Jeff Epler for Adafruit Industries
//
// 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.
#pragma once
#include "mbedtls/ssl.h"
int crt_bundle_attach(mbedtls_ssl_config *conf);
void crt_bundle_detach(mbedtls_ssl_config *conf);
int crt_bundle_set(const uint8_t *x509_bundle, size_t bundle_size);

View File

@ -0,0 +1,126 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018-2019 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H
#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H
// If you want to debug MBEDTLS uncomment the following and
// Pass 3 to mbedtls_debug_set_threshold in socket_new
// #define MBEDTLS_DEBUG_C
// Set mbedtls configuration
#define MBEDTLS_PLATFORM_MEMORY
#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
#define MBEDTLS_DEPRECATED_REMOVED
#define MBEDTLS_ENTROPY_HARDWARE_ALT
#define MBEDTLS_AES_ROM_TABLES
#define MBEDTLS_CIPHER_MODE_CBC
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
#define MBEDTLS_ECP_NIST_OPTIM
#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
#define MBEDTLS_NO_PLATFORM_ENTROPY
#define MBEDTLS_PKCS1_V15
#define MBEDTLS_SHA256_SMALLER
#define MBEDTLS_SSL_PROTO_TLS1
#define MBEDTLS_SSL_PROTO_TLS1_1
#define MBEDTLS_SSL_PROTO_TLS1_2
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
// Use a smaller output buffer to reduce size of SSL context
#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384)
#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN)
#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096)
// Enable mbedtls modules
#define MBEDTLS_AES_C
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_ASN1_WRITE_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_CIPHER_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECDSA_C
#define MBEDTLS_ECP_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_ERROR_C
#define MBEDTLS_GCM_C
#define MBEDTLS_MD_C
#define MBEDTLS_MD5_C
#define MBEDTLS_OID_C
#define MBEDTLS_PKCS5_C
#define MBEDTLS_PK_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_PLATFORM_C
#define MBEDTLS_RSA_C
#define MBEDTLS_SHA1_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_SHA512_C
#define MBEDTLS_SSL_CLI_C
#define MBEDTLS_SSL_SRV_C
#define MBEDTLS_SSL_TLS_C
#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
#define MBEDTLS_X509_CRT_PARSE_C
#define MBEDTLS_X509_USE_C
#define MBEDTLS_HAVE_TIME
#define MBEDTLS_DHM_C // needed by DHE_PSK
#undef MBEDTLS_HAVE_TIME_DATE
// Memory allocation hooks
#include <stdlib.h>
#include <stdio.h>
void *m_tracked_calloc(size_t nmemb, size_t size);
void m_tracked_free(void *ptr);
#define MBEDTLS_PLATFORM_STD_CALLOC m_tracked_calloc
#define MBEDTLS_PLATFORM_STD_FREE m_tracked_free
#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
// Time hook
#include <time.h>
time_t rp2_rtctime_seconds(time_t *timer);
#define MBEDTLS_PLATFORM_TIME_MACRO rp2_rtctime_seconds
#include "mbedtls/check_config.h"
#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */

View File

@ -0,0 +1,51 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <py/mpconfig.h>
#if CIRCUITPY_SSL_MBEDTLS
#include "mbedtls_config.h"
#include "mbedtls/entropy_poll.h"
#include "hardware/rtc.h"
#include "shared/timeutils/timeutils.h"
#include "shared-bindings/os/__init__.h"
extern uint8_t rosc_random_u8(size_t cycles);
int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) {
*olen = len;
common_hal_os_urandom(data, len);
return 0;
}
time_t rp2_rtctime_seconds(time_t *timer) {
datetime_t t;
rtc_get_datetime(&t);
return timeutils_seconds_since_epoch(t.year, t.month, t.day, t.hour, t.min, t.sec);
}
#endif

View File

@ -46,7 +46,13 @@
#include "src/rp2_common/hardware_flash/include/hardware/flash.h"
#include "src/common/pico_binary_info/include/pico/binary_info.h"
#if !defined(RESERVED_FLASH)
#define RESERVED_FLASH (1 * 1024 * 1024)
#endif
#if !defined(TOTAL_FLASH_MINIMUM)
#define TOTAL_FLASH_MINIMUM (2 * 1024 * 1024)
#endif
// TODO: Split the caching out of supervisor/shared/external_flash so we can use it.
#define SECTOR_SIZE 4096
@ -60,7 +66,7 @@ void supervisor_flash_init(void) {
BINARY_INFO_MAKE_TAG('C', 'P'),
"CircuitPython",
RESERVED_FLASH,
(1 * 1024 * 1024), // This is a minimum. We can't set it dynamically.
TOTAL_FLASH_MINIMUM - RESERVED_FLASH, // This is a minimum. We can't set it dynamically.
NULL,
BINARY_INFO_BLOCK_DEV_FLAG_READ |
BINARY_INFO_BLOCK_DEV_FLAG_WRITE |

View File

@ -41,6 +41,10 @@
#include "shared-bindings/rtc/__init__.h"
#include "shared-bindings/pwmio/PWMOut.h"
#if CIRCUITPY_SSL
#include "common-hal/ssl/__init__.h"
#endif
#if CIRCUITPY_WIFI
#include "common-hal/wifi/__init__.h"
#endif
@ -179,6 +183,10 @@ void reset_port(void) {
audio_dma_reset();
#endif
#if CIRCUITPY_SSL
ssl_reset();
#endif
#if CIRCUITPY_WIFI
wifi_reset();
#endif

View File

@ -73,6 +73,7 @@ extern void common_hal_mcu_enable_interrupts(void);
#define MICROPY_ENABLE_DOC_STRING (0)
#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_TRACKED_ALLOC (CIRCUITPY_SSL_MBEDTLS)
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_EPOCH_IS_1970 (1)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL)

View File

@ -388,6 +388,10 @@ CFLAGS += -DCIRCUITPY_SOCKETPOOL=$(CIRCUITPY_SOCKETPOOL)
CIRCUITPY_SSL ?= $(CIRCUITPY_WIFI)
CFLAGS += -DCIRCUITPY_SSL=$(CIRCUITPY_SSL)
CIRCUITPY_SSL_MBEDTLS ?= 0
CFLAGS += -DCIRCUITPY_SSL_MBEDTLS=$(CIRCUITPY_SSL_MBEDTLS)
# Currently always off.
CIRCUITPY_STAGE ?= 0
CFLAGS += -DCIRCUITPY_STAGE=$(CIRCUITPY_STAGE)

View File

@ -207,6 +207,99 @@ void m_free(void *ptr) {
#endif
}
#if MICROPY_TRACKED_ALLOC
#define MICROPY_TRACKED_ALLOC_STORE_SIZE (!MICROPY_ENABLE_GC)
typedef struct _m_tracked_node_t {
struct _m_tracked_node_t *prev;
struct _m_tracked_node_t *next;
#if MICROPY_TRACKED_ALLOC_STORE_SIZE
uintptr_t size;
#endif
uint8_t data[];
} m_tracked_node_t;
#if MICROPY_DEBUG_VERBOSE
STATIC size_t m_tracked_count_links(size_t *nb) {
m_tracked_node_t *node = MP_STATE_VM(m_tracked_head);
size_t n = 0;
*nb = 0;
while (node != NULL) {
++n;
#if MICROPY_TRACKED_ALLOC_STORE_SIZE
*nb += node->size;
#else
*nb += gc_nbytes(node);
#endif
node = node->next;
}
return n;
}
#endif
void *m_tracked_calloc(size_t nmemb, size_t size) {
m_tracked_node_t *node = m_malloc_maybe(sizeof(m_tracked_node_t) + nmemb * size, false);
if (node == NULL) {
return NULL;
}
#if MICROPY_DEBUG_VERBOSE
size_t nb;
size_t n = m_tracked_count_links(&nb);
DEBUG_printf("m_tracked_calloc(%u, %u) -> (%u;%u) %p\n", (int)nmemb, (int)size, (int)n, (int)nb, node);
#endif
if (MP_STATE_VM(m_tracked_head) != NULL) {
MP_STATE_VM(m_tracked_head)->prev = node;
}
node->prev = NULL;
node->next = MP_STATE_VM(m_tracked_head);
MP_STATE_VM(m_tracked_head) = node;
#if MICROPY_TRACKED_ALLOC_STORE_SIZE
node->size = nmemb * size;
#endif
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(&node->data[0], 0, nmemb * size);
#endif
return &node->data[0];
}
void m_tracked_free(void *ptr_in) {
if (ptr_in == NULL) {
return;
}
m_tracked_node_t *node = (m_tracked_node_t *)((uint8_t *)ptr_in - sizeof(m_tracked_node_t));
#if MICROPY_DEBUG_VERBOSE
size_t data_bytes;
#if MICROPY_TRACKED_ALLOC_STORE_SIZE
data_bytes = node->size;
#else
data_bytes = gc_nbytes(node);
#endif
size_t nb;
size_t n = m_tracked_count_links(&nb);
DEBUG_printf("m_tracked_free(%p, [%p, %p], nbytes=%u, links=%u;%u)\n", node, node->prev, node->next, (int)data_bytes, (int)n, (int)nb);
#endif
if (node->next != NULL) {
node->next->prev = node->prev;
}
if (node->prev != NULL) {
node->prev->next = node->next;
} else {
MP_STATE_VM(m_tracked_head) = node->next;
}
m_free(node
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
#if MICROPY_TRACKED_ALLOC_STORE_SIZE
, node->size
#else
, gc_nbytes(node)
#endif
#endif
);
}
#endif
#if MICROPY_MEM_STATS
size_t m_get_total_bytes_allocated(void) {
return MP_STATE_MEM(total_bytes_allocated);

View File

@ -112,6 +112,13 @@ void m_free(void *ptr);
#endif
NORETURN void m_malloc_fail(size_t num_bytes);
#if MICROPY_TRACKED_ALLOC
// These alloc/free functions track the pointers in a linked list so the GC does not reclaim
// them. They can be used by code that requires traditional C malloc/free semantics.
void *m_tracked_calloc(size_t nmemb, size_t size);
void m_tracked_free(void *ptr_in);
#endif
#if MICROPY_MEM_STATS
size_t m_get_total_bytes_allocated(void);
size_t m_get_current_bytes_allocated(void);

View File

@ -119,6 +119,10 @@ typedef struct _mp_state_vm_t {
qstr_pool_t *last_pool;
#if MICROPY_TRACKED_ALLOC
struct _m_tracked_node_t *m_tracked_head;
#endif
// non-heap memory for creating a traceback if we can't allocate RAM
mp_obj_traceback_t mp_emergency_traceback_obj;

View File

@ -1,12 +1,10 @@
# For nvm.toml
cascadetoml
jinja2
# Undo this pin when click and typer are again compatible.
typer==0.4.0
typer
sh
# Undo this pin when click and typer are again compatible.
click==8.0.4
click
cpp-coveralls
requests
requests-cache
@ -28,6 +26,9 @@ pyelftools
# for stubs and annotations
adafruit-circuitpython-typing
# for mbedtls certificate store
cryptography
# for web workflow minify
minify_html
jsmin

View File

@ -38,7 +38,7 @@ void common_hal_ssl_sslsocket_connect(ssl_sslsocket_obj_t *self, const char *hos
bool common_hal_ssl_sslsocket_get_closed(ssl_sslsocket_obj_t *self);
bool common_hal_ssl_sslsocket_get_connected(ssl_sslsocket_obj_t *self);
bool common_hal_ssl_sslsocket_listen(ssl_sslsocket_obj_t *self, int backlog);
mp_uint_t common_hal_ssl_sslsocket_recv_into(ssl_sslsocket_obj_t *self, const uint8_t *buf, uint32_t len);
mp_uint_t common_hal_ssl_sslsocket_recv_into(ssl_sslsocket_obj_t *self, uint8_t *buf, uint32_t len);
mp_uint_t common_hal_ssl_sslsocket_send(ssl_sslsocket_obj_t *self, const uint8_t *buf, uint32_t len);
void common_hal_ssl_sslsocket_settimeout(ssl_sslsocket_obj_t *self, uint32_t timeout_ms);

View File

@ -25,14 +25,22 @@ port_deps = {
],
"broadcom": ["extmod/ulab/", "lib/tinyusb/"],
"cxd56": ["extmod/ulab/", "lib/tinyusb/"],
"espressif": ["extmod/ulab/", "lib/tinyusb/", "lib/protomatter/", "lib/quirc/"],
"espressif": [
"extmod/ulab/",
"lib/certificates/nina-fw/",
"lib/protomatter/",
"lib/quirc/",
"lib/tinyusb/",
],
"litex": ["extmod/ulab/", "lib/tinyusb/"],
"mimxrt10xx": ["extmod/ulab/", "lib/tinyusb/", "data/nvm.toml/"],
"nrf": ["extmod/ulab/", "lib/mp3/", "lib/protomatter/", "lib/tinyusb/", "data/nvm.toml/"],
"raspberrypi": [
"extmod/ulab/",
"lib/adafruit_floppy/",
"lib/mbedtls/",
"lib/mp3/",
"lib/certificates/nina-fw/",
"lib/protomatter/",
"lib/quirc/",
"lib/tinyusb/",

298
tools/gen_crt_bundle.py Executable file
View File

@ -0,0 +1,298 @@
#!/usr/bin/env python
#
# ESP32 x509 certificate bundle generation utility
#
# Converts PEM and DER certificates to a custom bundle format which stores just the
# subject name and public key to reduce space
#
# The bundle will have the format: number of certificates; crt 1 subject name length; crt 1 public key length;
# crt 1 subject name; crt 1 public key; crt 2...
#
# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
#
# 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.
from __future__ import with_statement
import argparse
import csv
import os
import re
import struct
import sys
import textwrap
from io import open
try:
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
except ImportError:
print(
"The cryptography package is not installed."
"Please refer to the Get Started section of the ESP-IDF Programming Guide for "
"setting up the required packages."
)
raise
ca_bundle_bin_file = "x509_crt_bundle"
quiet = False
def status(msg):
"""Print status message to stderr"""
if not quiet:
critical(msg)
def critical(msg):
"""Print critical message to stderr"""
sys.stderr.write("gen_crt_bundle.py: ")
sys.stderr.write(msg)
sys.stderr.write("\n")
class CertificateBundle:
def __init__(self):
self.certificates = []
self.compressed_crts = []
if os.path.isfile(ca_bundle_bin_file):
os.remove(ca_bundle_bin_file)
def add_from_path(self, crts_path):
found = False
for file_path in os.listdir(crts_path):
found |= self.add_from_file(os.path.join(crts_path, file_path))
if found is False:
raise InputError("No valid x509 certificates found in %s" % crts_path)
def add_from_file(self, file_path):
try:
if file_path.endswith(".pem"):
status("Parsing certificates from %s" % file_path)
with open(file_path, "r", encoding="utf-8") as f:
crt_str = f.read()
self.add_from_pem(crt_str)
return True
elif file_path.endswith(".der"):
status("Parsing certificates from %s" % file_path)
with open(file_path, "rb") as f:
crt_str = f.read()
self.add_from_der(crt_str)
return True
except ValueError:
critical("Invalid certificate in %s" % file_path)
raise InputError("Invalid certificate")
return False
def add_from_pem(self, crt_str):
"""A single PEM file may have multiple certificates"""
crt = ""
count = 0
start = False
for strg in crt_str.splitlines(True):
if strg == "-----BEGIN CERTIFICATE-----\n" and start is False:
crt = ""
start = True
elif strg == "-----END CERTIFICATE-----\n" and start is True:
crt += strg + "\n"
start = False
self.certificates.append(
x509.load_pem_x509_certificate(crt.encode(), default_backend())
)
count += 1
if start is True:
crt += strg
if count == 0:
raise InputError("No certificate found")
status("Successfully added %d certificates" % count)
def add_from_der(self, crt_str):
self.certificates.append(x509.load_der_x509_certificate(crt_str, default_backend()))
status("Successfully added 1 certificate")
def create_bundle(self):
# Sort certificates in order to do binary search when looking up certificates
self.certificates = sorted(
self.certificates, key=lambda cert: cert.subject.public_bytes(default_backend())
)
bundle = struct.pack(">H", len(self.certificates))
for crt in self.certificates:
"""Read the public key as DER format"""
pub_key = crt.public_key()
pub_key_der = pub_key.public_bytes(
serialization.Encoding.DER, serialization.PublicFormat.SubjectPublicKeyInfo
)
""" Read the subject name as DER format """
sub_name_der = crt.subject.public_bytes(default_backend())
name_len = len(sub_name_der)
key_len = len(pub_key_der)
len_data = struct.pack(">HH", name_len, key_len)
bundle += len_data
bundle += sub_name_der
bundle += pub_key_der
return bundle
def add_with_filter(self, crts_path, filter_path):
filter_set = set()
with open(filter_path, "r", encoding="utf-8") as f:
csv_reader = csv.reader(f, delimiter=",")
# Skip header
next(csv_reader)
for row in csv_reader:
filter_set.add(row[1])
status("Parsing certificates from %s" % crts_path)
crt_str = []
with open(crts_path, "r", encoding="utf-8") as f:
crt_str = f.read()
# Split all certs into a list of (name, certificate string) tuples
pem_crts = re.findall(
r"(^.+?)\n(=+\n[\s\S]+?END CERTIFICATE-----\n)", crt_str, re.MULTILINE
)
filtered_crts = ""
for name, crt in pem_crts:
if name in filter_set:
filtered_crts += crt
self.add_from_pem(filtered_crts)
class InputError(RuntimeError):
def __init__(self, e):
super(InputError, self).__init__(e)
def main():
global quiet
parser = argparse.ArgumentParser(description="ESP-IDF x509 certificate bundle utility")
parser.add_argument(
"--quiet",
"-q",
help="Don't print non-critical status messages to stderr",
action="store_true",
)
parser.add_argument(
"--input",
"-i",
nargs="+",
required=True,
help="Paths to the custom certificate folders or files to parse, parses all .pem or .der files",
)
parser.add_argument(
"--filter",
"-f",
help="Path to CSV-file where the second columns contains the name of the certificates \
that should be included from cacrt_all.pem",
)
parser.add_argument(
"--asm",
"-S",
action="store_true",
default=False,
help="Output an asm file for use with gas, rather than a binary file",
)
parser.add_argument("--symbol", help="The symbol to define", default="x509_crt_bundle")
parser.add_argument("--output", "-o", help="The output file", default=None)
args = parser.parse_args()
quiet = args.quiet
bundle = CertificateBundle()
for path in args.input:
if os.path.isfile(path):
if os.path.basename(path) == "cacrt_all.pem" and args.filter:
bundle.add_with_filter(path, args.filter)
else:
bundle.add_from_file(path)
elif os.path.isdir(path):
bundle.add_from_path(path)
else:
raise InputError("Invalid --input=%s, is neither file nor folder" % args.input)
status("Successfully added %d certificates in total" % len(bundle.certificates))
crt_bundle = bundle.create_bundle()
if args.asm:
symbol = args.symbol
filename = args.output or (ca_bundle_bin_file + ".S")
with open(filename, "w") as f:
print(
textwrap.dedent(
f"""\
// Generated from {" ".join(args.input)} with {len(bundle.certificates)} certificates
.data
.section .rodata.embedded
.global {symbol}
.global _binary_{symbol}_start
.global _binary_{symbol}_end
{symbol}:
_binary_{symbol}_start:
"""
),
file=f,
)
for i in range(0, len(crt_bundle), 16):
chunk = crt_bundle[i : i + 16]
formatted = ", ".join(f"0x{byte:02x}" for byte in chunk)
print(f".byte {formatted}", file=f)
print(
textwrap.dedent(
f"""\
_binary_{symbol}_end:
{symbol}_length:
.word {len(crt_bundle)}
"""
),
file=f,
)
else:
filename = args.output or ca_bundle_bin_file
with open(filename, "wb") as f:
f.write(crt_bundle)
if __name__ == "__main__":
try:
main()
except InputError as e:
print(e)
sys.exit(2)