mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge branch 'dtls' of https://github.com/SeppoTakalo/mbed-os into dev_rollup
						commit
						95b1e75202
					
				| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited and affiliates
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKET_DTLS_TEST_CONFIG_H_
 | 
			
		||||
#define UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKET_DTLS_TEST_CONFIG_H_
 | 
			
		||||
 | 
			
		||||
#define MBEDTLS_SSL_CLI_C
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKET_DTLS_TEST_CONFIG_H_ */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,73 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited and affiliates
 | 
			
		||||
 * 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 "gtest/gtest.h"
 | 
			
		||||
#include "features/netsocket/DTLSSocket.h"
 | 
			
		||||
#include "NetworkStack_stub.h"
 | 
			
		||||
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Control the rtos EventFlags stub. See EventFlags_stub.cpp
 | 
			
		||||
extern std::list<uint32_t> eventFlagsStubNextRetval;
 | 
			
		||||
 | 
			
		||||
class TestDTLSSocket : public testing::Test {
 | 
			
		||||
public:
 | 
			
		||||
    unsigned int dataSize = 10;
 | 
			
		||||
    char dataBuf[10];
 | 
			
		||||
protected:
 | 
			
		||||
    DTLSSocket *socket;
 | 
			
		||||
    NetworkStackstub stack;
 | 
			
		||||
 | 
			
		||||
    virtual void SetUp()
 | 
			
		||||
    {
 | 
			
		||||
        socket = new DTLSSocket();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void TearDown()
 | 
			
		||||
    {
 | 
			
		||||
        stack.return_values.clear();
 | 
			
		||||
        eventFlagsStubNextRetval.clear();
 | 
			
		||||
        delete socket;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocket, constructor)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_TRUE(socket);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* connect */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocket, connect)
 | 
			
		||||
{
 | 
			
		||||
    socket->open((NetworkStack *)&stack);
 | 
			
		||||
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocket, connect_error)
 | 
			
		||||
{
 | 
			
		||||
    socket->open((NetworkStack *)&stack);
 | 
			
		||||
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_DNS_FAILURE;
 | 
			
		||||
    EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_DNS_FAILURE);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
 | 
			
		||||
####################
 | 
			
		||||
# UNIT TESTS
 | 
			
		||||
####################
 | 
			
		||||
 | 
			
		||||
set(unittest-sources
 | 
			
		||||
  ../features/netsocket/SocketAddress.cpp
 | 
			
		||||
  ../features/netsocket/NetworkStack.cpp
 | 
			
		||||
  ../features/netsocket/InternetSocket.cpp
 | 
			
		||||
  ../features/netsocket/UDPSocket.cpp
 | 
			
		||||
  ../features/netsocket/DTLSSocket.cpp
 | 
			
		||||
  ../features/netsocket/DTLSSocketWrapper.cpp
 | 
			
		||||
  ../features/netsocket/TLSSocketWrapper.cpp
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(unittest-test-sources
 | 
			
		||||
  features/netsocket/DTLSSocket/test_DTLSSocket.cpp
 | 
			
		||||
  stubs/Mutex_stub.cpp
 | 
			
		||||
  stubs/mbed_assert_stub.c
 | 
			
		||||
  stubs/equeue_stub.c
 | 
			
		||||
  ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c
 | 
			
		||||
  stubs/EventQueue_stub.cpp
 | 
			
		||||
  stubs/mbed_shared_queues_stub.cpp
 | 
			
		||||
  stubs/nsapi_dns_stub.cpp
 | 
			
		||||
  stubs/EventFlags_stub.cpp
 | 
			
		||||
  stubs/stoip4_stub.c
 | 
			
		||||
  stubs/ip4tos_stub.c
 | 
			
		||||
  stubs/Kernel_stub.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h\"")
 | 
			
		||||
set_source_files_properties(features/netsocket/DTLSSocket/test_DTLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH})
 | 
			
		||||
set_source_files_properties(../features/netsocket/DTLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH})
 | 
			
		||||
