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