diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 81cbd3af28d854e2bb606aa6ce39af61ea83067a..ce01511f4e0524a1a17e7f4e6ac252b538298c80 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -7,6 +7,7 @@ include(00-Common)
 include(LLCommon)
 include(Linking)
 include(Boost)
+include(OpenSSL)
 include(LLSharedLibs)
 include(GoogleBreakpad)
 include(GooglePerfTools)
@@ -16,6 +17,7 @@ include(ZLIB)
 include_directories(
     ${EXPAT_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
+    ${OPENSSL_INCLUDE_DIRS}
     ${ZLIB_INCLUDE_DIRS}
     ${BREAKPAD_INCLUDE_DIRECTORIES}
     )
@@ -260,6 +262,7 @@ target_link_libraries(
     ${APRUTIL_LIBRARIES}
     ${APR_LIBRARIES}
     ${EXPAT_LIBRARIES}
+    ${OPENSSL_LIBRARIES}
     ${ZLIB_LIBRARIES}
     ${WINDOWS_LIBRARIES}
     ${BOOST_PROGRAM_OPTIONS_LIBRARY}
@@ -286,7 +289,7 @@ if (LL_TESTS)
   LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")
 
   #set(TEST_DEBUG on)
-  set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES} ${GOOGLEMOCK_LIBRARIES})
+  set(test_libs llcommon ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES} ${GOOGLEMOCK_LIBRARIES} ${OPENSSL_LIBRARIES})
   LL_ADD_INTEGRATION_TEST(commonmisc "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(bitpack "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llbase64 "" "${test_libs}")
diff --git a/indra/llcommon/llbase64.cpp b/indra/llcommon/llbase64.cpp
index a7f6a3a810304adaf28b7afbc8c73cf0412d5d29..cc116259080f09af503db8d9d7da3af5fe164080 100755
--- a/indra/llcommon/llbase64.cpp
+++ b/indra/llcommon/llbase64.cpp
@@ -28,35 +28,30 @@
 #include "linden_common.h"
 
 #include "llbase64.h"
-
+#include <openssl/evp.h>
 #include <string>
 
-#include "apr_base64.h"
-
-
 // static
 std::string LLBase64::encode(const U8* input, size_t input_size)
 {
-	std::string output;
-	if (input
-		&& input_size > 0)
-	{
-		// Yes, it returns int.
-		int b64_buffer_length = apr_base64_encode_len(input_size);
-		char* b64_buffer = new char[b64_buffer_length];
-		
-		// This is faster than apr_base64_encode() if you know
-		// you're not on an EBCDIC machine.  Also, the output is
-		// null terminated, even though the documentation doesn't
-		// specify.  See apr_base64.c for details. JC
-		b64_buffer_length = apr_base64_encode_binary(
-			b64_buffer,
-			input,
-			input_size);
-		output.assign(b64_buffer);
-		delete[] b64_buffer;
-	}
-	return output;
+	if (!(input && input_size > 0)) return LLStringUtil::null;
+	
+	BIO *b64 = BIO_new(BIO_f_base64());
+	BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+	
+	BIO *bio = BIO_new(BIO_s_mem());
+	BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
+	bio = BIO_push(b64, bio);
+	BIO_write(bio, input, input_size);
+	
+	BIO_flush(bio);
+	
+	char *new_data;
+	size_t bytes_written = BIO_get_mem_data(bio, &new_data);
+	std::string result(new_data, bytes_written);
+	BIO_free_all(bio);
+	
+	return result;
 }
 
 // static
@@ -72,13 +67,18 @@ std::string LLBase64::encode(const std::string& in_str)
 // static
 size_t LLBase64::decode(const std::string& input, U8 * buffer, size_t buffer_size)
 {
-	size_t len = apr_base64_decode_len(input.c_str());
-	if (len != buffer_size || buffer_size <= 0 || buffer == 0 || input.empty())
-		return 0;
+	if (input.empty()) return 0;
+	
+	BIO *b64 = BIO_new(BIO_f_base64());
+	BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
 	
-	len = apr_base64_decode_binary(buffer, input.c_str());
+	// BIO_new_mem_buf is not const aware, but it doesn't modify the buffer
+	BIO *bio = BIO_new_mem_buf(const_cast<char*>(input.c_str()), input.length());
+	bio = BIO_push(b64, bio);
+	size_t bytes_written = BIO_read(bio, buffer, buffer_size);
+	BIO_free_all(bio);
 	
-	return len;
+	return bytes_written;
 }
 
 std::string LLBase64::decode(const std::string& input)
@@ -91,8 +91,16 @@ std::string LLBase64::decode(const std::string& input)
 }
 
 // static
-U32 LLBase64::requiredDecryptionSpace(const std::string& str)
+size_t LLBase64::requiredDecryptionSpace(const std::string& str)
 {
-	return apr_base64_decode_len(str.c_str());
+	size_t len = str.length();
+	U32 padding = 0;
+ 
+	if (str[len - 1] == '=' && str[len - 2] == '=') //last two chars are =
+		padding = 2;
+	else if (str[len - 1] == '=') //last char is =
+		padding = 1;
+ 
+	return len * 0.75 - padding;
 }
 
