1 #include <dlfcn.h>
2 #include <errno.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <openssl/provider.h>
6
7 #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
8 #define CRYPTO_LIBRARY "/lib/libcrypto.so.30"
9 static void fbsd_ossl_provider_unload(void);
10 static void print_dlerror(char *);
11 static OSSL_PROVIDER *legacy;
12 static OSSL_PROVIDER *deflt;
13 static int providers_loaded = 0;
14 static OSSL_PROVIDER * (*ossl_provider_load)(OSSL_LIB_CTX *, const char*) = NULL;
15 static int (*ossl_provider_unload)(OSSL_PROVIDER *) = NULL;
16 static void *crypto_lib_handle = NULL;
17
18 static void
fbsd_ossl_provider_unload(void)19 fbsd_ossl_provider_unload(void)
20 {
21 if (ossl_provider_unload == NULL) {
22 if (!(ossl_provider_unload = (int (*)(OSSL_PROVIDER*)) dlsym(crypto_lib_handle, "OSSL_PROVIDER_unload"))) {
23 print_dlerror("Unable to link OSSL_PROVIDER_unload");
24 return;
25 }
26 }
27 if (providers_loaded == 1) {
28 (*ossl_provider_unload)(legacy);
29 (*ossl_provider_unload)(deflt);
30 providers_loaded = 0;
31 }
32 }
33
34 static void
print_dlerror(char * message)35 print_dlerror(char *message)
36 {
37 char *errstr;
38
39 if ((errstr = dlerror()) != NULL)
40 fprintf(stderr, "%s: %s\n",
41 message, errstr);
42 }
43 #endif
44
45 int
fbsd_ossl_provider_load(void)46 fbsd_ossl_provider_load(void)
47 {
48 #if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
49 if (crypto_lib_handle == NULL) {
50 if (!(crypto_lib_handle = dlopen(CRYPTO_LIBRARY,
51 RTLD_LAZY|RTLD_GLOBAL))) {
52 print_dlerror("Unable to load libcrypto.so");
53 return (EINVAL);
54 }
55 }
56 if (ossl_provider_load == NULL) {
57 if (!(ossl_provider_load = (OSSL_PROVIDER * (*)(OSSL_LIB_CTX*, const char *)) dlsym(crypto_lib_handle, "OSSL_PROVIDER_load"))) {
58 print_dlerror("Unable to link OSSL_PROVIDER_load");
59 return(ENOENT);
60 }
61 }
62
63 if (providers_loaded == 0) {
64 if ((legacy = (*ossl_provider_load)(NULL, "legacy")) == NULL)
65 return (EINVAL);
66 if ((deflt = (*ossl_provider_load)(NULL, "default")) == NULL) {
67 (*ossl_provider_unload)(legacy);
68 return (EINVAL);
69 }
70 if (atexit(fbsd_ossl_provider_unload)) {
71 fbsd_ossl_provider_unload();
72 return (errno);
73 }
74 providers_loaded = 1;
75 }
76 #endif
77 return (0);
78 }
79