blob: 9aba73308c4424e90b8a58bc00f615fee75b8f27 [file] [log] [blame]
Gilles Peskinea7c247e2021-11-04 12:45:19 +01001/*
2 * Test dynamic loading of libmbed*
3 *
4 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Gilles Peskinea7c247e2021-11-04 12:45:19 +01006 */
7
Felix Conway998760a2025-03-24 11:37:33 +00008#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
9
Gilles Peskinea7c247e2021-11-04 12:45:19 +010010#include "mbedtls/build_info.h"
11
12#include "mbedtls/platform.h"
Gilles Peskinea7c247e2021-11-04 12:45:19 +010013
14#if defined(MBEDTLS_X509_CRT_PARSE_C)
15#include "mbedtls/x509_crt.h"
16#endif
17
Gilles Peskine834d2292021-11-12 14:30:22 +010018#if defined(__APPLE__)
19#define SO_SUFFIX ".dylib"
20#else
21#define SO_SUFFIX ".so"
22#endif
23
Ronald Cron8126a682024-10-25 17:34:23 +020024#define MBEDCRYPTO_SO_FILENAME "libmbedcrypto" SO_SUFFIX
25#define TFPSACRYPTO_SO_FILENAME "libtfpsacrypto" SO_SUFFIX
Gilles Peskine834d2292021-11-12 14:30:22 +010026#define X509_SO_FILENAME "libmbedx509" SO_SUFFIX
27#define TLS_SO_FILENAME "libmbedtls" SO_SUFFIX
Gilles Peskinea7c247e2021-11-04 12:45:19 +010028
29#include <dlfcn.h>
30
Gilles Peskine449bd832023-01-11 14:50:10 +010031#define CHECK_DLERROR(function, argument) \
Gilles Peskinea7c247e2021-11-04 12:45:19 +010032 do \
33 { \
Gilles Peskine449bd832023-01-11 14:50:10 +010034 char *CHECK_DLERROR_error = dlerror(); \
35 if (CHECK_DLERROR_error != NULL) \
Gilles Peskinea7c247e2021-11-04 12:45:19 +010036 { \
Gilles Peskine449bd832023-01-11 14:50:10 +010037 fprintf(stderr, "Dynamic loading error for %s(%s): %s\n", \
38 function, argument, CHECK_DLERROR_error); \
39 mbedtls_exit(MBEDTLS_EXIT_FAILURE); \
Gilles Peskinea7c247e2021-11-04 12:45:19 +010040 } \
41 } \
Gilles Peskine449bd832023-01-11 14:50:10 +010042 while (0)
Gilles Peskinea7c247e2021-11-04 12:45:19 +010043
Gilles Peskine449bd832023-01-11 14:50:10 +010044int main(void)
Gilles Peskinea7c247e2021-11-04 12:45:19 +010045{
Gilles Peskineb6a02992021-11-10 19:11:32 +010046#if defined(MBEDTLS_MD_C) || defined(MBEDTLS_SSL_TLS_C)
Gilles Peskinea7c247e2021-11-04 12:45:19 +010047 unsigned n;
Gilles Peskineb6a02992021-11-10 19:11:32 +010048#endif
Gilles Peskinea7c247e2021-11-04 12:45:19 +010049
50#if defined(MBEDTLS_SSL_TLS_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010051 void *tls_so = dlopen(TLS_SO_FILENAME, RTLD_NOW);
52 CHECK_DLERROR("dlopen", TLS_SO_FILENAME);
Gilles Peskine06af4172025-01-08 17:26:01 +010053#pragma GCC diagnostic push
54 /* dlsym() returns an object pointer which is meant to be used as a
55 * function pointer. This has undefined behavior in standard C, so
56 * "gcc -std=c99 -pedantic" complains about it, but it is perfectly
57 * fine on platforms that have dlsym(). */
58#pragma GCC diagnostic ignored "-Wpedantic"
Gilles Peskine449bd832023-01-11 14:50:10 +010059 const int *(*ssl_list_ciphersuites)(void) =
60 dlsym(tls_so, "mbedtls_ssl_list_ciphersuites");
Gilles Peskine06af4172025-01-08 17:26:01 +010061#pragma GCC diagnostic pop
Gilles Peskine449bd832023-01-11 14:50:10 +010062 CHECK_DLERROR("dlsym", "mbedtls_ssl_list_ciphersuites");
63 const int *ciphersuites = ssl_list_ciphersuites();
64 for (n = 0; ciphersuites[n] != 0; n++) {/* nothing to do, we're just counting */
65 ;
66 }
67 mbedtls_printf("dlopen(%s): %u ciphersuites\n",
68 TLS_SO_FILENAME, n);
69 dlclose(tls_so);
70 CHECK_DLERROR("dlclose", TLS_SO_FILENAME);
Gilles Peskinea7c247e2021-11-04 12:45:19 +010071#endif /* MBEDTLS_SSL_TLS_C */
72
73#if defined(MBEDTLS_X509_CRT_PARSE_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010074 void *x509_so = dlopen(X509_SO_FILENAME, RTLD_NOW);
75 CHECK_DLERROR("dlopen", X509_SO_FILENAME);
Gilles Peskinea7c247e2021-11-04 12:45:19 +010076 const mbedtls_x509_crt_profile *profile =
Gilles Peskine449bd832023-01-11 14:50:10 +010077 dlsym(x509_so, "mbedtls_x509_crt_profile_default");
78 CHECK_DLERROR("dlsym", "mbedtls_x509_crt_profile_default");
79 mbedtls_printf("dlopen(%s): Allowed md mask: %08x\n",
80 X509_SO_FILENAME, (unsigned) profile->allowed_mds);
81 dlclose(x509_so);
82 CHECK_DLERROR("dlclose", X509_SO_FILENAME);
Gilles Peskinea7c247e2021-11-04 12:45:19 +010083#endif /* MBEDTLS_X509_CRT_PARSE_C */
84
85#if defined(MBEDTLS_MD_C)
Ronald Cron8126a682024-10-25 17:34:23 +020086 const char *crypto_so_filename = NULL;
87 void *crypto_so = dlopen(MBEDCRYPTO_SO_FILENAME, RTLD_NOW);
88 if (dlerror() == NULL) {
89 crypto_so_filename = MBEDCRYPTO_SO_FILENAME;
90 } else {
91 crypto_so = dlopen(TFPSACRYPTO_SO_FILENAME, RTLD_NOW);
92 CHECK_DLERROR("dlopen", TFPSACRYPTO_SO_FILENAME);
93 crypto_so_filename = TFPSACRYPTO_SO_FILENAME;
94 }
Gilles Peskine06af4172025-01-08 17:26:01 +010095#pragma GCC diagnostic push
96 /* dlsym() returns an object pointer which is meant to be used as a
97 * function pointer. This has undefined behavior in standard C, so
98 * "gcc -std=c99 -pedantic" complains about it, but it is perfectly
99 * fine on platforms that have dlsym(). */
100#pragma GCC diagnostic ignored "-Wpedantic"
Ari Weiler-Ofekabcfd4c2025-06-17 15:18:20 +0100101 psa_status_t (*dyn_psa_crypto_init)(void) =
102 dlsym(crypto_so, "psa_crypto_init");
103 psa_status_t (*dyn_psa_hash_compute)(psa_algorithm_t, const uint8_t *, size_t, uint8_t *,
104 size_t, size_t *) =
105 dlsym(crypto_so, "psa_hash_compute");
106
Gilles Peskine06af4172025-01-08 17:26:01 +0100107#pragma GCC diagnostic pop
Ari Weiler-Ofekabcfd4c2025-06-17 15:18:20 +0100108 /* Use psa_hash_compute from PSA Crypto API instead of deprecated mbedtls_md_list()
109 * to demonstrate runtime linking of libmbedcrypto / libtfpsacrypto */
110
111 CHECK_DLERROR("dlsym", "psa_crypto_init");
112 CHECK_DLERROR("dlsym", "psa_hash_compute");
113
114 psa_status_t status = dyn_psa_crypto_init();
115 if (status != PSA_SUCCESS) {
116 mbedtls_fprintf(stderr, "psa_crypto_init failed: %d\n", (int) status);
117 mbedtls_exit(MBEDTLS_EXIT_FAILURE);
Gilles Peskine449bd832023-01-11 14:50:10 +0100118 }
Ari Weiler-Ofekabcfd4c2025-06-17 15:18:20 +0100119
120 const uint8_t input[] = "hello world";
121 uint8_t hash[32]; // Buffer to hold the output hash
122 size_t hash_len = 0;
123
124 status = dyn_psa_hash_compute(PSA_ALG_SHA_256,
125 input, sizeof(input) - 1,
126 hash, sizeof(hash),
127 &hash_len);
128 if (status != PSA_SUCCESS) {
129 mbedtls_fprintf(stderr, "psa_hash_compute failed: %d\n", (int) status);
130 mbedtls_exit(MBEDTLS_EXIT_FAILURE);
131 }
132
133 mbedtls_printf("dlopen(%s): psa_hash_compute succeeded. SHA-256 output length: %zu\n",
134 crypto_so_filename, hash_len);
135
136
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 dlclose(crypto_so);
Ronald Cron8126a682024-10-25 17:34:23 +0200138 CHECK_DLERROR("dlclose", crypto_so_filename);
Gilles Peskinea7c247e2021-11-04 12:45:19 +0100139#endif /* MBEDTLS_MD_C */
140
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 return 0;
Gilles Peskinea7c247e2021-11-04 12:45:19 +0100142}