summaryrefslogtreecommitdiff
path: root/indra/llmessage/llblowfishcipher.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-02-15 20:24:08 +0000
committerJames Cook <james@lindenlab.com>2007-02-15 20:24:08 +0000
commit12ac04231b8d358e70c830f7958f7efbc0f7c0d1 (patch)
tree189b9bc4e3bfa63275cc41be8dc42a28b0f54ffe /indra/llmessage/llblowfishcipher.cpp
parent4feabe4a9caec380cad405d5410bc762c862113d (diff)
merge -r 57761:57967 im-email-session-3, removes database load from IM to email session tracking, introduces new format for email return addresses
Diffstat (limited to 'indra/llmessage/llblowfishcipher.cpp')
-rw-r--r--indra/llmessage/llblowfishcipher.cpp135
1 files changed, 135 insertions, 0 deletions
diff --git a/indra/llmessage/llblowfishcipher.cpp b/indra/llmessage/llblowfishcipher.cpp
new file mode 100644
index 0000000000..0255a654df
--- /dev/null
+++ b/indra/llmessage/llblowfishcipher.cpp
@@ -0,0 +1,135 @@
+/**
+ * @file llblowcipher.cpp
+ * @brief Wrapper around OpenSSL Blowfish encryption algorithm.
+ *
+ * We do not have OpenSSL headers or libraries on Windows, so this
+ * class only works on Linux.
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "llblowfishcipher.h"
+
+
+LLBlowfishCipher::LLBlowfishCipher(const U8* secret, size_t secret_size)
+: LLCipher()
+{
+ llassert(secret);
+
+ mSecretSize = secret_size;
+ mSecret = new U8[mSecretSize];
+ memcpy(mSecret, secret, mSecretSize);
+}
+
+LLBlowfishCipher::~LLBlowfishCipher()
+{
+ delete [] mSecret;
+ mSecret = NULL;
+}
+
+
+#if LL_LINUX
+
+#include <openssl/evp.h>
+
+// virtual
+U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
+{
+ if (!src || !src_len || !dst || !dst_len) return 0;
+ if (src_len > dst_len) return 0;
+
+ // OpenSSL uses "cipher contexts" to hold encryption parameters.
+ EVP_CIPHER_CTX context;
+ EVP_CIPHER_CTX_init(&context);
+
+ // We want a blowfish cyclic block chain cipher, but need to set
+ // the key length before we pass in a key, so call EncryptInit
+ // first with NULLs.
+ EVP_EncryptInit_ex(&context, EVP_bf_cbc(), NULL, NULL, NULL);
+ EVP_CIPHER_CTX_set_key_length(&context, (int)mSecretSize);
+
+ // Complete initialization. Per EVP_EncryptInit man page, the
+ // cipher pointer must be NULL. Apparently initial_vector must
+ // be 8 bytes for blowfish, as this is the block size.
+ unsigned char initial_vector[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ EVP_EncryptInit_ex(&context, NULL, NULL, mSecret, initial_vector);
+
+ int blocksize = EVP_CIPHER_CTX_block_size(&context);
+ int keylen = EVP_CIPHER_CTX_key_length(&context);
+ int iv_length = EVP_CIPHER_CTX_iv_length(&context);
+ lldebugs << "LLBlowfishCipher blocksize " << blocksize
+ << " keylen " << keylen
+ << " iv_len " << iv_length
+ << llendl;
+
+ int output_len = 0;
+ if (!EVP_EncryptUpdate(&context,
+ dst,
+ &output_len,
+ src,
+ src_len))
+ {
+ llwarns << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << llendl;
+ return 0;
+ }
+
+ // There may be some final data left to encrypt if the input is
+ // not an exact multiple of the block size.
+ int temp_len = 0;
+ if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len))
+ {
+ llwarns << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << llendl;
+ return 0;
+ }
+ output_len += temp_len;
+ return output_len;
+}
+
+// virtual
+U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
+{
+ llerrs << "LLBlowfishCipher decrypt unsupported" << llendl;
+ return 0;
+}
+
+// virtual
+U32 LLBlowfishCipher::requiredEncryptionSpace(U32 len) const
+{
+ // *HACK: We know blowfish uses an 8 byte block size.
+ // Oddly, sometimes EVP_Encrypt produces an extra block
+ // if the input is an exact multiple of the block size.
+ // So round up.
+ const U32 BLOCK_SIZE = 8;
+ len += BLOCK_SIZE;
+ len -= (len % BLOCK_SIZE);
+ return len;
+}
+
+#else // !LL_LINUX
+
+// virtual
+U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
+{
+ llerrs << "LLBlowfishCipher only supported on Linux" << llendl;
+ return 0;
+}
+
+// virtual
+U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
+{
+ llerrs << "LLBlowfishCipher only supported on Linux" << llendl;
+ return 0;
+}
+
+// virtual
+U32 LLBlowfishCipher::requiredEncryptionSpace(U32 len) const
+{
+ llerrs << "LLBlowfishCipher only supported on Linux" << llendl;
+ return 0;
+}
+
+#endif
+