diff --git a/programs/.gitignore b/programs/.gitignore index 5d3c5bdc1..d4026071a 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -54,6 +54,7 @@ ssl/ssl_server2 test/benchmark test/cpp_dummy_build test/cpp_dummy_build.cpp +test/dlopen test/ecp-bench test/query_compile_time_config test/selftest diff --git a/programs/Makefile b/programs/Makefile index 550887a12..2a3fd6f25 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -114,6 +114,10 @@ ifdef PTHREAD APPS += ssl/ssl_pthread_server$(EXEXT) endif +ifdef SHARED +APPS += test/dlopen +endif + ifdef TEST_CPP APPS += test/cpp_dummy_build$(EXEXT) endif @@ -318,6 +322,15 @@ test/cpp_dummy_build$(EXEXT): test/cpp_dummy_build.cpp $(DEP) echo " CXX test/cpp_dummy_build.cpp" $(CXX) $(LOCAL_CXXFLAGS) $(CXXFLAGS) test/cpp_dummy_build.cpp $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ +ifdef SHARED +test/dlopen$(EXEXT): test/dlopen.c $(DEP) + echo " CC test/dlopen.c" +# Do not link any test objects (that would bring in a static dependency on +# libmbedcrypto at least). Do not link with libmbed* (that would defeat the +# purpose of testing dynamic loading). + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/dlopen.c $(LDFLAGS) -ldl -o $@ +endif + test/query_config.o: test/query_config.c test/query_config.h $(DEP) echo " CC test/query_config.c" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c test/query_config.c -o $@ @@ -379,6 +392,7 @@ ifndef WINDOWS rm -f $(APPS) -rm -f ssl/ssl_pthread_server$(EXEXT) -rm -f test/cpp_dummy_build.cpp test/cpp_dummy_build$(EXEXT) + -rm -f test/dlopen$(EXEXT) else if exist *.o del /Q /F *.o if exist *.exe del /Q /F *.exe diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt index 04ec7fcac..6233de423 100644 --- a/programs/test/CMakeLists.txt +++ b/programs/test/CMakeLists.txt @@ -35,6 +35,12 @@ if(TEST_CPP) target_link_libraries(cpp_dummy_build ${mbedcrypto_target}) endif() +if(USE_SHARED_MBEDTLS_LIBRARY) + add_executable(dlopen "dlopen.c") + target_include_directories(dlopen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../include) + target_link_libraries(dlopen "-ldl") +endif() + foreach(exe IN LISTS executables_libs executables_mbedcrypto) set(extra_sources "") if(exe STREQUAL "query_compile_time_config") diff --git a/programs/test/dlopen.c b/programs/test/dlopen.c new file mode 100644 index 000000000..e770c3911 --- /dev/null +++ b/programs/test/dlopen.c @@ -0,0 +1,102 @@ +/* + * Test dynamic loading of libmbed* + * + * Copyright The Mbed TLS Contributors + * 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 "mbedtls/config.h" + +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#include +#include +#define mbedtls_fprintf fprintf +#define mbedtls_printf printf +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/x509_crt.h" +#endif + +#define CRYPTO_SO_FILENAME "libmbedcrypto.so" +#define X509_SO_FILENAME "libmbedx509.so" +#define TLS_SO_FILENAME "libmbedtls.so" + +#include + +#define CHECK_DLERROR( function, argument ) \ + do \ + { \ + char *CHECK_DLERROR_error = dlerror ( ); \ + if( CHECK_DLERROR_error != NULL ) \ + { \ + fprintf( stderr, "Dynamic loading error for %s(%s): %s\n", \ + function, argument, CHECK_DLERROR_error ); \ + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); \ + } \ + } \ + while( 0 ) + +int main( void ) +{ + unsigned n; + +#if defined(MBEDTLS_SSL_TLS_C) + void *tls_so = dlopen( TLS_SO_FILENAME, RTLD_NOW ); + CHECK_DLERROR( "dlopen", TLS_SO_FILENAME ); + const int *( *ssl_list_ciphersuites )( void ) = + dlsym( tls_so, "mbedtls_ssl_list_ciphersuites" ); + CHECK_DLERROR( "dlsym", "mbedtls_ssl_list_ciphersuites" ); + const int *ciphersuites = ssl_list_ciphersuites( ); + for( n = 0; ciphersuites[n] != 0; n++ ) + /* nothing to do, we're just counting */; + mbedtls_printf( "%u ciphersuites\n", n ); + dlclose( tls_so ); + CHECK_DLERROR( "dlclose", TLS_SO_FILENAME ); +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + void *x509_so = dlopen( X509_SO_FILENAME, RTLD_NOW ); + CHECK_DLERROR( "dlopen", X509_SO_FILENAME ); + const mbedtls_x509_crt_profile *profile = + dlsym( x509_so, "mbedtls_x509_crt_profile_default" ); + CHECK_DLERROR( "dlsym", "mbedtls_x509_crt_profile_default" ); + mbedtls_printf( "Allowed md mask: %08x\n", + (unsigned) profile->allowed_mds ); + dlclose( x509_so ); + CHECK_DLERROR( "dlclose", X509_SO_FILENAME ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_MD_C) + void *crypto_so = dlopen( CRYPTO_SO_FILENAME, RTLD_NOW ); + CHECK_DLERROR( "dlopen", CRYPTO_SO_FILENAME ); + const int *( *md_list )( void ) = + dlsym( crypto_so, "mbedtls_md_list" ); + CHECK_DLERROR( "dlsym", "mbedtls_md_list" ); + const int *mds = md_list( ); + for( n = 0; mds[n] != 0; n++ ) + /* nothing to do, we're just counting */; + mbedtls_printf( "%u hashes\n", n ); + dlclose( crypto_so ); + CHECK_DLERROR( "dlclose", CRYPTO_SO_FILENAME ); +#endif /* MBEDTLS_MD_C */ + + return( 0 ); +} +