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