+/*
+ * Perform global initialization of OpenSSL
+ * This function is not thread safe.
+ * Returns: 0 on success
+ * errno on failure
+ */
+int init_crypto (void)
+{
+ int stat = 0;
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+ if ((stat = openssl_init_threads()) != 0) {
+ berrno be;
+ Jmsg1(NULL, M_ABORT, 0,
+ _("Unable to init OpenSSL threading: ERR=%s\n"), be.bstrerror(stat));
+ }
+
+ /* Load libssl and libcrypto human-readable error strings */
+ SSL_load_error_strings();
+
+ /* Initialize OpenSSL SSL library */
+ SSL_library_init();
+
+ /* Register OpenSSL ciphers and digests */
+ OpenSSL_add_all_algorithms();
+#endif
+
+ if (!openssl_seed_prng()) {
+ Jmsg0(NULL, M_ERROR_TERM, 0, _("Failed to seed OpenSSL PRNG\n"));
+ }
+
+ crypto_initialized = true;
+
+ return stat;
+}
+
+/*
+ * Perform global cleanup of OpenSSL
+ * All cryptographic operations must be completed before calling this function.
+ * This function is not thread safe.
+ * Returns: 0 on success
+ * errno on failure
+ */
+int cleanup_crypto (void)
+{
+ /*
+ * Ensure that we've actually been initialized; Doing this here decreases the
+ * complexity of client's termination/cleanup code.
+ */
+ if (!crypto_initialized) {
+ return 0;
+ }
+
+ if (!openssl_save_prng()) {
+ Jmsg0(NULL, M_ERROR, 0, _("Failed to save OpenSSL PRNG\n"));
+ }
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+ openssl_cleanup_threads();
+
+ /* Free libssl and libcrypto error strings */
+ ERR_free_strings();
+
+ /* Free all ciphers and digests */
+ EVP_cleanup();
+
+ /* Free memory used by PRNG */
+ RAND_cleanup();
+#endif
+
+ crypto_initialized = false;
+
+ return 0;
+}
+
+#else
+
+/* Dummy routines */
+int init_crypto (void) { return 0; }
+int cleanup_crypto (void) { return 0; }
+