aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/llblowfishcipher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llmessage/llblowfishcipher.cpp')
-rw-r--r--linden/indra/llmessage/llblowfishcipher.cpp154
1 files changed, 154 insertions, 0 deletions
diff --git a/linden/indra/llmessage/llblowfishcipher.cpp b/linden/indra/llmessage/llblowfishcipher.cpp
new file mode 100644
index 0000000..f9a68ab
--- /dev/null
+++ b/linden/indra/llmessage/llblowfishcipher.cpp
@@ -0,0 +1,154 @@
1/**
2 * @file llblowcipher.cpp
3 * @brief Wrapper around OpenSSL Blowfish encryption algorithm.
4 *
5 * We do not have OpenSSL headers or libraries on Windows, so this
6 * class only works on Linux.
7 *
8 * Copyright (c) 2007-2007, Linden Research, Inc.
9 *
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 */
30
31#include "linden_common.h"
32
33#include "llblowfishcipher.h"
34
35
36LLBlowfishCipher::LLBlowfishCipher(const U8* secret, size_t secret_size)
37: LLCipher()
38{
39 llassert(secret);
40
41 mSecretSize = secret_size;
42 mSecret = new U8[mSecretSize];
43 memcpy(mSecret, secret, mSecretSize);
44}
45
46LLBlowfishCipher::~LLBlowfishCipher()
47{
48 delete [] mSecret;
49 mSecret = NULL;
50}
51
52
53#if LL_LINUX
54
55#include <openssl/evp.h>
56
57// virtual
58U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
59{
60 if (!src || !src_len || !dst || !dst_len) return 0;
61 if (src_len > dst_len) return 0;
62
63 // OpenSSL uses "cipher contexts" to hold encryption parameters.
64 EVP_CIPHER_CTX context;
65 EVP_CIPHER_CTX_init(&context);
66
67 // We want a blowfish cyclic block chain cipher, but need to set
68 // the key length before we pass in a key, so call EncryptInit
69 // first with NULLs.
70 EVP_EncryptInit_ex(&context, EVP_bf_cbc(), NULL, NULL, NULL);
71 EVP_CIPHER_CTX_set_key_length(&context, (int)mSecretSize);
72
73 // Complete initialization. Per EVP_EncryptInit man page, the
74 // cipher pointer must be NULL. Apparently initial_vector must
75 // be 8 bytes for blowfish, as this is the block size.
76 unsigned char initial_vector[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
77 EVP_EncryptInit_ex(&context, NULL, NULL, mSecret, initial_vector);
78
79 int blocksize = EVP_CIPHER_CTX_block_size(&context);
80 int keylen = EVP_CIPHER_CTX_key_length(&context);
81 int iv_length = EVP_CIPHER_CTX_iv_length(&context);
82 lldebugs << "LLBlowfishCipher blocksize " << blocksize
83 << " keylen " << keylen
84 << " iv_len " << iv_length
85 << llendl;
86
87 int output_len = 0;
88 if (!EVP_EncryptUpdate(&context,
89 dst,
90 &output_len,
91 src,
92 src_len))
93 {
94 llwarns << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << llendl;
95 return 0;
96 }
97
98 // There may be some final data left to encrypt if the input is
99 // not an exact multiple of the block size.
100 int temp_len = 0;
101 if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len))
102 {
103 llwarns << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << llendl;
104 return 0;
105 }
106 output_len += temp_len;
107 return output_len;
108}
109
110// virtual
111U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
112{
113 llerrs << "LLBlowfishCipher decrypt unsupported" << llendl;
114 return 0;
115}
116
117// virtual
118U32 LLBlowfishCipher::requiredEncryptionSpace(U32 len) const
119{
120 // *HACK: We know blowfish uses an 8 byte block size.
121 // Oddly, sometimes EVP_Encrypt produces an extra block
122 // if the input is an exact multiple of the block size.
123 // So round up.
124 const U32 BLOCK_SIZE = 8;
125 len += BLOCK_SIZE;
126 len -= (len % BLOCK_SIZE);
127 return len;
128}
129
130#else // !LL_LINUX
131
132// virtual
133U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
134{
135 llerrs << "LLBlowfishCipher only supported on Linux" << llendl;
136 return 0;
137}
138
139// virtual
140U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
141{
142 llerrs << "LLBlowfishCipher only supported on Linux" << llendl;
143 return 0;
144}
145
146// virtual
147U32 LLBlowfishCipher::requiredEncryptionSpace(U32 len) const
148{
149 llerrs << "LLBlowfishCipher only supported on Linux" << llendl;
150 return 0;
151}
152
153#endif
154