set_source_files_properties(../features/netsocket/DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited and affiliates
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKETWRAPPER_TLS_TEST_CONFIG_H_
 | 
			
		||||
#define UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKETWRAPPER_TLS_TEST_CONFIG_H_
 | 
			
		||||
 | 
			
		||||
#define MBEDTLS_SSL_CLI_C
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* UNITTESTS_FEATURES_NETSOCKET_DTLSSOCKETWRAPPER_TLS_TEST_CONFIG_H_ */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,406 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited and affiliates
 | 
			
		||||
 * 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 "gtest/gtest.h"
 | 
			
		||||
#include "features/netsocket/UDPSocket.h"
 | 
			
		||||
#include "features/netsocket/DTLSSocketWrapper.h"
 | 
			
		||||
#include "NetworkStack_stub.h"
 | 
			
		||||
#include "features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.h"
 | 
			
		||||
#include <cstring> //memset
 | 
			
		||||
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Control the rtos EventFlags stub. See EventFlags_stub.cpp
 | 
			
		||||
extern std::list<uint32_t> eventFlagsStubNextRetval;
 | 
			
		||||
 | 
			
		||||
class TestDTLSSocketWrapper : public testing::Test {
 | 
			
		||||
public:
 | 
			
		||||
    unsigned int dataSize = 10;
 | 
			
		||||
    char dataBuf[10];
 | 
			
		||||
protected:
 | 
			
		||||
    UDPSocket *transport;
 | 
			
		||||
    DTLSSocketWrapper *wrapper;
 | 
			
		||||
    NetworkStackstub stack;
 | 
			
		||||
 | 
			
		||||
    virtual void SetUp()
 | 
			
		||||
    {
 | 
			
		||||
        memset(mbedtls_stub.retArray, 0, sizeof(mbedtls_stub.retArray));
 | 
			
		||||
        mbedtls_stub.useCounter = false;
 | 
			
		||||
        mbedtls_stub.counter = 0;
 | 
			
		||||
        mbedtls_stub.crt_expected_int = 0;
 | 
			
		||||
        mbedtls_stub.expected_int = 0;
 | 
			
		||||
        transport = new UDPSocket();
 | 
			
		||||
        wrapper = new DTLSSocketWrapper(transport);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void TearDown()
 | 
			
		||||
    {
 | 
			
		||||
        mbedtls_stub.useCounter = false;
 | 
			
		||||
        stack.return_values.clear();
 | 
			
		||||
        stack.return_socketAddress = SocketAddress();
 | 
			
		||||
        eventFlagsStubNextRetval.clear();
 | 
			
		||||
        delete wrapper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char *cert = "-----BEGIN CERTIFICATE-----\
 | 
			
		||||
                MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\
 | 
			
		||||
                MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\
 | 
			
		||||
                DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\
 | 
			
		||||
                SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\
 | 
			
		||||
                GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\
 | 
			
		||||
                AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\
 | 
			
		||||
                q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\
 | 
			
		||||
                SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\
 | 
			
		||||
                Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\
 | 
			
		||||
                a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\
 | 
			
		||||
                /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\
 | 
			
		||||
                AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\
 | 
			
		||||
                CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\
 | 
			
		||||
                bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\
 | 
			
		||||
                c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\
 | 
			
		||||
                VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\
 | 
			
		||||
                ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\
 | 
			
		||||
                MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\
 | 
			
		||||
                Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\
 | 
			
		||||
                AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\
 | 
			
		||||
                uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\
 | 
			
		||||
                wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\
 | 
			
		||||
                X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\
 | 
			
		||||
                PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\
 | 
			
		||||
                KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\
 | 
			
		||||
                -----END CERTIFICATE-----";
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool callback_is_called;
 | 
			
		||||
static void my_callback()
 | 
			
		||||
{
 | 
			
		||||
    callback_is_called = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, constructor)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_TRUE(wrapper);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, constructor_hostname)
 | 
			
		||||
{
 | 
			
		||||
    DTLSSocketWrapper *wrapper2 = new DTLSSocketWrapper(transport, "localhost");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* connect */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, connect)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IS_CONNECTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, connect_no_open)
 | 
			
		||||
{
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK); //UDP doesn't mind.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* connect: SSL-related errors */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, connect_handshake_fail_ssl_handshake)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[1] = -1; // mbedtls_ssl_handshake error
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_AUTH_FAILURE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, connect_handshake_fail_ssl_handshake_in_progress)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    wrapper->set_timeout(1);
 | 
			
		||||
    eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
 | 
			
		||||
    mbedtls_stub.retArray[1] = MBEDTLS_ERR_SSL_WANT_READ; // mbedtls_ssl_handshake error
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, connect_handshake_fail_ssl_get_verify_result)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.uint32_value = 1; // mbedtls_ssl_get_verify_result error
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, connect_fail_ctr_drbg_seed)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.crt_expected_int = 1; // mbedtls_ctr_drbg_seed error
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER);
 | 
			
		||||
    mbedtls_stub.crt_expected_int = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, connect_fail_ssl_setup)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[0] = 2; // mbedtls_ssl_setup           error
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* send */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, send_no_open)
 | 
			
		||||
{
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, send_in_one_chunk)
 | 
			
		||||
{
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, send_in_two_chunks)
 | 
			
		||||
{
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, send_error_would_block)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[2] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write
 | 
			
		||||
    eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, send_to)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
 | 
			
		||||
    mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->sendto(a, dataBuf, dataSize), dataSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* recv */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, recv_no_open)
 | 
			
		||||
{
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, recv_all_data)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[2] = dataSize; // mbedtls_ssl_write
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->recv(dataBuf, dataSize), dataSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, recv_less_than_expected)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    unsigned int lessThanDataSize = dataSize - 1;
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[2] = lessThanDataSize; // mbedtls_ssl_write
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->recv(dataBuf, dataSize), lessThanDataSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, recv_would_block)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[2] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
 | 
			
		||||
    EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, recv_from_no_socket)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->recvfrom(&a, dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, recv_from)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    SocketAddress b;
 | 
			
		||||
    EXPECT_EQ(wrapper->recvfrom(&b, dataBuf, dataSize), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, recv_from_null)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    stack.return_socketAddress = a;
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->recvfrom(NULL, dataBuf, dataSize), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* set_root_ca_cert */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, set_root_ca_cert)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(wrapper->get_ca_chain(), static_cast<mbedtls_x509_crt *>(NULL));
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_NE(wrapper->get_ca_chain(), static_cast<mbedtls_x509_crt *>(NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, set_root_ca_cert_nolen)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->set_root_ca_cert(cert), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, set_root_ca_cert_invalid)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.counter = 0;
 | 
			
		||||
    mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error
 | 
			
		||||
    EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_PARAMETER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, set_client_cert_key)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(wrapper->get_own_cert(), static_cast<mbedtls_x509_crt *>(NULL));
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_NE(wrapper->get_own_cert(), static_cast<mbedtls_x509_crt *>(NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, set_client_cert_key_invalid)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error
 | 
			
		||||
    EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, set_client_cert_key_invalid_pem)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[0] = 0; // mbedtls_x509_crt_parse ok
 | 
			
		||||
    mbedtls_stub.retArray[1] = 1; // mbedtls_pk_parse_key error
 | 
			
		||||
    EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, bind)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, bind_no_open)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, sigio)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    callback_is_called = false;
 | 
			
		||||
    wrapper->sigio(mbed::callback(my_callback));
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    wrapper->close(); //trigger events.
 | 
			
		||||
    EXPECT_EQ(callback_is_called, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, setsockopt)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    EXPECT_EQ(wrapper->setsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, getsockopt_no_stack)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, getsockopt)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* unsupported */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, listen_unsupported)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(wrapper->listen(1), NSAPI_ERROR_UNSUPPORTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestDTLSSocketWrapper, accept_unsupported)
 | 
			
		||||
{
 | 
			
		||||
    nsapi_error_t error;
 | 
			
		||||
    EXPECT_EQ(wrapper->accept(&error), static_cast<UDPSocket *>(NULL));
 | 
			
		||||
    EXPECT_EQ(error, NSAPI_ERROR_UNSUPPORTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
 | 
			
		||||
####################
 | 
			
		||||
# UNIT TESTS
 | 
			
		||||
####################
 | 
			
		||||
 | 
			
		||||
set(unittest-sources
 | 
			
		||||
  ../features/netsocket/SocketAddress.cpp
 | 
			
		||||
  ../features/netsocket/NetworkStack.cpp
 | 
			
		||||
  ../features/netsocket/InternetSocket.cpp
 | 
			
		||||
  ../features/netsocket/UDPSocket.cpp
 | 
			
		||||
  ../features/netsocket/DTLSSocketWrapper.cpp
 | 
			
		||||
  ../features/netsocket/TLSSocketWrapper.cpp
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(unittest-test-sources
 | 
			
		||||
  features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp
 | 
			
		||||
  stubs/Mutex_stub.cpp
 | 
			
		||||
  stubs/mbed_assert_stub.c
 | 
			
		||||
  stubs/equeue_stub.c
 | 
			
		||||
  ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c
 | 
			
		||||
  stubs/EventQueue_stub.cpp
 | 
			
		||||
  stubs/mbed_shared_queues_stub.cpp
 | 
			
		||||
  stubs/nsapi_dns_stub.cpp
 | 
			
		||||
  stubs/EventFlags_stub.cpp
 | 
			
		||||
  stubs/stoip4_stub.c
 | 
			
		||||
  stubs/ip4tos_stub.c
 | 
			
		||||
  stubs/Kernel_stub.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h\"")
 | 
			
		||||
set_source_files_properties(features/netsocket/DTLSSocketWrapper/test_DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH})
 | 
			
		||||
set_source_files_properties(../features/netsocket/DTLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,71 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited and affiliates
 | 
			
		||||
 * 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 "gtest/gtest.h"
 | 
			
		||||
#include "features/netsocket/TLSSocket.h"
 | 
			
		||||
#include "NetworkStack_stub.h"
 | 
			
		||||
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Control the rtos EventFlags stub. See EventFlags_stub.cpp
 | 
			
		||||
extern std::list<uint32_t> eventFlagsStubNextRetval;
 | 
			
		||||
 | 
			
		||||
class TestTLSSocket : public testing::Test {
 | 
			
		||||
public:
 | 
			
		||||
    unsigned int dataSize = 10;
 | 
			
		||||
    char dataBuf[10];
 | 
			
		||||
protected:
 | 
			
		||||
    TLSSocket *socket;
 | 
			
		||||
    NetworkStackstub stack;
 | 
			
		||||
 | 
			
		||||
    virtual void SetUp()
 | 
			
		||||
    {
 | 
			
		||||
        socket = new TLSSocket();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void TearDown()
 | 
			
		||||
    {
 | 
			
		||||
        stack.return_values.clear();
 | 
			
		||||
        eventFlagsStubNextRetval.clear();
 | 
			
		||||
        delete socket;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocket, constructor)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_TRUE(socket);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* connect */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocket, connect)
 | 
			
		||||
{
 | 
			
		||||
    socket->open((NetworkStack *)&stack);
 | 
			
		||||
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocket, connect_no_open)
 | 
			
		||||
{
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    EXPECT_EQ(socket->connect("127.0.0.1", 1024), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
/*
 | 
			
		||||
 * tls_test_config.h
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_
 | 
			
		||||
#define UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_
 | 
			
		||||
 | 
			
		||||
#define MBEDTLS_SSL_CLI_C
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
 | 
			
		||||
####################
 | 
			
		||||
# UNIT TESTS
 | 
			
		||||
####################
 | 
			
		||||
 | 
			
		||||
set(unittest-sources
 | 
			
		||||
  ../features/netsocket/SocketAddress.cpp
 | 
			
		||||
  ../features/netsocket/NetworkStack.cpp
 | 
			
		||||
  ../features/netsocket/InternetSocket.cpp
 | 
			
		||||
  ../features/netsocket/TCPSocket.cpp
 | 
			
		||||
  ../features/netsocket/TLSSocket.cpp
 | 
			
		||||
  ../features/netsocket/TLSSocketWrapper.cpp
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c  
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(unittest-test-sources
 | 
			
		||||
  features/netsocket/TLSSocket/test_TLSSocket.cpp
 | 
			
		||||
  stubs/Mutex_stub.cpp
 | 
			
		||||
  stubs/mbed_assert_stub.c
 | 
			
		||||
  stubs/equeue_stub.c
 | 
			
		||||
  ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c
 | 
			
		||||
  stubs/EventQueue_stub.cpp
 | 
			
		||||
  stubs/mbed_shared_queues_stub.cpp
 | 
			
		||||
  stubs/nsapi_dns_stub.cpp
 | 
			
		||||
  stubs/EventFlags_stub.cpp
 | 
			
		||||
  stubs/stoip4_stub.c
 | 
			
		||||
  stubs/ip4tos_stub.c
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h\"")
 | 
			
		||||
set_source_files_properties(features/netsocket/TLSSocket/test_TLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH})
 | 
			
		||||
set_source_files_properties(../features/netsocket/TLSSocket.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH})
 | 
			
		||||
set_source_files_properties(../features/netsocket/TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,420 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018, Arm Limited and affiliates
 | 
			
		||||
 * 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 "gtest/gtest.h"
 | 
			
		||||
#include "features/netsocket/TCPSocket.h"
 | 
			
		||||
#include "features/netsocket/TLSSocketWrapper.h"
 | 
			
		||||
#include "NetworkStack_stub.h"
 | 
			
		||||
#include "features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.h"
 | 
			
		||||
#include <cstring> //memset
 | 
			
		||||
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
mbed_error_status_t mbed_error(mbed_error_status_t error_status, const char *error_msg, unsigned int error_value, const char *filename, int line_number)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Control the rtos EventFlags stub. See EventFlags_stub.cpp
 | 
			
		||||
extern std::list<uint32_t> eventFlagsStubNextRetval;
 | 
			
		||||
 | 
			
		||||
class TestTLSSocketWrapper : public testing::Test {
 | 
			
		||||
public:
 | 
			
		||||
    unsigned int dataSize = 10;
 | 
			
		||||
    char dataBuf[10];
 | 
			
		||||
protected:
 | 
			
		||||
    TCPSocket *transport;
 | 
			
		||||
    TLSSocketWrapper *wrapper;
 | 
			
		||||
    NetworkStackstub stack;
 | 
			
		||||
 | 
			
		||||
    virtual void SetUp()
 | 
			
		||||
    {
 | 
			
		||||
        memset(mbedtls_stub.retArray, 0, sizeof(mbedtls_stub.retArray));
 | 
			
		||||
        mbedtls_stub.useCounter = false;
 | 
			
		||||
        mbedtls_stub.counter = 0;
 | 
			
		||||
        mbedtls_stub.crt_expected_int = 0;
 | 
			
		||||
        mbedtls_stub.expected_int = 0;
 | 
			
		||||
        transport = new TCPSocket();
 | 
			
		||||
        wrapper = new TLSSocketWrapper(transport);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void TearDown()
 | 
			
		||||
    {
 | 
			
		||||
        stack.return_values.clear();
 | 
			
		||||
        eventFlagsStubNextRetval.clear();
 | 
			
		||||
        delete wrapper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    char *cert = "-----BEGIN CERTIFICATE-----\
 | 
			
		||||
                MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\
 | 
			
		||||
                MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\
 | 
			
		||||
                DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\
 | 
			
		||||
                SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\
 | 
			
		||||
                GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\
 | 
			
		||||
                AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\
 | 
			
		||||
                q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\
 | 
			
		||||
                SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\
 | 
			
		||||
                Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\
 | 
			
		||||
                a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\
 | 
			
		||||
                /PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\
 | 
			
		||||
                AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\
 | 
			
		||||
                CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\
 | 
			
		||||
                bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\
 | 
			
		||||
                c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\
 | 
			
		||||
                VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\
 | 
			
		||||
                ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\
 | 
			
		||||
                MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\
 | 
			
		||||
                Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\
 | 
			
		||||
                AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\
 | 
			
		||||
                uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\
 | 
			
		||||
                wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\
 | 
			
		||||
                X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\
 | 
			
		||||
                PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\
 | 
			
		||||
                KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\
 | 
			
		||||
                -----END CERTIFICATE-----";
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool callback_is_called;
 | 
			
		||||
static void my_callback()
 | 
			
		||||
{
 | 
			
		||||
    callback_is_called = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, constructor)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_TRUE(wrapper);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, constructor_hostname)
 | 
			
		||||
{
 | 
			
		||||
    TLSSocketWrapper *wrapper2 = new TLSSocketWrapper(transport, "localhost");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* connect */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, connect)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IS_CONNECTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* connect: TCP-related errors */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, connect_no_open)
 | 
			
		||||
{
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, connect_error_in_progress_no_timeout)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_IN_PROGRESS;
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, connect_with_timeout)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_IN_PROGRESS;
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
 | 
			
		||||
    wrapper->set_blocking(true);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, connect_error_is_connected)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    wrapper->set_timeout(1);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[0] = 1; //  mbedtls_ctr_drbg_seed error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* connect: SSL-related errors */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, connect_fail_ctr_drbg_seed)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.crt_expected_int = 1; // mbedtls_ctr_drbg_seed error
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER);
 | 
			
		||||
    mbedtls_stub.crt_expected_int = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, connect_fail_ssl_setup)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[0] = 0; // mbedtls_ssl_config_defaults ok
 | 
			
		||||
    mbedtls_stub.retArray[1] = 2; // mbedtls_ssl_setup           error
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_PARAMETER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, connect_handshake_fail_ssl_handshake)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[2] = -1; // mbedtls_ssl_handshake error
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_AUTH_FAILURE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, connect_handshake_fail_ssl_handshake_in_progress)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    wrapper->set_timeout(1);
 | 
			
		||||
    eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
 | 
			
		||||
    mbedtls_stub.retArray[2] = MBEDTLS_ERR_SSL_WANT_READ; // mbedtls_ssl_handshake error
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_IN_PROGRESS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, connect_handshake_fail_ssl_get_verify_result)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.uint32_value = 1; // mbedtls_ssl_get_verify_result error
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* send */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, send_no_open)
 | 
			
		||||
{
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, send_in_one_chunk)
 | 
			
		||||
{
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, send_in_two_chunks)
 | 
			
		||||
{
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->send(dataBuf, dataSize), dataSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, send_error_would_block)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[3] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write
 | 
			
		||||
    eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->send(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, send_to)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
 | 
			
		||||
    mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->sendto(a, dataBuf, dataSize), dataSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* recv */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, recv_no_open)
 | 
			
		||||
{
 | 
			
		||||
    stack.return_value = NSAPI_ERROR_OK;
 | 
			
		||||
    EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, recv_all_data)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[3] = dataSize; // mbedtls_ssl_write
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->recv(dataBuf, dataSize), dataSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, recv_less_than_expected)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    unsigned int lessThanDataSize = dataSize - 1;
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[3] = lessThanDataSize; // mbedtls_ssl_write
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->recv(dataBuf, dataSize), lessThanDataSize);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, recv_would_block)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[3] = MBEDTLS_ERR_SSL_WANT_WRITE; // mbedtls_ssl_write
 | 
			
		||||
    const SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    eventFlagsStubNextRetval.push_back(osFlagsError); // Break the wait loop
 | 
			
		||||
    EXPECT_EQ(wrapper->recv(dataBuf, dataSize), NSAPI_ERROR_WOULD_BLOCK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, recv_from_no_socket)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->recvfrom(&a, dataBuf, dataSize), NSAPI_ERROR_NO_CONNECTION);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, recv_from)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    SocketAddress b;
 | 
			
		||||
    EXPECT_EQ(wrapper->recvfrom(&b, dataBuf, dataSize), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, recv_from_null)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->connect(a), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->recvfrom(NULL, dataBuf, dataSize), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* set_root_ca_cert */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, set_root_ca_cert)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(wrapper->get_ca_chain(), static_cast<mbedtls_x509_crt *>(NULL));
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_NE(wrapper->get_ca_chain(), static_cast<mbedtls_x509_crt *>(NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, set_root_ca_cert_nolen)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->set_root_ca_cert(cert), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, set_root_ca_cert_invalid)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error
 | 
			
		||||
    EXPECT_EQ(wrapper->set_root_ca_cert(cert, strlen(cert)), NSAPI_ERROR_PARAMETER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, set_client_cert_key)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(wrapper->get_own_cert(), static_cast<mbedtls_x509_crt *>(NULL));
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_OK);
 | 
			
		||||
    EXPECT_NE(wrapper->get_own_cert(), static_cast<mbedtls_x509_crt *>(NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, set_client_cert_key_invalid)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[0] = 1; // mbedtls_x509_crt_parse error
 | 
			
		||||
    EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, set_client_cert_key_invalid_pem)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(transport->open((NetworkStack *)&stack), NSAPI_ERROR_OK);
 | 
			
		||||
    mbedtls_stub.useCounter = true;
 | 
			
		||||
    mbedtls_stub.retArray[0] = 0; // mbedtls_x509_crt_parse ok
 | 
			
		||||
    mbedtls_stub.retArray[1] = 1; // mbedtls_pk_parse_key error
 | 
			
		||||
    EXPECT_EQ(wrapper->set_client_cert_key(cert, cert), NSAPI_ERROR_PARAMETER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, bind)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, bind_no_open)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    EXPECT_EQ(wrapper->bind(a), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, sigio)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    callback_is_called = false;
 | 
			
		||||
    wrapper->sigio(mbed::callback(my_callback));
 | 
			
		||||
    SocketAddress a("127.0.0.1", 1024);
 | 
			
		||||
    wrapper->close(); //trigger events.
 | 
			
		||||
    EXPECT_EQ(callback_is_called, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, setsockopt)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    EXPECT_EQ(wrapper->setsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, getsockopt_no_stack)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_NO_SOCKET);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, getsockopt)
 | 
			
		||||
{
 | 
			
		||||
    transport->open((NetworkStack *)&stack);
 | 
			
		||||
    EXPECT_EQ(wrapper->getsockopt(0, 0, 0, 0), NSAPI_ERROR_UNSUPPORTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* unsupported */
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, listen_unsupported)
 | 
			
		||||
{
 | 
			
		||||
    EXPECT_EQ(wrapper->listen(1), NSAPI_ERROR_UNSUPPORTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(TestTLSSocketWrapper, accept_unsupported)
 | 
			
		||||
{
 | 
			
		||||
    nsapi_error_t error;
 | 
			
		||||
    EXPECT_EQ(wrapper->accept(&error), static_cast<TCPSocket *>(NULL));
 | 
			
		||||
    EXPECT_EQ(error, NSAPI_ERROR_UNSUPPORTED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
/*
 | 
			
		||||
 * tls_test_config.h
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_
 | 
			
		||||
#define UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_
 | 
			
		||||
 | 
			
		||||
#define MBEDTLS_SSL_CLI_C
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif /* UNITTESTS_FEATURES_NETSOCKET_TLSSOCKET_TLS_TEST_CONFIG_H_ */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
 | 
			
		||||
####################
 | 
			
		||||
# UNIT TESTS
 | 
			
		||||
####################
 | 
			
		||||
 | 
			
		||||
set(unittest-sources
 | 
			
		||||
  ../features/netsocket/SocketAddress.cpp
 | 
			
		||||
  ../features/netsocket/NetworkStack.cpp
 | 
			
		||||
  ../features/netsocket/InternetSocket.cpp
 | 
			
		||||
  ../features/netsocket/TCPSocket.cpp
 | 
			
		||||
  ../features/netsocket/TLSSocketWrapper.cpp
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip4string/ip4tos.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip6string/ip6tos.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip4string/stoip4.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libip6string/stoip6.c
 | 
			
		||||
  ../features/frameworks/nanostack-libservice/source/libBits/common_functions.c  
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(unittest-test-sources
 | 
			
		||||
  features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp
 | 
			
		||||
  stubs/Mutex_stub.cpp
 | 
			
		||||
  stubs/mbed_assert_stub.c
 | 
			
		||||
  stubs/equeue_stub.c
 | 
			
		||||
  ../features/nanostack/coap-service/test/coap-service/unittest/stub/mbedtls_stub.c
 | 
			
		||||
  stubs/EventQueue_stub.cpp
 | 
			
		||||
  stubs/mbed_shared_queues_stub.cpp
 | 
			
		||||
  stubs/nsapi_dns_stub.cpp
 | 
			
		||||
  stubs/EventFlags_stub.cpp
 | 
			
		||||
  stubs/stoip4_stub.c
 | 
			
		||||
  stubs/ip4tos_stub.c
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h\"")
 | 
			
		||||
set_source_files_properties(features/netsocket/TLSSocketWrapper/test_TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH})
 | 
			
		||||
set_source_files_properties(../features/netsocket/TLSSocketWrapper.cpp PROPERTIES COMPILE_DEFINITIONS MBEDTLS_USER_CONFIG_FILE=${MBEDTLS_USER_CONFIG_FILE_PATH})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ class NetworkStackstub : public NetworkStack {
 | 
			
		|||
public:
 | 
			
		||||
    std::list<nsapi_error_t> return_values;
 | 
			
		||||
    nsapi_error_t return_value;
 | 
			
		||||
    SocketAddress return_socketAddress;
 | 
			
		||||
 | 
			
		||||
    NetworkStackstub()
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -113,6 +114,9 @@ protected:
 | 
			
		|||
    virtual nsapi_size_or_error_t socket_recvfrom(nsapi_socket_t handle, SocketAddress *address,
 | 
			
		||||
                                                  void *buffer, nsapi_size_t size)
 | 
			
		||||
    {
 | 
			
		||||
        if (return_socketAddress != SocketAddress()) {
 | 
			
		||||
            *address = return_socketAddress;
 | 
			
		||||
        }
 | 
			
		||||
        if (!return_values.empty()) {
 | 
			
		||||
            nsapi_error_t ret = return_values.front();
 | 
			
		||||
            return_values.pop_front();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,7 +59,12 @@ void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_ssl_config_init(mbedtls_ssl_config *a)
 | 
			
		||||
void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport )
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_ssl_config_init( mbedtls_ssl_config *a )
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -198,6 +203,16 @@ int mbedtls_ssl_write(mbedtls_ssl_context *a, const unsigned char *b, size_t c)
 | 
			
		|||
    return mbedtls_stub.expected_int;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname )
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl )
 | 
			
		||||
{
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//From crt_drbg.h
 | 
			
		||||
| 
						 | 
				
			
			@ -252,6 +267,18 @@ 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_info( char *buf, size_t size, const char *prefix,
 | 
			
		||||
                   const mbedtls_x509_crt *crt )
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
 | 
			
		||||
                          uint32_t flags )
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//From entropy.h
 | 
			
		||||
void mbedtls_entropy_init(mbedtls_entropy_context *a)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -356,3 +383,6 @@ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl)
 | 
			
		|||
    }
 | 
			
		||||
    return mbedtls_stub.expected_int;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbedtls_strerror( int ret, char *buf, size_t buflen ){
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 * 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 "DTLSSocket.h"
 | 
			
		||||
 | 
			
		||||
#define TRACE_GROUP "TLSS"
 | 
			
		||||
#include "mbed-trace/mbed_trace.h"
 | 
			
		||||
 | 
			
		||||
// This class requires Mbed TLS SSL/TLS client code
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C)
 | 
			
		||||
 | 
			
		||||
nsapi_error_t DTLSSocket::connect(const char *host, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress addr;
 | 
			
		||||
    nsapi_error_t ret;
 | 
			
		||||
 | 
			
		||||
    ret = _udp_socket.getpeername(&addr);
 | 
			
		||||
    if (ret != NSAPI_ERROR_NO_CONNECTION) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!addr || ret == NSAPI_ERROR_NO_CONNECTION) {
 | 
			
		||||
        nsapi_error_t err = _udp_socket._stack->gethostbyname(host, &addr);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            return NSAPI_ERROR_DNS_FAILURE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        addr.set_port(port);
 | 
			
		||||
 | 
			
		||||
        set_hostname(host);
 | 
			
		||||
        _udp_socket.connect(addr); // UDPSocket::connect() cannot fail
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return connect(addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DTLSSocket::~DTLSSocket()
 | 
			
		||||
{
 | 
			
		||||
    // Make sure that DTLSSocketWrapper::close() is called before the transport is
 | 
			
		||||
    // destroyed.
 | 
			
		||||
    close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // MBEDTLS_SSL_CLI_C
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,94 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef DTLSSOCKET_H
 | 
			
		||||
#define DTLSSOCKET_H
 | 
			
		||||
 | 
			
		||||
#include "DTLSSocketWrapper.h"
 | 
			
		||||
#include "SocketAddress.h"
 | 
			
		||||
#include "UDPSocket.h"
 | 
			
		||||
 | 
			
		||||
// This class requires Mbed TLS SSL/TLS client code
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY)
 | 
			
		||||
 | 
			
		||||
class DTLSSocket : public DTLSSocketWrapper {
 | 
			
		||||
public:
 | 
			
		||||
    /** Create an uninitialized DTLS socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Must call open to initialize the socket on a network stack.
 | 
			
		||||
     */
 | 
			
		||||
    DTLSSocket() : DTLSSocketWrapper(&_udp_socket) {}
 | 
			
		||||
 | 
			
		||||
    /** Destroy the DTLSSocket and closes the transport.
 | 
			
		||||
     */
 | 
			
		||||
    virtual ~DTLSSocket();
 | 
			
		||||
 | 
			
		||||
    /** Create a socket on a network interface
 | 
			
		||||
     *
 | 
			
		||||
     *  Creates and opens a socket on the network stack of the given
 | 
			
		||||
     *  network interface.
 | 
			
		||||
     *  If hostname is also given, user is not required to call set_hostname() later.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Network stack as target for socket
 | 
			
		||||
     *  @param hostname Hostname used for certificate verification
 | 
			
		||||
     */
 | 
			
		||||
    template <typename S>
 | 
			
		||||
    DTLSSocket(S *stack, const char *hostname = NULL) : DTLSSocketWrapper(&_udp_socket, hostname)
 | 
			
		||||
    {
 | 
			
		||||
        nsapi_error_t ret = _udp_socket.open(stack);
 | 
			
		||||
        MBED_ASSERT(ret == NSAPI_ERROR_OK);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** Opens a socket
 | 
			
		||||
     *
 | 
			
		||||
     *  Creates a network socket on the network stack of the given
 | 
			
		||||
     *  network interface. Not needed if stack is passed to the
 | 
			
		||||
     *  socket's constructor.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Network stack as target for socket
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    virtual nsapi_error_t open(NetworkStack *stack)
 | 
			
		||||
    {
 | 
			
		||||
        return _udp_socket.open(stack);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename S>
 | 
			
		||||
    nsapi_error_t open(S *stack)
 | 
			
		||||
    {
 | 
			
		||||
        return open(nsapi_create_stack(stack));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    using DTLSSocketWrapper::connect;
 | 
			
		||||
 | 
			
		||||
    /** Connects TCP socket to a remote host
 | 
			
		||||
     *
 | 
			
		||||
     *  Initiates a connection to a remote server specified by either
 | 
			
		||||
     *  a domain name or an IP address and a port.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param host     Hostname of the remote host
 | 
			
		||||
     *  @param port     Port of the remote host
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    nsapi_error_t connect(const char *host, uint16_t port);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    UDPSocket _udp_socket;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,77 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 * 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 "DTLSSocketWrapper.h"
 | 
			
		||||
#include "platform/Callback.h"
 | 
			
		||||
#include "drivers/Timer.h"
 | 
			
		||||
#include "events/mbed_events.h"
 | 
			
		||||
#include "rtos/Kernel.h"
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C)
 | 
			
		||||
 | 
			
		||||
DTLSSocketWrapper::DTLSSocketWrapper(Socket *transport, const char *hostname, control_transport control) :
 | 
			
		||||
    TLSSocketWrapper(transport, hostname, control),
 | 
			
		||||
    _int_ms_tick(0),
 | 
			
		||||
    _timer_event_id(0),
 | 
			
		||||
    _timer_expired(false)
 | 
			
		||||
{
 | 
			
		||||
    mbedtls_ssl_conf_transport(get_ssl_config(), MBEDTLS_SSL_TRANSPORT_DATAGRAM);
 | 
			
		||||
    mbedtls_ssl_set_timer_cb(get_ssl_context(), this, timing_set_delay, timing_get_delay);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DTLSSocketWrapper::timing_set_delay(void *ctx, uint32_t int_ms, uint32_t fin_ms)
 | 
			
		||||
{
 | 
			
		||||
    DTLSSocketWrapper *context = static_cast<DTLSSocketWrapper *>(ctx);
 | 
			
		||||
 | 
			
		||||
    if (context->_timer_event_id) {
 | 
			
		||||
        mbed::mbed_event_queue()->cancel(context->_timer_event_id);
 | 
			
		||||
        context->_timer_expired = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (fin_ms == 0) {
 | 
			
		||||
        context->_timer_event_id = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    context->_int_ms_tick = rtos::Kernel::get_ms_count() + int_ms;
 | 
			
		||||
    context->_timer_event_id = mbed::mbed_event_queue()->call_in(fin_ms, context, &DTLSSocketWrapper::timer_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int DTLSSocketWrapper::timing_get_delay(void *ctx)
 | 
			
		||||
{
 | 
			
		||||
    DTLSSocketWrapper *context = static_cast<DTLSSocketWrapper *>(ctx);
 | 
			
		||||
 | 
			
		||||
    /* See documentation of "typedef int mbedtls_ssl_get_timer_t( void * ctx );" from ssl.h */
 | 
			
		||||
 | 
			
		||||
    if (context->_timer_event_id == 0) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    } else if (context->_timer_expired) {
 | 
			
		||||
        return 2;
 | 
			
		||||
    } else if (context->_int_ms_tick < rtos::Kernel::get_ms_count()) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DTLSSocketWrapper::timer_event(void)
 | 
			
		||||
{
 | 
			
		||||
    _timer_expired = true;
 | 
			
		||||
    event();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* MBEDTLS_SSL_CLI_C */
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef DTLSSOCKETWRAPPER_H
 | 
			
		||||
#define DTLSSOCKETWRAPPER_H
 | 
			
		||||
 | 
			
		||||
#include "TLSSocketWrapper.h"
 | 
			
		||||
 | 
			
		||||
// This class requires Mbed TLS SSL/TLS client code
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY)
 | 
			
		||||
 | 
			
		||||
class DTLSSocketWrapper : public TLSSocketWrapper {
 | 
			
		||||
public:
 | 
			
		||||
    DTLSSocketWrapper(Socket *transport, const char *hostname = NULL, control_transport control = TRANSPORT_CONNECT_AND_CLOSE);
 | 
			
		||||
private:
 | 
			
		||||
    static void timing_set_delay(void *ctx, uint32_t int_ms, uint32_t fin_ms);
 | 
			
		||||
    static int timing_get_delay(void *ctx);
 | 
			
		||||
    void timer_event();
 | 
			
		||||
    uint64_t _int_ms_tick;
 | 
			
		||||
    int _timer_event_id;
 | 
			
		||||
    bool _timer_expired : 1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -175,6 +175,8 @@ protected:
 | 
			
		|||
    static const int WRITE_FLAG    = 0x2u;
 | 
			
		||||
    static const int FINISHED_FLAG = 0x3u;
 | 
			
		||||
 | 
			
		||||
    friend class DTLSSocket;  // Allow DTLSSocket::connect() to do name resolution on the _stack
 | 
			
		||||
 | 
			
		||||
#endif //!defined(DOXYGEN_ONLY)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,6 +103,9 @@ nsapi_error_t TCPSocket::connect(const SocketAddress &address)
 | 
			
		|||
nsapi_error_t TCPSocket::connect(const char *host, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    SocketAddress address;
 | 
			
		||||
    if (!_socket) {
 | 
			
		||||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
    nsapi_error_t err = _stack->gethostbyname(host, &address);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        return NSAPI_ERROR_DNS_FAILURE;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,14 +25,17 @@
 | 
			
		|||
 | 
			
		||||
nsapi_error_t TLSSocket::connect(const char *host, uint16_t port)
 | 
			
		||||
{
 | 
			
		||||
    set_hostname(host);
 | 
			
		||||
 | 
			
		||||
    nsapi_error_t ret = tcp_socket.connect(host, port);
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    nsapi_error_t ret = NSAPI_ERROR_OK;
 | 
			
		||||
    if (!is_handshake_started()) {
 | 
			
		||||
        ret = tcp_socket.connect(host, port);
 | 
			
		||||
        if (ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IN_PROGRESS) {
 | 
			
		||||
            set_hostname(host);
 | 
			
		||||
        }
 | 
			
		||||
        if (ret != NSAPI_ERROR_OK && ret != NSAPI_ERROR_IS_CONNECTED) {
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return TLSSocketWrapper::do_handshake();
 | 
			
		||||
    return TLSSocketWrapper::start_handshake(ret == NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TLSSocket::~TLSSocket()
 | 
			
		||||
| 
						 | 
				
			
			@ -44,4 +47,4 @@ TLSSocket::~TLSSocket()
 | 
			
		|||
    close();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // MBEDTLS_SSL_CLI_C
 | 
			
		||||
#endif // MBEDTLS_SSL_CLI_C
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@
 | 
			
		|||
#include "mbedtls/error.h"
 | 
			
		||||
 | 
			
		||||
// This class requires Mbed TLS SSL/TLS client code
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C)
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief TLSSocket a wrapper around TCPSocket for interacting with TLS servers
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +67,9 @@ public:
 | 
			
		|||
     *  network interface. Not needed if stack is passed to the
 | 
			
		||||
     *  socket's constructor.
 | 
			
		||||
     *
 | 
			
		||||
     *  @note TLSSocket cannot be reopened after closing. It should be destructed to
 | 
			
		||||
     *        clear internal TLS memory structures.
 | 
			
		||||
     *
 | 
			
		||||
     *  @param stack    Network stack as target for socket
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,18 +16,22 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include "TLSSocketWrapper.h"
 | 
			
		||||
#include "platform/Callback.h"
 | 
			
		||||
#include "drivers/Timer.h"
 | 
			
		||||
#include "events/mbed_events.h"
 | 
			
		||||
 | 
			
		||||
#define TRACE_GROUP "TLSW"
 | 
			
		||||
#include "mbed-trace/mbed_trace.h"
 | 
			
		||||
#include "mbedtls/debug.h"
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
#include "Kernel.h"
 | 
			
		||||
 | 
			
		||||
// This class requires Mbed TLS SSL/TLS client code
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C)
 | 
			
		||||
 | 
			
		||||
TLSSocketWrapper::TLSSocketWrapper(Socket *transport, const char *hostname, control_transport control) :
 | 
			
		||||
    _transport(transport),
 | 
			
		||||
    _timeout(-1),
 | 
			
		||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
 | 
			
		||||
    _cacert(NULL),
 | 
			
		||||
    _clicert(NULL),
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +39,7 @@ TLSSocketWrapper::TLSSocketWrapper(Socket *transport, const char *hostname, cont
 | 
			
		|||
    _ssl_conf(NULL),
 | 
			
		||||
    _connect_transport(control == TRANSPORT_CONNECT || control == TRANSPORT_CONNECT_AND_CLOSE),
 | 
			
		||||
    _close_transport(control == TRANSPORT_CLOSE || control == TRANSPORT_CONNECT_AND_CLOSE),
 | 
			
		||||
    _tls_initialized(false),
 | 
			
		||||
    _handshake_completed(false),
 | 
			
		||||
    _cacert_allocated(false),
 | 
			
		||||
    _clicert_allocated(false),
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +48,9 @@ TLSSocketWrapper::TLSSocketWrapper(Socket *transport, const char *hostname, cont
 | 
			
		|||
    mbedtls_entropy_init(&_entropy);
 | 
			
		||||
    mbedtls_ctr_drbg_init(&_ctr_drbg);
 | 
			
		||||
    mbedtls_ssl_init(&_ssl);
 | 
			
		||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
 | 
			
		||||
    mbedtls_pk_init(&_pkctx);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (hostname) {
 | 
			
		||||
        set_hostname(hostname);
 | 
			
		||||
| 
						 | 
				
			
			@ -58,9 +65,8 @@ TLSSocketWrapper::~TLSSocketWrapper()
 | 
			
		|||
    mbedtls_entropy_free(&_entropy);
 | 
			
		||||
    mbedtls_ctr_drbg_free(&_ctr_drbg);
 | 
			
		||||
    mbedtls_ssl_free(&_ssl);
 | 
			
		||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
 | 
			
		||||
    mbedtls_pk_free(&_pkctx);
 | 
			
		||||
 | 
			
		||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
 | 
			
		||||
    set_own_cert(NULL);
 | 
			
		||||
    set_ca_chain(NULL);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +120,7 @@ nsapi_error_t TLSSocketWrapper::set_client_cert_key(const char *client_cert_pem,
 | 
			
		|||
nsapi_error_t TLSSocketWrapper::set_client_cert_key(const void *client_cert, size_t client_cert_len,
 | 
			
		||||
                                                    const void *client_private_key_pem, size_t client_private_key_len)
 | 
			
		||||
{
 | 
			
		||||
#if !defined(MBEDTLS_X509_CRT_PARSE_C)
 | 
			
		||||
#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PK_C)
 | 
			
		||||
    return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -140,29 +146,34 @@ nsapi_error_t TLSSocketWrapper::set_client_cert_key(const void *client_cert, siz
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocketWrapper::do_handshake()
 | 
			
		||||
nsapi_error_t TLSSocketWrapper::start_handshake(bool first_call)
 | 
			
		||||
{
 | 
			
		||||
    nsapi_error_t _error;
 | 
			
		||||
    const char DRBG_PERS[] = "mbed TLS client";
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (!_transport) {
 | 
			
		||||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _transport->set_blocking(true);
 | 
			
		||||
    if (_tls_initialized) {
 | 
			
		||||
        return continue_handshake();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
 | 
			
		||||
    tr_info("Starting TLS handshake with %s", _ssl.hostname);
 | 
			
		||||
#else
 | 
			
		||||
    tr_info("Starting TLS handshake");
 | 
			
		||||
#endif
 | 
			
		||||
    /*
 | 
			
		||||
     * Initialize TLS-related stuf.
 | 
			
		||||
     */
 | 
			
		||||
    int ret;
 | 
			
		||||
    if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy,
 | 
			
		||||
                                     (const unsigned char *) DRBG_PERS,
 | 
			
		||||
                                     sizeof(DRBG_PERS))) != 0) {
 | 
			
		||||
        print_mbedtls_error("mbedtls_crt_drbg_init", ret);
 | 
			
		||||
        _error = ret;
 | 
			
		||||
        return _error;
 | 
			
		||||
        return NSAPI_ERROR_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tr_info("mbedtls_ssl_conf_rng()");
 | 
			
		||||
    mbedtls_ssl_conf_rng(get_ssl_config(), mbedtls_ctr_drbg_random, &_ctr_drbg);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -172,29 +183,62 @@ nsapi_error_t TLSSocketWrapper::do_handshake()
 | 
			
		|||
    mbedtls_debug_set_threshold(MBED_CONF_TLS_SOCKET_DEBUG_LEVEL);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    tr_info("mbedtls_ssl_setup()");
 | 
			
		||||
    tr_debug("mbedtls_ssl_setup()");
 | 
			
		||||
    if ((ret = mbedtls_ssl_setup(&_ssl, get_ssl_config())) != 0) {
 | 
			
		||||
        print_mbedtls_error("mbedtls_ssl_setup", ret);
 | 
			
		||||
        _error = ret;
 | 
			
		||||
        return _error;
 | 
			
		||||
        return NSAPI_ERROR_PARAMETER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _transport->set_blocking(false);
 | 
			
		||||
    _transport->sigio(mbed::callback(this, &TLSSocketWrapper::event));
 | 
			
		||||
    mbedtls_ssl_set_bio(&_ssl, this, ssl_send, ssl_recv, NULL);
 | 
			
		||||
 | 
			
		||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
 | 
			
		||||
    /* Start the handshake, the rest will be done in onReceive() */
 | 
			
		||||
    tr_info("Starting TLS handshake with %s", _ssl.hostname);
 | 
			
		||||
#else
 | 
			
		||||
    tr_info("Starting TLS handshake");
 | 
			
		||||
#endif
 | 
			
		||||
    _tls_initialized = true;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
    ret = continue_handshake();
 | 
			
		||||
    if (first_call) {
 | 
			
		||||
        if (ret == NSAPI_ERROR_ALREADY) {
 | 
			
		||||
            ret = NSAPI_ERROR_IN_PROGRESS; // If first call should return IN_PROGRESS
 | 
			
		||||
        }
 | 
			
		||||
        if (ret == NSAPI_ERROR_IS_CONNECTED) {
 | 
			
		||||
            ret = NSAPI_ERROR_OK;   // If we happened to complete the request on the first call, return OK.
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocketWrapper::continue_handshake()
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (_handshake_completed) {
 | 
			
		||||
        return NSAPI_ERROR_IS_CONNECTED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!_tls_initialized) {
 | 
			
		||||
        return NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while (true) {
 | 
			
		||||
        ret = mbedtls_ssl_handshake(&_ssl);
 | 
			
		||||
    } while (ret != 0 && (ret == MBEDTLS_ERR_SSL_WANT_READ ||
 | 
			
		||||
                          ret == MBEDTLS_ERR_SSL_WANT_WRITE));
 | 
			
		||||
        if (_timeout && (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)) {
 | 
			
		||||
            uint32_t flag;
 | 
			
		||||
            flag = _event_flag.wait_any(1, _timeout);
 | 
			
		||||
            if (flag & osFlagsError) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        print_mbedtls_error("mbedtls_ssl_handshake", ret);
 | 
			
		||||
        return ret;
 | 
			
		||||
        if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
 | 
			
		||||
            return NSAPI_ERROR_ALREADY;
 | 
			
		||||
        } else {
 | 
			
		||||
            return NSAPI_ERROR_AUTH_FAILURE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
 | 
			
		||||
| 
						 | 
				
			
			@ -225,8 +269,7 @@ nsapi_error_t TLSSocketWrapper::do_handshake()
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
    _handshake_completed = true;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
    return NSAPI_ERROR_IS_CONNECTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -239,15 +282,42 @@ nsapi_error_t TLSSocketWrapper::send(const void *data, nsapi_size_t size)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    tr_debug("send %d", size);
 | 
			
		||||
    ret = mbedtls_ssl_write(&_ssl, (const unsigned char *) data, size);
 | 
			
		||||
    while (true) {
 | 
			
		||||
        if (!_handshake_completed) {
 | 
			
		||||
            ret = continue_handshake();
 | 
			
		||||
            if (ret != NSAPI_ERROR_IS_CONNECTED) {
 | 
			
		||||
                if (ret == NSAPI_ERROR_ALREADY) {
 | 
			
		||||
                    ret = NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
                }
 | 
			
		||||
                return ret;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret = mbedtls_ssl_write(&_ssl, (const unsigned char *) data, size);
 | 
			
		||||
 | 
			
		||||
        if (_timeout == 0) {
 | 
			
		||||
            break;
 | 
			
		||||
        } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) {
 | 
			
		||||
            uint32_t flag;
 | 
			
		||||
            flag = _event_flag.wait_any(1, _timeout);
 | 
			
		||||
            if (flag & osFlagsError) {
 | 
			
		||||
                // Timeout break
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
 | 
			
		||||
            ret == MBEDTLS_ERR_SSL_WANT_READ) {
 | 
			
		||||
        // translate to socket error
 | 
			
		||||
        return NSAPI_ERROR_WOULD_BLOCK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        print_mbedtls_error("mbedtls_ssl_write", ret);
 | 
			
		||||
        return NSAPI_ERROR_DEVICE_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
    return ret; // Assume "non negative errorcode" to be propagated from Socket layer
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -266,15 +336,39 @@ nsapi_size_or_error_t TLSSocketWrapper::recv(void *data, nsapi_size_t size)
 | 
			
		|||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = mbedtls_ssl_read(&_ssl, (unsigned char *) data, size);
 | 
			
		||||
    while (true) {
 | 
			
		||||
        if (!_handshake_completed) {
 | 
			
		||||
            ret = continue_handshake();
 | 
			
		||||
            if (ret != NSAPI_ERROR_IS_CONNECTED) {
 | 
			
		||||
                if (ret == NSAPI_ERROR_ALREADY) {
 | 
			
		||||
                    ret = NSAPI_ERROR_NO_CONNECTION;
 | 
			
		||||
                }
 | 
			
		||||
                return ret;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ret = mbedtls_ssl_read(&_ssl, (unsigned char *) data, size);
 | 
			
		||||
 | 
			
		||||
        if (_timeout == 0) {
 | 
			
		||||
            break;
 | 
			
		||||
        } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) {
 | 
			
		||||
            uint32_t flag;
 | 
			
		||||
            flag = _event_flag.wait_any(1, _timeout);
 | 
			
		||||
            if (flag & osFlagsError) {
 | 
			
		||||
                // Timeout break
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
 | 
			
		||||
            ret == MBEDTLS_ERR_SSL_WANT_READ) {
 | 
			
		||||
        // translate to socket error
 | 
			
		||||
        return NSAPI_ERROR_WOULD_BLOCK;
 | 
			
		||||
    } else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
 | 
			
		||||
        /* MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY is not considered as error.
 | 
			
		||||
         * Just ignre here. Once connection is closed, mbedtls_ssl_read()
 | 
			
		||||
         * Just ignore here. Once connection is closed, mbedtls_ssl_read()
 | 
			
		||||
         * will return 0.
 | 
			
		||||
         */
 | 
			
		||||
        return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -390,7 +484,7 @@ int TLSSocketWrapper::ssl_send(void *ctx, const unsigned char *buf, size_t len)
 | 
			
		|||
    return size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
 | 
			
		||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
 | 
			
		||||
 | 
			
		||||
mbedtls_x509_crt *TLSSocketWrapper::get_own_cert()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -427,7 +521,7 @@ void TLSSocketWrapper::set_ca_chain(mbedtls_x509_crt *crt)
 | 
			
		|||
        _cacert_allocated = false;
 | 
			
		||||
    }
 | 
			
		||||
    _cacert = crt;
 | 
			
		||||
    tr_info("mbedtls_ssl_conf_ca_chain()");
 | 
			
		||||
    tr_debug("mbedtls_ssl_conf_ca_chain()");
 | 
			
		||||
    mbedtls_ssl_conf_ca_chain(get_ssl_config(), _cacert, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -441,7 +535,6 @@ mbedtls_ssl_config *TLSSocketWrapper::get_ssl_config()
 | 
			
		|||
        mbedtls_ssl_config_init(_ssl_conf);
 | 
			
		||||
        _ssl_conf_allocated = true;
 | 
			
		||||
 | 
			
		||||
        tr_info("mbedtls_ssl_config_defaults()");
 | 
			
		||||
        if ((ret = mbedtls_ssl_config_defaults(_ssl_conf,
 | 
			
		||||
                                               MBEDTLS_SSL_IS_CLIENT,
 | 
			
		||||
                                               MBEDTLS_SSL_TRANSPORT_STREAM,
 | 
			
		||||
| 
						 | 
				
			
			@ -454,7 +547,6 @@ mbedtls_ssl_config *TLSSocketWrapper::get_ssl_config()
 | 
			
		|||
        /* It is possible to disable authentication by passing
 | 
			
		||||
         * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode()
 | 
			
		||||
         */
 | 
			
		||||
        tr_info("mbedtls_ssl_conf_authmode()");
 | 
			
		||||
        mbedtls_ssl_conf_authmode(get_ssl_config(), MBEDTLS_SSL_VERIFY_REQUIRED);
 | 
			
		||||
    }
 | 
			
		||||
    return _ssl_conf;
 | 
			
		||||
| 
						 | 
				
			
			@ -470,6 +562,11 @@ void TLSSocketWrapper::set_ssl_config(mbedtls_ssl_config *conf)
 | 
			
		|||
    _ssl_conf = conf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mbedtls_ssl_context *TLSSocketWrapper::get_ssl_context()
 | 
			
		||||
{
 | 
			
		||||
    return &_ssl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocketWrapper::close()
 | 
			
		||||
{
 | 
			
		||||
    if (!_transport) {
 | 
			
		||||
| 
						 | 
				
			
			@ -502,17 +599,18 @@ nsapi_error_t TLSSocketWrapper::close()
 | 
			
		|||
 | 
			
		||||
nsapi_error_t TLSSocketWrapper::connect(const SocketAddress &address)
 | 
			
		||||
{
 | 
			
		||||
    nsapi_error_t ret = NSAPI_ERROR_OK;
 | 
			
		||||
    if (!_transport) {
 | 
			
		||||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (_connect_transport) {
 | 
			
		||||
        nsapi_error_t ret = _transport->connect(address);
 | 
			
		||||
        if (ret) {
 | 
			
		||||
    if (!is_handshake_started() && _connect_transport) {
 | 
			
		||||
        ret = _transport->connect(address);
 | 
			
		||||
        if (ret && ret != NSAPI_ERROR_IS_CONNECTED) {
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return do_handshake();
 | 
			
		||||
    return start_handshake(ret == NSAPI_ERROR_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocketWrapper::bind(const SocketAddress &address)
 | 
			
		||||
| 
						 | 
				
			
			@ -525,18 +623,17 @@ nsapi_error_t TLSSocketWrapper::bind(const SocketAddress &address)
 | 
			
		|||
 | 
			
		||||
void TLSSocketWrapper::set_blocking(bool blocking)
 | 
			
		||||
{
 | 
			
		||||
    if (!_transport) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    _transport->set_blocking(blocking);
 | 
			
		||||
    set_timeout(blocking ? -1 : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TLSSocketWrapper::set_timeout(int timeout)
 | 
			
		||||
{
 | 
			
		||||
    if (!_transport) {
 | 
			
		||||
        return;
 | 
			
		||||
    _timeout = timeout;
 | 
			
		||||
    if (!is_handshake_started() && timeout != -1 && _connect_transport) {
 | 
			
		||||
        // If we have not yet connected the transport, we need to modify its blocking mode as well.
 | 
			
		||||
        // After connection is initiated, it is already set to non blocking mode
 | 
			
		||||
        _transport->set_timeout(timeout);
 | 
			
		||||
    }
 | 
			
		||||
    _transport->set_timeout(timeout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TLSSocketWrapper::sigio(mbed::Callback<void()> func)
 | 
			
		||||
| 
						 | 
				
			
			@ -544,8 +641,8 @@ void TLSSocketWrapper::sigio(mbed::Callback<void()> func)
 | 
			
		|||
    if (!_transport) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    // Allow sigio() to propagate to upper level and handle errors on recv() and send()
 | 
			
		||||
    _transport->sigio(func);
 | 
			
		||||
    _sigio = func;
 | 
			
		||||
    _transport->sigio(mbed::callback(this, &TLSSocketWrapper::event));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocketWrapper::setsockopt(int level, int optname, const void *optval, unsigned optlen)
 | 
			
		||||
| 
						 | 
				
			
			@ -577,6 +674,20 @@ nsapi_error_t TLSSocketWrapper::listen(int)
 | 
			
		|||
    return NSAPI_ERROR_UNSUPPORTED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TLSSocketWrapper::event()
 | 
			
		||||
{
 | 
			
		||||
    _event_flag.set(1);
 | 
			
		||||
    if (_sigio) {
 | 
			
		||||
        _sigio();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool TLSSocketWrapper::is_handshake_started() const
 | 
			
		||||
{
 | 
			
		||||
    return _tls_initialized;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
nsapi_error_t TLSSocketWrapper::getpeername(SocketAddress *address)
 | 
			
		||||
{
 | 
			
		||||
    if (!_handshake_completed) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,8 @@
 | 
			
		|||
#define _MBED_HTTPS_TLS_SOCKET_WRAPPER_H_
 | 
			
		||||
 | 
			
		||||
#include "netsocket/Socket.h"
 | 
			
		||||
 | 
			
		||||
#include "rtos/EventFlags.h"
 | 
			
		||||
#include "platform/Callback.h"
 | 
			
		||||
#include "mbedtls/platform.h"
 | 
			
		||||
#include "mbedtls/ssl.h"
 | 
			
		||||
#include "mbedtls/entropy.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +28,7 @@
 | 
			
		|||
#include "mbedtls/error.h"
 | 
			
		||||
 | 
			
		||||
// This class requires Mbed TLS SSL/TLS client code
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C)
 | 
			
		||||
#if defined(MBEDTLS_SSL_CLI_C) || defined(DOXYGEN_ONLY)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief TLSSocket a wrapper around Socket for interacting with TLS servers
 | 
			
		||||
| 
						 | 
				
			
			@ -134,7 +135,7 @@ public:
 | 
			
		|||
    virtual nsapi_error_t listen(int backlog = 1);
 | 
			
		||||
    virtual nsapi_error_t getpeername(SocketAddress *address);
 | 
			
		||||
 | 
			
		||||
#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(DOXYGEN)
 | 
			
		||||
#if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(DOXYGEN_ONLY)
 | 
			
		||||
    /** Get own certificate directly from Mbed TLS
 | 
			
		||||
     * @return internal Mbed TLS X509 structure
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			@ -167,12 +168,12 @@ public:
 | 
			
		|||
     */
 | 
			
		||||
    void set_ssl_config(mbedtls_ssl_config *conf);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    /**
 | 
			
		||||
     * Helper for pretty-printing mbed TLS error codes
 | 
			
		||||
    /** Get internal Mbed TLS contect structure.
 | 
			
		||||
     * @return SSL context
 | 
			
		||||
     */
 | 
			
		||||
    static void print_mbedtls_error(const char *name, int err);
 | 
			
		||||
    mbedtls_ssl_context *get_ssl_context();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    /** Initiates TLS Handshake
 | 
			
		||||
     *
 | 
			
		||||
     *  Initiates a TLS handshake to a remote peer
 | 
			
		||||
| 
						 | 
				
			
			@ -181,9 +182,28 @@ protected:
 | 
			
		|||
     *  Root CA certification must be set by set_ssl_ca_pem() before
 | 
			
		||||
     *  call this function.
 | 
			
		||||
     *
 | 
			
		||||
     *  For non-blocking purposes, this functions needs to know whether this
 | 
			
		||||
     *  was a first call to Socket::connect() API so that NSAPI_ERROR_INPROGRESS
 | 
			
		||||
     *  does not happen twice.
 | 
			
		||||
     *
 | 
			
		||||
     *  @parameter first_call is this a first call to Socket::connect() API.
 | 
			
		||||
     *  @return         0 on success, negative error code on failure
 | 
			
		||||
     */
 | 
			
		||||
    nsapi_error_t do_handshake();
 | 
			
		||||
    nsapi_error_t start_handshake(bool first_call);
 | 
			
		||||
 | 
			
		||||
    bool is_handshake_started() const;
 | 
			
		||||
 | 
			
		||||
    void event();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    /** Continue already initialised handshake */
 | 
			
		||||
    nsapi_error_t continue_handshake();
 | 
			
		||||
    /**
 | 
			
		||||
     * Helper for pretty-printing mbed TLS error codes
 | 
			
		||||
     */
 | 
			
		||||
    static void print_mbedtls_error(const char *name, int err);
 | 
			
		||||
 | 
			
		||||
#if MBED_CONF_TLS_SOCKET_DEBUG_LEVEL > 0
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -211,13 +231,17 @@ protected:
 | 
			
		|||
     */
 | 
			
		||||
    static int ssl_send(void *ctx, const unsigned char *buf, size_t len);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    mbedtls_ssl_context _ssl;
 | 
			
		||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
 | 
			
		||||
    mbedtls_pk_context _pkctx;
 | 
			
		||||
#endif
 | 
			
		||||
    mbedtls_ctr_drbg_context _ctr_drbg;
 | 
			
		||||
    mbedtls_entropy_context _entropy;
 | 
			
		||||
 | 
			
		||||
    rtos::EventFlags _event_flag;
 | 
			
		||||
    mbed::Callback<void()> _sigio;
 | 
			
		||||
    Socket *_transport;
 | 
			
		||||
    int _timeout;
 | 
			
		||||
 | 
			
		||||
#ifdef MBEDTLS_X509_CRT_PARSE_C
 | 
			
		||||
    mbedtls_x509_crt *_cacert;
 | 
			
		||||
| 
						 | 
				
			
			@ -227,6 +251,7 @@ private:
 | 
			
		|||
 | 
			
		||||
    bool _connect_transport: 1;
 | 
			
		||||
    bool _close_transport: 1;
 | 
			
		||||
    bool _tls_initialized: 1;
 | 
			
		||||
    bool _handshake_completed: 1;
 | 
			
		||||
    bool _cacert_allocated: 1;
 | 
			
		||||
    bool _clicert_allocated: 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,9 +40,12 @@
 | 
			
		|||
#include "netsocket/UDPSocket.h"
 | 
			
		||||
#include "netsocket/TCPSocket.h"
 | 
			
		||||
#include "netsocket/TCPServer.h"
 | 
			
		||||
#include "netsocket/TLSSocketWrapper.h"
 | 
			
		||||
#include "netsocket/DTLSSocketWrapper.h"
 | 
			
		||||
#include "netsocket/TLSSocket.h"
 | 
			
		||||
#include "netsocket/DTLSSocket.h"
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif // __cplusplus
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue