From 36383ca97b0db20d17518de070c5d05bbfe9ed3f Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 9 Nov 2020 10:00:01 +0100 Subject: [PATCH 1/3] TLSSocketWrapper: add method to retrieve certificates from filesystem --- connectivity/mbedtls/source/x509_crt.c | 4 +++ .../include/netsocket/TLSSocketWrapper.h | 12 ++++++++ .../netsocket/source/TLSSocketWrapper.cpp | 29 +++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/connectivity/mbedtls/source/x509_crt.c b/connectivity/mbedtls/source/x509_crt.c index 1e472303b16..c224a223bc5 100644 --- a/connectivity/mbedtls/source/x509_crt.c +++ b/connectivity/mbedtls/source/x509_crt.c @@ -80,7 +80,11 @@ #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) #include #include +#if defined(__MBED__) +#include +#else #include +#endif /* __MBED__ */ #endif /* !_WIN32 || EFIX64 || EFI32 */ #endif diff --git a/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h b/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h index 8f6af7f8ed6..cc120a07b72 100644 --- a/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h +++ b/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h @@ -116,6 +116,18 @@ class TLSSocketWrapper : public Socket { */ nsapi_error_t set_root_ca_cert(const char *root_ca_pem); + /** Sets the certification of Root CA. + * + * @note Must be called before calling connect() + * + * @param root_ca Path containing Root CA Certificate files in any Mbed TLS-supported format. + * @retval NSAPI_ERROR_OK on success. + * @retval NSAPI_ERROR_NO_MEMORY in case there is not enough memory to allocate certificate. + * @retval NSAPI_ERROR_PARAMETER in case the provided root_ca parameter failed parsing. + * + */ + nsapi_error_t set_root_ca_cert_path(const char *root_ca); + /** Sets client certificate, and client private key. * * @param client_cert Client certification in PEM or DER format. diff --git a/connectivity/netsocket/source/TLSSocketWrapper.cpp b/connectivity/netsocket/source/TLSSocketWrapper.cpp index 2ff807d2f6c..ec470c29170 100644 --- a/connectivity/netsocket/source/TLSSocketWrapper.cpp +++ b/connectivity/netsocket/source/TLSSocketWrapper.cpp @@ -121,6 +121,35 @@ nsapi_error_t TLSSocketWrapper::set_root_ca_cert(const char *root_ca_pem) return set_root_ca_cert(root_ca_pem, strlen(root_ca_pem) + 1); } +nsapi_error_t TLSSocketWrapper::set_root_ca_cert_path(const char *root_ca) +{ +#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) + return NSAPI_ERROR_UNSUPPORTED; +#else + mbedtls_x509_crt *crt; + + crt = new (std::nothrow) mbedtls_x509_crt; + if (!crt) { + return NSAPI_ERROR_NO_MEMORY; + } + + mbedtls_x509_crt_init(crt); + + /* Parse CA certification */ + int ret = mbedtls_x509_crt_parse_path(crt, root_ca); + if (ret < 0) { + print_mbedtls_error("mbedtls_x509_crt_parse", ret); + mbedtls_x509_crt_free(crt); + delete crt; + return NSAPI_ERROR_PARAMETER; + } + set_ca_chain(crt); + _cacert_allocated = true; + return NSAPI_ERROR_OK; +#endif +} + + nsapi_error_t TLSSocketWrapper::set_client_cert_key(const char *client_cert_pem, const char *client_private_key_pem) { return set_client_cert_key(client_cert_pem, strlen(client_cert_pem) + 1, client_private_key_pem, strlen(client_private_key_pem) + 1); From dd1adbdb13a530b5a06cbdbb5b8834b15ddcbcfc Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 9 Nov 2020 13:34:18 +0100 Subject: [PATCH 2/3] TLSSocketWrapper: Add unit test for set_root_ca_cert_path --- .../test/coap-service/unittest/stub/mbedtls_stub.c | 6 ++++++ .../netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp | 6 ++++++ .../UNITTESTS/netsocket/TLSSocketWrapper/tls_test_config.h | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/connectivity/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c b/connectivity/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c index 403ae9a57a5..3d098b19fa7 100644 --- a/connectivity/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c +++ b/connectivity/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c @@ -299,6 +299,12 @@ int mbedtls_x509_crt_parse(mbedtls_x509_crt *a, const unsigned char *b, size_t c return mbedtls_stub.expected_int; } +int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *a, const char *b) +{ + // means 5 valid certificates found + return 5; +} + int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crt *crt) { diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp index 056317d7aa0..4ab23334b2d 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp @@ -399,6 +399,12 @@ TEST_F(TestTLSSocketWrapper, set_root_ca_cert_invalid) EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_PARAMETER); } +TEST_F(TestTLSSocketWrapper, set_root_ca_cert_path) +{ + EXPECT_EQ(transport->open(&stack), NSAPI_ERROR_OK); + EXPECT_EQ(wrapper->set_root_ca_cert_path("/"), NSAPI_ERROR_OK); +} + TEST_F(TestTLSSocketWrapper, set_client_cert_key) { EXPECT_EQ(wrapper->get_own_cert(), static_cast(NULL)); diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/tls_test_config.h b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/tls_test_config.h index 4f9ce6b96c5..ad2d3d8d44c 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/tls_test_config.h +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/TLSSocketWrapper/tls_test_config.h @@ -19,6 +19,6 @@ #define UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ #define MBEDTLS_SSL_CLI_C - +#define MBEDTLS_FS_IO #endif /* UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ */ From 822bfb1ea0093cf9e67b41a56143766439be2e74 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 9 Nov 2020 13:52:28 +0100 Subject: [PATCH 3/3] TLSSocketWrapper: add test for certificates stored in filesystem --- .../tests/TESTS/netsocket/tls/main.cpp | 3 ++ .../tests/TESTS/netsocket/tls/tls_tests.h | 1 + .../tls/tlssocket_cert_in_filesystem.cpp | 51 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 connectivity/netsocket/tests/TESTS/netsocket/tls/tlssocket_cert_in_filesystem.cpp diff --git a/connectivity/netsocket/tests/TESTS/netsocket/tls/main.cpp b/connectivity/netsocket/tests/TESTS/netsocket/tls/main.cpp index 7d174b1a1ba..79ac7b69f99 100644 --- a/connectivity/netsocket/tests/TESTS/netsocket/tls/main.cpp +++ b/connectivity/netsocket/tests/TESTS/netsocket/tls/main.cpp @@ -231,6 +231,9 @@ Case cases[] = { Case("TLSSOCKET_SEND_REPEAT", TLSSOCKET_SEND_REPEAT), Case("TLSSOCKET_SEND_TIMEOUT", TLSSOCKET_SEND_TIMEOUT), Case("TLSSOCKET_NO_CERT", TLSSOCKET_NO_CERT), +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_FS_IO) + Case("TLSSOCKET_CERT_IN_FILESYSTEM", TLSSOCKET_CERT_IN_FILESYSTEM), +#endif // Temporarily removing this test, as TLS library consumes too much memory // and we see frequent memory allocation failures on architectures with less // RAM such as DISCO_L475VG_IOT1A and NUCLEO_F207ZG (both have 128 kB RAM) diff --git a/connectivity/netsocket/tests/TESTS/netsocket/tls/tls_tests.h b/connectivity/netsocket/tests/TESTS/netsocket/tls/tls_tests.h index f0905fa8ec3..57461683c8b 100644 --- a/connectivity/netsocket/tests/TESTS/netsocket/tls/tls_tests.h +++ b/connectivity/netsocket/tests/TESTS/netsocket/tls/tls_tests.h @@ -89,6 +89,7 @@ void TLSSOCKET_SEND_UNCONNECTED(); void TLSSOCKET_SEND_CLOSED(); void TLSSOCKET_SEND_REPEAT(); void TLSSOCKET_NO_CERT(); +void TLSSOCKET_CERT_IN_FILESYSTEM(); void TLSSOCKET_SIMULTANEOUS(); void TLSSOCKET_SEND_TIMEOUT(); diff --git a/connectivity/netsocket/tests/TESTS/netsocket/tls/tlssocket_cert_in_filesystem.cpp b/connectivity/netsocket/tests/TESTS/netsocket/tls/tlssocket_cert_in_filesystem.cpp new file mode 100644 index 00000000000..5cb9c8b07bf --- /dev/null +++ b/connectivity/netsocket/tests/TESTS/netsocket/tls/tlssocket_cert_in_filesystem.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020, Arduino SA, 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. + */ + +#include "mbed.h" +#include "TLSSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest.h" +#include "tls_tests.h" +#include "HeapBlockDevice.h" +#include "LittleFileSystem.h" + +using namespace utest::v1; + +void TLSSOCKET_CERT_IN_FILESYSTEM() +{ + SKIP_IF_TCP_UNSUPPORTED(); + + HeapBlockDevice bd(1024 * 10); + LittleFileSystem fs("fs"); + TEST_ASSERT_EQUAL(0, fs.format(&bd)); + TEST_ASSERT_EQUAL(0, fs.mount(&bd)); + + FILE *fp = fopen("/fs/certs.pem", "wb"); + int ret = fwrite(tls_global::cert, strlen(tls_global::cert), 1, fp); + fclose(fp); + + TLSSocket sock; + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(NetworkInterface::get_default_instance())); + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.set_root_ca_cert_path("/fs")); + + SocketAddress a; + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, NetworkInterface::get_default_instance()->gethostbyname(ECHO_SERVER_ADDR, &a)); + a.set_port(ECHO_SERVER_PORT_TLS); + TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.connect(a)); +} +