llblowfishcipher.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 #include "llblowfishcipher.h"
00034 #include <openssl/evp.h>
00035 
00036 
00037 LLBlowfishCipher::LLBlowfishCipher(const U8* secret, size_t secret_size)
00038 :       LLCipher()
00039 {
00040         llassert(secret);
00041 
00042         mSecretSize = secret_size;
00043         mSecret = new U8[mSecretSize];
00044         memcpy(mSecret, secret, mSecretSize);
00045 }
00046 
00047 LLBlowfishCipher::~LLBlowfishCipher()
00048 {
00049         delete [] mSecret;
00050         mSecret = NULL;
00051 }
00052 
00053 // virtual
00054 U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
00055 {
00056         if (!src || !src_len || !dst || !dst_len) return 0;
00057         if (src_len > dst_len) return 0;
00058 
00059         // OpenSSL uses "cipher contexts" to hold encryption parameters.
00060     EVP_CIPHER_CTX context;
00061     EVP_CIPHER_CTX_init(&context);
00062 
00063         // We want a blowfish cyclic block chain cipher, but need to set 
00064         // the key length before we pass in a key, so call EncryptInit 
00065         // first with NULLs.
00066         EVP_EncryptInit_ex(&context, EVP_bf_cbc(), NULL, NULL, NULL);
00067         EVP_CIPHER_CTX_set_key_length(&context, (int)mSecretSize);
00068         
00069         // Complete initialization.  Per EVP_EncryptInit man page, the
00070         // cipher pointer must be NULL.  Apparently initial_vector must
00071         // be 8 bytes for blowfish, as this is the block size.
00072     unsigned char initial_vector[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
00073         EVP_EncryptInit_ex(&context, NULL, NULL, mSecret, initial_vector);
00074 
00075     int blocksize = EVP_CIPHER_CTX_block_size(&context);
00076     int keylen = EVP_CIPHER_CTX_key_length(&context);
00077     int iv_length = EVP_CIPHER_CTX_iv_length(&context);
00078     lldebugs << "LLBlowfishCipher blocksize " << blocksize
00079                 << " keylen " << keylen
00080                 << " iv_len " << iv_length
00081                 << llendl;
00082 
00083         int output_len = 0;
00084         int temp_len = 0;
00085         if (!EVP_EncryptUpdate(&context,
00086                         dst,
00087                         &output_len,
00088                         src,
00089                         src_len))
00090         {
00091                 llwarns << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << llendl;
00092                 goto ERROR;
00093         }
00094 
00095         // There may be some final data left to encrypt if the input is
00096         // not an exact multiple of the block size.
00097         if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len))
00098         {
00099                 llwarns << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << llendl;
00100                 goto ERROR;
00101         }
00102         output_len += temp_len;
00103 
00104         EVP_CIPHER_CTX_cleanup(&context);
00105         return output_len;
00106 
00107 ERROR:
00108         EVP_CIPHER_CTX_cleanup(&context);
00109         return 0;
00110 }
00111 
00112 // virtual
00113 U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
00114 {
00115         llerrs << "LLBlowfishCipher decrypt unsupported" << llendl;
00116         return 0;
00117 }
00118 
00119 // virtual
00120 U32 LLBlowfishCipher::requiredEncryptionSpace(U32 len) const
00121 {
00122         // *HACK: We know blowfish uses an 8 byte block size.
00123         // Oddly, sometimes EVP_Encrypt produces an extra block
00124         // if the input is an exact multiple of the block size.
00125         // So round up.
00126         const U32 BLOCK_SIZE = 8;
00127         len += BLOCK_SIZE;
00128         len -= (len % BLOCK_SIZE);
00129         return len;
00130 }

Generated on Fri May 16 08:32:21 2008 for SecondLife by  doxygen 1.5.5