diff --git a/indra/llcommon/llbase64.h b/indra/llcommon/llbase64.h
index 302dde5506a4cf3861d8f386faca4476ed6c43d6..064da10a1f4d348fdd1873e383eaa4f9e45ee53f 100755
--- a/indra/llcommon/llbase64.h
+++ b/indra/llcommon/llbase64.h
@@ -35,7 +35,7 @@ public:
 	static std::string encode(const U8* input, size_t input_size);
 	static size_t decode(const std::string& input, U8 * buffer, size_t buffer_size);
 	static std::string decode(const std::string& input);
-	static U32 requiredDecryptionSpace(const std::string& str);
+	static size_t requiredDecryptionSpace(const std::string& str);
 };
 
 #endif
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 4f84ce974aafa9c46cd35b33183e5608460f792b..4daee3928cb6e23004f895779a0c0b8d1de5d593 100755
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -30,9 +30,9 @@
 #include "llsdserialize.h"
 #include "llpointer.h"
 #include "llstreamtools.h" // for fullread
+#include "llbase64.h"
 
 #include <iostream>
-#include "apr_base64.h"
 
 #ifdef LL_USESYSTEMLIBS
 # include <zlib.h>
@@ -807,12 +807,12 @@ bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
 		get(istr, *(coded_stream.rdbuf()), '\"');
 		c = get(istr);
 		std::string encoded(coded_stream.str());
-		S32 len = apr_base64_decode_len(encoded.c_str());
+		size_t len = LLBase64::requiredDecryptionSpace(encoded);
 		std::vector<U8> value;
 		if(len)
 		{
 			value.resize(len);
-			len = apr_base64_decode_binary(&value[0], encoded.c_str());
+			len = LLBase64::decode(encoded, &value[0], len);
 			value.resize(len);
 		}
 		data = value;
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index 98646facb82d54b597a8c555565658efcbf73731..275a5ed7308d05298c9b3870d9fc16a5ca87c389 100755
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -26,11 +26,11 @@
 
 #include "linden_common.h"
 #include "llsdserialize_xml.h"
+#include "llbase64.h"
 
 #include <iostream>
 #include <deque>
 
-#include "apr_base64.h"
 #include <boost/regex.hpp>
 
 extern "C"
@@ -189,17 +189,8 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
 		}
 		else
 		{
-			// *FIX: memory inefficient.
-			// *TODO: convert to use LLBase64
 			ostr << pre << "<binary encoding=\"base64\">";
-			int b64_buffer_length = apr_base64_encode_len(buffer.size());
-			char* b64_buffer = new char[b64_buffer_length];
-			b64_buffer_length = apr_base64_encode_binary(
-				b64_buffer,
-				&buffer[0],
-				buffer.size());
-			ostr.write(b64_buffer, b64_buffer_length - 1);
-			delete[] b64_buffer;
+			ostr << LLBase64::encode(&buffer[0], buffer.size());
 			ostr << "</binary>" << post;
 		}
 		break;
@@ -780,10 +771,10 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name)
 			boost::regex r;
 			r.assign("\\s");
 			std::string stripped = boost::regex_replace(mCurrentContent, r, "");
-			S32 len = apr_base64_decode_len(stripped.c_str());
+			size_t len = LLBase64::requiredDecryptionSpace(stripped);
 			std::vector<U8> data;
 			data.resize(len);
-			len = apr_base64_decode_binary(&data[0], stripped.c_str());
+			len = LLBase64::decode(stripped, &data[0], len);
 			data.resize(len);
 			value = data;
 			break;
diff --git a/indra/llmessage/llfiltersd2xmlrpc.cpp b/indra/llmessage/llfiltersd2xmlrpc.cpp
index d3e195789bf84222a0dc63d5f2ea13233fa53765..ee331bf63db39d6f9035e8154ff70eeeb5c39100 100755
--- a/indra/llmessage/llfiltersd2xmlrpc.cpp
+++ b/indra/llmessage/llfiltersd2xmlrpc.cpp
@@ -72,11 +72,11 @@
 
 #include "linden_common.h"
 #include "llfiltersd2xmlrpc.h"
+#include "llbase64.h"
 
 #include <sstream>
 #include <iterator>
 #include <xmlrpc-epi/xmlrpc.h>
-#include "apr_base64.h"
 
 #include "llbuffer.h"
 #include "llbufferstream.h"
