diff options
author | James Cook <james@lindenlab.com> | 2007-02-15 20:24:08 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-02-15 20:24:08 +0000 |
commit | 12ac04231b8d358e70c830f7958f7efbc0f7c0d1 (patch) | |
tree | 189b9bc4e3bfa63275cc41be8dc42a28b0f54ffe /indra/llmessage/llblowfishcipher.cpp | |
parent | 4feabe4a9caec380cad405d5410bc762c862113d (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.cpp | 135 |
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 + |