Add a CRYPTO_library_init and static-initializer-less build option.

Chromium does not like static initializers, and the CPU logic uses one to
initialize CPU bits. However, the crypto library lacks an explicit
initialization function, which could complicate (no compile-time errors)
porting existing code which uses crypto/, but not ssl/.

Add an explicit CRYPTO_library_init function, but make it a no-op by default.
It only does anything (and is required) if building with
BORINGSSL_NO_STATIC_INITIALIZER.

Change-Id: I6933bdc3447fb382b1f87c788e5b8142d6f3fe39
Reviewed-on: https://boringssl-review.googlesource.com/1770
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 4292781..5d656ec 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -113,6 +113,7 @@
 	crypto
 	STATIC
 
+	crypto.c
 	crypto_error.c
 	mem.c
 	thread.c
diff --git a/crypto/base64/base64_test.c b/crypto/base64/base64_test.c
index 0bee55f..e208e81 100644
--- a/crypto/base64/base64_test.c
+++ b/crypto/base64/base64_test.c
@@ -16,6 +16,7 @@
 #include <string.h>
 
 #include <openssl/base64.h>
+#include <openssl/crypto.h>
 #include <openssl/err.h>
 
 
@@ -117,6 +118,7 @@
 }
 
 int main(void) {
+  CRYPTO_library_init();
   ERR_load_crypto_strings();
 
   if (!test_encode()) {
diff --git a/crypto/bio/bio_test.c b/crypto/bio/bio_test.c
index 75399df..beb3849 100644
--- a/crypto/bio/bio_test.c
+++ b/crypto/bio/bio_test.c
@@ -22,6 +22,7 @@
 #include <unistd.h>
 
 #include <openssl/bio.h>
+#include <openssl/crypto.h>
 #include <openssl/err.h>
 
 
@@ -145,6 +146,7 @@
 }
 
 int main(void) {
+  CRYPTO_library_init();
   ERR_load_crypto_strings();
 
   if (!test_socket_connect()) {
diff --git a/crypto/bn/bn_test.c b/crypto/bn/bn_test.c
index d50b6b5..11b3c62 100644
--- a/crypto/bn/bn_test.c
+++ b/crypto/bn/bn_test.c
@@ -71,6 +71,7 @@
 
 #include <openssl/bio.h>
 #include <openssl/bn.h>
+#include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
@@ -135,6 +136,8 @@
   BIO *out = NULL;
   char *outfile = NULL;
 
+  CRYPTO_library_init();
+
   results = 0;
 
   argc--;
diff --git a/crypto/bytestring/bytestring_test.c b/crypto/bytestring/bytestring_test.c
index 5ea9d48..e4afccd 100644
--- a/crypto/bytestring/bytestring_test.c
+++ b/crypto/bytestring/bytestring_test.c
@@ -15,6 +15,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <openssl/crypto.h>
 #include <openssl/bytestring.h>
 
 #include "internal.h"
@@ -434,6 +435,8 @@
 }
 
 int main(void) {
+  CRYPTO_library_init();
+
   if (!test_skip() ||
       !test_get_u() ||
       !test_get_prefixed() ||
diff --git a/crypto/cipher/aead_test.c b/crypto/cipher/aead_test.c
index f0f3cf4..ff2244c 100644
--- a/crypto/cipher/aead_test.c
+++ b/crypto/cipher/aead_test.c
@@ -18,6 +18,7 @@
 #include <string.h>
 
 #include <openssl/aead.h>
+#include <openssl/crypto.h>
 
 /* This program tests an AEAD against a series of test vectors from a file. The
  * test vector file consists of key-value lines where the key and value are
@@ -155,6 +156,8 @@
   unsigned char bufs[NUM_TYPES][BUF_MAX];
   unsigned int lengths[NUM_TYPES];
 
+  CRYPTO_library_init();
+
   if (argc != 3) {
     fprintf(stderr, "%s <aead> <test file.txt>\n", argv[0]);
     return 1;
diff --git a/crypto/cipher/cipher_test.c b/crypto/cipher/cipher_test.c
index 3dadb8a..b91b505 100644
--- a/crypto/cipher/cipher_test.c
+++ b/crypto/cipher/cipher_test.c
@@ -56,9 +56,10 @@
 
 #include <stdio.h>
 
-#include <openssl/cipher.h>
-#include <openssl/err.h>
 #include <openssl/bio.h>
+#include <openssl/cipher.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
 
 
 static void hexdump(FILE *f, const char *title, const uint8_t *s, int l) {
@@ -331,6 +332,8 @@
   const char *input_file;
   FILE *f;
 
+  CRYPTO_library_init();
+
   if (argc != 2) {
     fprintf(stderr, "%s <test file>\n", argv[0]);
     return 1;
diff --git a/crypto/cpu-intel.c b/crypto/cpu-intel.c
index bc3148f..e2efb2c 100644
--- a/crypto/cpu-intel.c
+++ b/crypto/cpu-intel.c
@@ -78,10 +78,6 @@
 /* OPENSSL_ia32_cpuid is defined in cpu-x86_64-asm.pl. */
 extern uint64_t OPENSSL_ia32_cpuid(uint32_t*);
 
-#if !defined(OPENSSL_WINDOWS)
-void OPENSSL_cpuid_setup(void) __attribute__ ((constructor));
-#endif
-
 /* handle_cpu_env applies the value from |in| to the CPUID values in |out[0]|
  * and |out[1]|. See the comment in |OPENSSL_cpuid_setup| about this. */
 static void handle_cpu_env(uint32_t *out, const char *in) {
@@ -101,14 +97,7 @@
   }
 }
 
-#if defined(OPENSSL_WINDOWS)
-#pragma section(".CRT$XCU", read)
-void __cdecl OPENSSL_cpuid_setup(void);
-__declspec(allocate(".CRT$XCU")) void(*cpuid_constructor)(void) = OPENSSL_cpuid_setup;
-void __cdecl OPENSSL_cpuid_setup(void) {
-#else
 void OPENSSL_cpuid_setup(void) {
-#endif
   const char *env1, *env2;
 
 #if defined(OPENSSL_X86_64)
diff --git a/crypto/crypto.c b/crypto/crypto.c
new file mode 100644
index 0000000..78241da
--- /dev/null
+++ b/crypto/crypto.c
@@ -0,0 +1,60 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/crypto.h>
+
+#include "internal.h"
+
+
+/* Currently, the only configurations which require a static initializer are x86
+ * and x86_64. Don't bother emitting one in other cases. */
+#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64) && \
+    !defined(BORINGSSL_NO_STATIC_INITIALIZER)
+#define BORINGSSL_NO_STATIC_INITIALIZER
+#endif
+
+#if defined(OPENSSL_WINDOWS)
+#define OPENSSL_CDECL __cdecl
+#else
+#define OPENSSL_CDECL
+#endif
+
+#if !defined(BORINGSSL_NO_STATIC_INITIALIZER)
+#if !defined(OPENSSL_WINDOWS)
+static void do_library_init(void) __attribute__ ((constructor));
+#else
+#pragma section(".CRT$XCU", read)
+static void __cdecl do_library_init(void);
+__declspec(allocate(".CRT$XCU")) void(*library_init_constructor)(void) =
+    do_library_init;
+#endif
+#endif  /* !BORINGSSL_NO_STATIC_INITIALIZER */
+
+/* do_library_init is the actual initialization function. If
+ * BORINGSSL_NO_STATIC_INITIALIZER isn't defined, this is set as a static
+ * initializer. Otherwise, it is called by CRYPTO_library_init. */
+static void OPENSSL_CDECL do_library_init(void) {
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+  OPENSSL_cpuid_setup();
+#endif
+}
+
+void CRYPTO_library_init(void) {
+  /* TODO(davidben): It would be tidier if this build knob could be replaced
+   * with an internal lazy-init mechanism that would handle things correctly
+   * in-library. */
+#if defined(BORINGSSL_NO_STATIC_INITIALIZER)
+  do_library_init();
+#endif
+}
diff --git a/crypto/dh/dh_test.c b/crypto/dh/dh_test.c
index 73dbba9..31b3dd9 100644
--- a/crypto/dh/dh_test.c
+++ b/crypto/dh/dh_test.c
@@ -60,6 +60,7 @@
 
 #include <openssl/bio.h>
 #include <openssl/bn.h>
+#include <openssl/crypto.h>
 #include <openssl/mem.h>
 
 #include "internal.h"
@@ -93,6 +94,8 @@
   int i, alen, blen, aout, bout, ret = 1;
   BIO *out;
 
+  CRYPTO_library_init();
+
   out = BIO_new(BIO_s_file());
   if (out == NULL) {
     return 1;
diff --git a/crypto/dsa/dsa_test.c b/crypto/dsa/dsa_test.c
index 8841c12..1edb7e7 100644
--- a/crypto/dsa/dsa_test.c
+++ b/crypto/dsa/dsa_test.c
@@ -61,6 +61,7 @@
 
 #include <openssl/bio.h>
 #include <openssl/bn.h>
+#include <openssl/crypto.h>
 
 #include "internal.h"
 
@@ -107,6 +108,8 @@
   unsigned char sig[256];
   unsigned int siglen;
 
+  CRYPTO_library_init();
+
   bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
   bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
 
diff --git a/crypto/ec/example_mul.c b/crypto/ec/example_mul.c
index d65c3a1..ebb724f 100644
--- a/crypto/ec/example_mul.c
+++ b/crypto/ec/example_mul.c
@@ -68,6 +68,7 @@
 #include <stdio.h>
 
 #include <openssl/bn.h>
+#include <openssl/crypto.h>
 #include <openssl/ec.h>
 #include <openssl/obj.h>
 
@@ -120,6 +121,8 @@
 }
 
 int main(void) {
+  CRYPTO_library_init();
+
   if (!example_EC_POINT_mul()) {
     fprintf(stderr, "failed\n");
     return 1;
diff --git a/crypto/ecdsa/ecdsa_test.c b/crypto/ecdsa/ecdsa_test.c
index 64480e3..e3b1142 100644
--- a/crypto/ecdsa/ecdsa_test.c
+++ b/crypto/ecdsa/ecdsa_test.c
@@ -54,6 +54,7 @@
 
 #include <openssl/bio.h>
 #include <openssl/bn.h>
+#include <openssl/crypto.h>
 #include <openssl/ec.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
@@ -285,10 +286,11 @@
   int ret = 1;
   BIO *out;
 
-  out = BIO_new_fp(stdout, BIO_NOCLOSE);
-
+  CRYPTO_library_init();
   ERR_load_crypto_strings();
 
+  out = BIO_new_fp(stdout, BIO_NOCLOSE);
+
   if (!test_builtin(out))
     goto err;
 
diff --git a/crypto/err/err_test.c b/crypto/err/err_test.c
index 14217f7..230cada 100644
--- a/crypto/err/err_test.c
+++ b/crypto/err/err_test.c
@@ -14,6 +14,7 @@
 
 #include <stdio.h>
 
+#include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
@@ -112,6 +113,8 @@
 }
 
 int main(void) {
+  CRYPTO_library_init();
+
   if (!test_overflow() ||
       !test_put_error() ||
       !test_clear_error() ||
diff --git a/crypto/evp/example_sign.c b/crypto/evp/example_sign.c
index 9d2a296..c25ef2a 100644
--- a/crypto/evp/example_sign.c
+++ b/crypto/evp/example_sign.c
@@ -17,6 +17,7 @@
 #include <stdlib.h>
 
 #include <openssl/bio.h>
+#include <openssl/crypto.h>
 #include <openssl/digest.h>
 #include <openssl/evp.h>
 #include <openssl/rsa.h>
@@ -198,6 +199,8 @@
 }
 
 int main(void) {
+  CRYPTO_library_init();
+
   if (!example_EVP_DigestSignInit()) {
     fprintf(stderr, "EVP_DigestSignInit failed\n");
     return 1;
diff --git a/crypto/hmac/hmac_test.c b/crypto/hmac/hmac_test.c
index e2ae4a6..7b85196 100644
--- a/crypto/hmac/hmac_test.c
+++ b/crypto/hmac/hmac_test.c
@@ -56,6 +56,7 @@
 
 #include <stdio.h>
 
+#include <openssl/crypto.h>
 #include <openssl/digest.h>
 #include <openssl/hmac.h>
 
@@ -124,6 +125,8 @@
   uint8_t out[EVP_MAX_MD_SIZE];
   unsigned out_len;
 
+  CRYPTO_library_init();
+
   for (i = 0; i < NUM_TESTS; i++) {
     const struct test_st *test = &kTests[i];
 
diff --git a/crypto/internal.h b/crypto/internal.h
index 65a52ed..ffac2d5 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -144,6 +144,10 @@
 
 #endif  /* OPENSSL_WINDOWS */
 
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+/* OPENSSL_cpuid_setup initializes OPENSSL_ia32cap_P. */
+void OPENSSL_cpuid_setup(void);
+#endif
 
 #if defined(__cplusplus)
 }  /* extern C */
diff --git a/crypto/lhash/lhash_test.c b/crypto/lhash/lhash_test.c
index 9a94a88..eb40cab 100644
--- a/crypto/lhash/lhash_test.c
+++ b/crypto/lhash/lhash_test.c
@@ -14,6 +14,7 @@
 
 #define _BSD_SOURCE
 
+#include <openssl/crypto.h>
 #include <openssl/lhash.h>
 
 #include <stdio.h>
@@ -113,10 +114,14 @@
 }
 
 int main(int argc, char **argv) {
-  _LHASH *lh = lh_new(NULL, NULL);
+  _LHASH *lh;
   struct dummy_lhash dummy_lh = {NULL};
   unsigned i;
 
+  CRYPTO_library_init();
+
+  lh = lh_new(NULL, NULL);
+
   for (i = 0; i < 100000; i++) {
     unsigned action;
     char *s, *s1, *s2;
diff --git a/crypto/md5/md5_test.c b/crypto/md5/md5_test.c
index eb5984c..fd24341 100644
--- a/crypto/md5/md5_test.c
+++ b/crypto/md5/md5_test.c
@@ -55,8 +55,9 @@
 
 #include <stdio.h>
 
-#include <openssl/md5.h>
+#include <openssl/crypto.h>
 #include <openssl/digest.h>
+#include <openssl/md5.h>
 
 
 static const char *const test[] = {
@@ -78,6 +79,8 @@
   char md_hex[sizeof(md) * 2 + 1];
   int ok = 1;
 
+  CRYPTO_library_init();
+
   for (i = 0; test[i] != NULL; i++) {
     EVP_Digest(test[i], strlen(test[i]), md, NULL, EVP_md5(), NULL);
     for (j = 0; j < sizeof(md); j++) {
diff --git a/crypto/modes/gcm_test.c b/crypto/modes/gcm_test.c
index a112431..5308976 100644
--- a/crypto/modes/gcm_test.c
+++ b/crypto/modes/gcm_test.c
@@ -49,6 +49,7 @@
 #include <stdio.h>
 
 #include <openssl/aes.h>
+#include <openssl/crypto.h>
 #include <openssl/mem.h>
 #include <openssl/modes.h>
 
@@ -417,6 +418,8 @@
   int ret = 0;
   unsigned i;
 
+  CRYPTO_library_init();
+
   for (i = 0; i < sizeof(test_cases) / sizeof(struct test_case); i++) {
     if (!run_test_case(i, &test_cases[i])) {
       ret = 1;
diff --git a/crypto/pkcs8/pkcs12_test.c b/crypto/pkcs8/pkcs12_test.c
index 39ed840..6aea1eb 100644
--- a/crypto/pkcs8/pkcs12_test.c
+++ b/crypto/pkcs8/pkcs12_test.c
@@ -17,6 +17,7 @@
 
 #include <openssl/bio.h>
 #include <openssl/bytestring.h>
+#include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/pkcs8.h>
@@ -705,6 +706,7 @@
 }
 
 int main(int argc, char **argv) {
+  CRYPTO_library_init();
   ERR_load_crypto_strings();
 
   if (!test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
diff --git a/crypto/rsa/rsa_test.c b/crypto/rsa/rsa_test.c
index 897bb61..a5bc366 100644
--- a/crypto/rsa/rsa_test.c
+++ b/crypto/rsa/rsa_test.c
@@ -58,6 +58,7 @@
 
 #include <openssl/bio.h>
 #include <openssl/bn.h>
+#include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/obj.h>
 
@@ -394,6 +395,8 @@
   int num;
   int n;
 
+  CRYPTO_library_init();
+
   plen = sizeof(ptext_ex) - 1;
 
   for (v = 0; v < 3; v++) {
diff --git a/crypto/sha/sha1_test.c b/crypto/sha/sha1_test.c
index a0df062..d723e40 100644
--- a/crypto/sha/sha1_test.c
+++ b/crypto/sha/sha1_test.c
@@ -56,8 +56,9 @@
 
 #include <stdio.h>
 
-#include <openssl/sha.h>
+#include <openssl/crypto.h>
 #include <openssl/digest.h>
+#include <openssl/sha.h>
 
 
 static const char *const test[] = {
@@ -102,6 +103,8 @@
   char md_hex[sizeof(md) * 2 + 1];
   int ok = 1;
 
+  CRYPTO_library_init();
+
   for (i = 0; test[i] != NULL; i++) {
     EVP_Digest(test[i], strlen(test[i]), md, NULL, EVP_sha1(), NULL);
     for (j = 0; j < sizeof(md); j++) {
diff --git a/crypto/x509/pkcs7_test.c b/crypto/x509/pkcs7_test.c
index 9d8adce..2e20c40 100644
--- a/crypto/x509/pkcs7_test.c
+++ b/crypto/x509/pkcs7_test.c
@@ -16,6 +16,7 @@
 #include <stdlib.h>
 
 #include <openssl/bytestring.h>
+#include <openssl/crypto.h>
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
@@ -394,6 +395,8 @@
 }
 
 int main(void) {
+  CRYPTO_library_init();
+
   if (!test_reparse(kPKCS7NSS, sizeof(kPKCS7NSS)) ||
       !test_reparse(kPKCS7Windows, sizeof(kPKCS7Windows))) {
     return 1;
diff --git a/crypto/x509v3/tabtest.c b/crypto/x509v3/tabtest.c
index 06a692e..f783938 100644
--- a/crypto/x509v3/tabtest.c
+++ b/crypto/x509v3/tabtest.c
@@ -62,6 +62,7 @@
 
 #include <stdio.h>
 
+#include <openssl/crypto.h>
 #include <openssl/x509v3.h>
 
 #include "ext_dat.h"
@@ -70,6 +71,7 @@
 {
 	int i, prev = -1, bad = 0;
 	const X509V3_EXT_METHOD **tmp;
+        CRYPTO_library_init();
 	i = sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *);
 	if(i != STANDARD_EXTENSION_COUNT)
 		fprintf(stderr, "Extension number invalid expecting %d\n", i);
diff --git a/crypto/x509v3/v3nametest.c b/crypto/x509v3/v3nametest.c
index 326b1f9..6a2ea85 100644
--- a/crypto/x509v3/v3nametest.c
+++ b/crypto/x509v3/v3nametest.c
@@ -55,6 +55,7 @@
 #include <string.h>
 #include <strings.h>
 
+#include <openssl/crypto.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
@@ -391,6 +392,8 @@
 int
 main(void)
 	{
+	CRYPTO_library_init();
+
 	const struct set_name_fn *pfn = name_fns;
 	while (pfn->name) {
 		const char *const *pname = names;
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index ddb97be..112431e 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -12,12 +12,34 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
-/* This header is provided in order to make compiling against code that expects
-   OpenSSL easier. */
+#ifndef OPENSSL_HEADER_CRYPTO_H
+#define OPENSSL_HEADER_CRYPTO_H
+
+#include <openssl/base.h>
+
+#include <openssl/mem.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* crypto.h contains functions for initializing the crypto library. */
+
+
+/* CRYPTO_library_init initializes the crypto library. It must be called if the
+ * library is built with BORINGSSL_NO_STATIC_INITIALIZER. Otherwise, it does
+ * nothing and a static initializer is used instead. */
+OPENSSL_EXPORT void CRYPTO_library_init(void);
+
+
+#if defined(__cplusplus)
+}  /* extern C */
+#endif
 
 #define CRYPTO_F_CRYPTO_set_ex_data 100
 #define CRYPTO_F_get_class 101
 #define CRYPTO_F_get_new_index 102
 #define CRYPTO_F_get_func_pointers 103
 
-#include "mem.h"
+#endif  /* OPENSSL_HEADER_CRYPTO_H */
diff --git a/ssl/pqueue/CMakeLists.txt b/ssl/pqueue/CMakeLists.txt
index 6049350..b7166b4 100644
--- a/ssl/pqueue/CMakeLists.txt
+++ b/ssl/pqueue/CMakeLists.txt
@@ -14,4 +14,4 @@
 	pqueue_test.c
 )
 
-target_link_libraries(pqueue_test ssl)
+target_link_libraries(pqueue_test ssl crypto)
diff --git a/ssl/pqueue/pqueue_test.c b/ssl/pqueue/pqueue_test.c
index 112afed..16a9ad8 100644
--- a/ssl/pqueue/pqueue_test.c
+++ b/ssl/pqueue/pqueue_test.c
@@ -16,6 +16,7 @@
 #include <string.h>
 
 #include <openssl/pqueue.h>
+#include <openssl/ssl.h>
 
 
 static int trivial() {
@@ -79,6 +80,8 @@
 }
 
 int main(void) {
+  SSL_library_init();
+
   if (!trivial() || !fixed_random()) {
     return 1;
   }
diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c
index 8f7ede6..9308d40 100644
--- a/ssl/ssl_algs.c
+++ b/ssl/ssl_algs.c
@@ -56,11 +56,13 @@
 
 #include "ssl_locl.h"
 
+#include <openssl/crypto.h>
 
 extern const ERR_STRING_DATA SSL_error_string_data[];
 
 int SSL_library_init(void)
 	{
+	CRYPTO_library_init();
 	ERR_load_crypto_strings();
 	ERR_load_strings(SSL_error_string_data);
 	ssl_load_ciphers();