@@ -267,15 +267,7 @@ void LLFilterSD2XMLRPC::streamOut(std::ostream& ostr, const LLSD& sd)
 		LLSD::Binary buffer = sd.asBinary();
 		if(!buffer.empty())
 		{
-			// *TODO: convert to LLBase64
-			int b64_buffer_length = apr_base64_encode_len(buffer.size());
-			char* b64_buffer = new char[b64_buffer_length];
-			b64_buffer_length = apr_base64_encode_binary(
-				b64_buffer,
-				&buffer[0],
-				buffer.size());
-			ostr.write(b64_buffer, b64_buffer_length - 1);
-			delete[] b64_buffer;
+			ostr << LLBase64::encode(&buffer[0], buffer.size());
 		}
 		ostr << "</base64>";
 		break;
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index e178546675393736799f1b61ecedeede2ab7e79c..e7ca2d940b0baccebe4d62596d0dfdfb76d42e22 100755
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -66,9 +66,6 @@
 
 #include "stringize.h"
 
-// for base64 decoding
-#include "apr_base64.h"
-
 #define USE_SESSION_GROUPS 0
 
 extern LLMenuBarGL* gMenuBarView;
@@ -4480,8 +4477,8 @@ bool LLVivoxVoiceClient::IDFromName(const std::string inName, LLUUID &uuid)
 		LLStringUtil::replaceChar(temp, '-', '+');
 		LLStringUtil::replaceChar(temp, '_', '/');
 
-		U8 rawuuid[UUID_BYTES + 1]; 
-		int len = apr_base64_decode_binary(rawuuid, temp.c_str() + 1);
+		U8 rawuuid[UUID_BYTES + 1];
+		int len = LLBase64::decode(temp, rawuuid, UUID_BYTES + 1);
 		if(len == UUID_BYTES)
 		{
 			// The decode succeeded.  Stuff the bits into the result's UUID
diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp
index 2a8dc153466a7ee12efe56f815d7f027c9774855..3aa2e8c7bcbb3c76fbf592b5425f31655be2d03b 100755
--- a/indra/newview/tests/llsechandler_basic_test.cpp
+++ b/indra/newview/tests/llsechandler_basic_test.cpp
@@ -31,9 +31,9 @@
 #include "../llsechandler_basic.h"
 #include "../../llxml/llcontrol.h"
 #include "../llviewernetwork.h"
+#include "llbase64.h"
 #include "lluuid.h"
 #include "llxorcipher.h"
-#include "apr_base64.h"
 #include <vector>
 #include <ios>
 #include <llsdserialize.h>
@@ -331,7 +331,8 @@ namespace tut
 			   mPemTestCert, test_cert->getPem());
 		std::vector<U8> binary_cert = test_cert->getBinary();
 
-		apr_base64_encode(buffer, (const char *)&binary_cert[0], binary_cert.size());
+		const std::string& tmp = LLBase64::encode(&binary_cert[0], binary_cert.size());
+		std::strcpy(buffer, tmp.c_str());
 		
 		ensure_equals("Der Format is correct", memcmp(buffer, mDerFormat.c_str(), mDerFormat.length()), 0);
 		
@@ -391,8 +392,8 @@ namespace tut
 		"4ZT9Y4wZ9Rh8nnF3fDUL6IGamHe1ClXM1jgBu10F6UMhZbnH4C3aJ2E9+LiOntU+l3iCb2MpkEpr"
 		"82r2ZAMwIrpnirL/xoYoyz7MJQYwUuMvBPToZJrxNSsjI+S2Z+I3iEJAELMAAA==";
 		
-		std::vector<U8> binary_data(apr_base64_decode_len(protected_data.c_str()));
-		apr_base64_decode_binary(&binary_data[0], protected_data.c_str());
+		std::vector<U8> binary_data(LLBase64::requiredDecryptionSpace(protected_data));
+		LLBase64::decode(protected_data, &binary_data[0], binary_data.size());
 
 		LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES);
 		cipher.decrypt(&binary_data[0], 16);
@@ -576,9 +577,9 @@ namespace tut
 		// test loading of an unknown credential with legacy saved password and username
 
 		std::string hashed_password = "fSQcLG03eyIWJmkzfyYaKm81dSweLmsxeSAYKGE7fSQ=";		
-		int length = apr_base64_decode_len(hashed_password.c_str());
-		std::vector<char> decoded_password(length);
-		apr_base64_decode(&decoded_password[0], hashed_password.c_str());
+		size_t length = LLBase64::requiredDecryptionSpace(hashed_password);
+		std::vector<U8> decoded_password(length);
+		LLBase64::decode(hashed_password, &decoded_password[0], length);
 		LLXORCipher cipher(gMACAddress, MAC_ADDRESS_BYTES);
 		cipher.decrypt((U8*)&decoded_password[0], length);
 		unsigned char unique_id[MAC_ADDRESS_BYTES];
@@ -586,7 +587,7 @@ namespace tut
 		LLXORCipher cipher2(unique_id, sizeof(unique_id));
 		cipher2.encrypt((U8*)&decoded_password[0], length);
 		llofstream password_file("test_password.dat", std::ofstream::binary);
-		password_file.write(&decoded_password[0], length); 
+		password_file.write(reinterpret_cast<char*>(&decoded_password[0]), length);
 		password_file.close();
 		
 		my_new_cred = handler->loadCredential("my_legacy_grid2");