WvStreams
|
00001 /* 00002 * Worldvisions Tunnel Vision Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * Blowfish cryptography abstractions. 00006 */ 00007 #include "wvblowfish.h" 00008 #include <assert.h> 00009 #include <openssl/rand.h> 00010 #include <openssl/blowfish.h> 00011 00012 /***** WvBlowfishEncoder ****/ 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 // if flushing on encryption, add some randomized padding 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 // nothing we can do here, flushing does not make sense! 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 // ECB works 64bits at a time 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 // CFB simulates a stream 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 /***** WvBlowfishStream *****/ 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 }