00001
00002
00003
00004
00005
00006
00007 #include "wvblowfish.h"
00008 #include <assert.h>
00009 #include <openssl/rand.h>
00010 #include <openssl/blowfish.h>
00011
00012
00013
00014 WvBlowfishEncoder::WvBlowfishEncoder(Mode _mode,
00015 const void *_key, size_t _keysize) :
00016 mode(_mode), key(NULL), bfkey(NULL)
00017 {
00018 setkey(_key, _keysize);
00019 }
00020
00021
00022 WvBlowfishEncoder::~WvBlowfishEncoder()
00023 {
00024 deletev key;
00025 delete bfkey;
00026 }
00027
00028
00029 bool WvBlowfishEncoder::_reset()
00030 {
00031 preparekey();
00032 return true;
00033 }
00034
00035
00036 void WvBlowfishEncoder::setkey(const void *_key, size_t _keysize)
00037 {
00038 deletev key;
00039 keysize = _keysize;
00040 key = new unsigned char[keysize];
00041 memcpy(key, _key, keysize);
00042 preparekey();
00043 }
00044
00045
00046 void WvBlowfishEncoder::setiv(const void *_iv)
00047 {
00048 memcpy(ivec, _iv, sizeof(ivec));
00049 ivecoff = 0;
00050 }
00051
00052
00053 void WvBlowfishEncoder::preparekey()
00054 {
00055 delete bfkey;
00056 bfkey = new BF_KEY;
00057 BF_set_key(bfkey, keysize, key);
00058 memset(ivec, 0, sizeof(ivec));
00059 ivecoff = 0;
00060 }
00061
00062
00063 bool WvBlowfishEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
00064 {
00065 size_t len = in.used();
00066 bool success = true;
00067 switch (mode) {
00068 case ECBEncrypt:
00069 case ECBDecrypt:
00070 {
00071 size_t remainder = len & 7;
00072 len -= remainder;
00073 if (remainder != 0 && flush)
00074 {
00075 if (mode == ECBEncrypt)
00076 {
00077
00078 size_t padlen = 8 - remainder;
00079 unsigned char *pad = in.alloc(padlen);
00080 RAND_pseudo_bytes(pad, padlen);
00081 len += 8;
00082 }
00083 else
00084 success = false;
00085 }
00086 }
00087
00088 default:
00089 break;
00090 }
00091 if (len == 0) return success;
00092
00093 const unsigned char *data = in.get(len);
00094 unsigned char *crypt = out.alloc(len);
00095
00096 switch (mode)
00097 {
00098 case ECBEncrypt:
00099 case ECBDecrypt:
00100
00101 while (len >= 8)
00102 {
00103 BF_ecb_encrypt(data, crypt, bfkey,
00104 mode == ECBEncrypt ? BF_ENCRYPT : BF_DECRYPT);
00105 len -= 8;
00106 data += 8;
00107 crypt += 8;
00108 }
00109 break;
00110
00111 case CFBEncrypt:
00112 case CFBDecrypt:
00113
00114 BF_cfb64_encrypt(data, crypt, len, bfkey, ivec, &ivecoff,
00115 mode == CFBEncrypt ? BF_ENCRYPT : BF_DECRYPT);
00116 break;
00117 }
00118 return success;
00119 }
00120
00121
00122
00123
00124 WvBlowfishStream::WvBlowfishStream(WvStream *_cloned,
00125 const void *_key, size_t _keysize,
00126 WvBlowfishEncoder::Mode readmode, WvBlowfishEncoder::Mode writemode) :
00127 WvEncoderStream(_cloned)
00128 {
00129 readchain.append(new WvBlowfishEncoder(readmode,
00130 _key, _keysize), true);
00131 writechain.append(new WvBlowfishEncoder(writemode,
00132 _key, _keysize), true);
00133 }