security: insert OpenSSL initialization call in PrivateKey::loadPkcs8

Change-Id: I71dc0c3ac71fa5db4f3be8ce51aea06e4cf7c088
Refs: #4204
diff --git a/src/security/transform/private-key.cpp b/src/security/transform/private-key.cpp
index 9cad918..c67d3d9 100644
--- a/src/security/transform/private-key.cpp
+++ b/src/security/transform/private-key.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -41,6 +41,18 @@
 namespace security {
 namespace transform {
 
+static void
+opensslInitAlgorithms()
+{
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL
+  static bool isInitialized = false;
+  if (!isInitialized) {
+    OpenSSL_add_all_algorithms();
+    isInitialized = true;
+  }
+#endif // OPENSSL_VERSION_NUMBER < 0x1010000fL
+}
+
 class PrivateKey::Impl
 {
 public:
@@ -104,6 +116,7 @@
 PrivateKey::loadPkcs8(const uint8_t* buf, size_t size, const char* pw, size_t pwLen)
 {
   BOOST_ASSERT(std::strlen(pw) == pwLen);
+  opensslInitAlgorithms();
 
   detail::Bio mem(BIO_s_mem());
   BIO_write(mem.get(), buf, size);
@@ -116,14 +129,16 @@
 static inline int
 passwordCallback(char* buf, int size, int rwflag, void* u)
 {
+  BOOST_ASSERT(size >= 0);
   auto cb = reinterpret_cast<PrivateKey::PasswordCallback*>(u);
-  return (*cb)(buf, size, rwflag);
+  return (*cb)(buf, static_cast<size_t>(size), rwflag);
 }
 
 void
 PrivateKey::loadPkcs8(const uint8_t* buf, size_t size, PasswordCallback pwCallback)
 {
-  OpenSSL_add_all_algorithms();
+  opensslInitAlgorithms();
+
   detail::Bio mem(BIO_s_mem());
   BIO_write(mem.get(), buf, size);
 
@@ -246,10 +261,10 @@
 #else
   switch (EVP_PKEY_base_id(m_impl->key)) {
 #endif // OPENSSL_VERSION_NUMBER < 0x1010000fL
-  case EVP_PKEY_RSA:
-    return rsaDecrypt(cipherText, cipherLen);
-  default:
-    BOOST_THROW_EXCEPTION(Error("Decryption is not supported for this key type"));
+    case EVP_PKEY_RSA:
+      return rsaDecrypt(cipherText, cipherLen);
+    default:
+      BOOST_THROW_EXCEPTION(Error("Decryption is not supported for this key type"));
   }
 }
 
@@ -263,8 +278,8 @@
 PrivateKey::toPkcs1() const
 {
   ENSURE_PRIVATE_KEY_LOADED(m_impl->key);
+  opensslInitAlgorithms();
 
-  OpenSSL_add_all_algorithms();
   detail::Bio mem(BIO_s_mem());
   int ret = i2d_PrivateKey_bio(mem.get(), m_impl->key);
   if (ret != 1)
@@ -280,11 +295,10 @@
 ConstBufferPtr
 PrivateKey::toPkcs8(const char* pw, size_t pwLen) const
 {
-  ENSURE_PRIVATE_KEY_LOADED(m_impl->key);
-
   BOOST_ASSERT(std::strlen(pw) == pwLen);
+  ENSURE_PRIVATE_KEY_LOADED(m_impl->key);
+  opensslInitAlgorithms();
 
-  OpenSSL_add_all_algorithms();
   detail::Bio mem(BIO_s_mem());
   int ret = i2d_PKCS8PrivateKey_bio(mem.get(), m_impl->key, EVP_des_cbc(),
                                     const_cast<char*>(pw), pwLen, nullptr, nullptr);
@@ -302,8 +316,8 @@
 PrivateKey::toPkcs8(PasswordCallback pwCallback) const
 {
   ENSURE_PRIVATE_KEY_LOADED(m_impl->key);
+  opensslInitAlgorithms();
 
-  OpenSSL_add_all_algorithms();
   detail::Bio mem(BIO_s_mem());
   int ret = i2d_PKCS8PrivateKey_bio(mem.get(), m_impl->key, EVP_des_cbc(),
                                     nullptr, 0,