PageRenderTime 22ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmessage/llblowfishcipher.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 125 lines | 68 code | 16 blank | 41 comment | 7 complexity | a79fd098ece6f8cc22644919f011bab1 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llblowfishcipher.cpp
  3. * @brief Wrapper around OpenSSL Blowfish encryption algorithm.
  4. *
  5. * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "llblowfishcipher.h"
  28. #include <openssl/evp.h>
  29. LLBlowfishCipher::LLBlowfishCipher(const U8* secret, size_t secret_size)
  30. : LLCipher()
  31. {
  32. llassert(secret);
  33. mSecretSize = secret_size;
  34. mSecret = new U8[mSecretSize];
  35. memcpy(mSecret, secret, mSecretSize);
  36. }
  37. LLBlowfishCipher::~LLBlowfishCipher()
  38. {
  39. delete [] mSecret;
  40. mSecret = NULL;
  41. }
  42. // virtual
  43. U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
  44. {
  45. if (!src || !src_len || !dst || !dst_len) return 0;
  46. if (src_len > dst_len) return 0;
  47. // OpenSSL uses "cipher contexts" to hold encryption parameters.
  48. EVP_CIPHER_CTX context;
  49. EVP_CIPHER_CTX_init(&context);
  50. // We want a blowfish cyclic block chain cipher, but need to set
  51. // the key length before we pass in a key, so call EncryptInit
  52. // first with NULLs.
  53. EVP_EncryptInit_ex(&context, EVP_bf_cbc(), NULL, NULL, NULL);
  54. EVP_CIPHER_CTX_set_key_length(&context, (int)mSecretSize);
  55. // Complete initialization. Per EVP_EncryptInit man page, the
  56. // cipher pointer must be NULL. Apparently initial_vector must
  57. // be 8 bytes for blowfish, as this is the block size.
  58. unsigned char initial_vector[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  59. EVP_EncryptInit_ex(&context, NULL, NULL, mSecret, initial_vector);
  60. int blocksize = EVP_CIPHER_CTX_block_size(&context);
  61. int keylen = EVP_CIPHER_CTX_key_length(&context);
  62. int iv_length = EVP_CIPHER_CTX_iv_length(&context);
  63. lldebugs << "LLBlowfishCipher blocksize " << blocksize
  64. << " keylen " << keylen
  65. << " iv_len " << iv_length
  66. << llendl;
  67. int output_len = 0;
  68. int temp_len = 0;
  69. if (!EVP_EncryptUpdate(&context,
  70. dst,
  71. &output_len,
  72. src,
  73. src_len))
  74. {
  75. llwarns << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << llendl;
  76. goto ERROR;
  77. }
  78. // There may be some final data left to encrypt if the input is
  79. // not an exact multiple of the block size.
  80. if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len))
  81. {
  82. llwarns << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << llendl;
  83. goto ERROR;
  84. }
  85. output_len += temp_len;
  86. EVP_CIPHER_CTX_cleanup(&context);
  87. return output_len;
  88. ERROR:
  89. EVP_CIPHER_CTX_cleanup(&context);
  90. return 0;
  91. }
  92. // virtual
  93. U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
  94. {
  95. llerrs << "LLBlowfishCipher decrypt unsupported" << llendl;
  96. return 0;
  97. }
  98. // virtual
  99. U32 LLBlowfishCipher::requiredEncryptionSpace(U32 len) const
  100. {
  101. // *HACK: We know blowfish uses an 8 byte block size.
  102. // Oddly, sometimes EVP_Encrypt produces an extra block
  103. // if the input is an exact multiple of the block size.
  104. // So round up.
  105. const U32 BLOCK_SIZE = 8;
  106. len += BLOCK_SIZE;
  107. len -= (len % BLOCK_SIZE);
  108. return len;
  109. }