00001
00002
00003
00004
00005
00006
00007 #include "wvtripledes.h"
00008 #include <assert.h>
00009 #include <openssl/rand.h>
00010
00011
00012
00013 WvTripleDESEncoder::WvTripleDESEncoder(Mode _mode, const void *_key1,
00014 const void *_key2, const void *_key3) :
00015 mode(_mode)
00016 {
00017 setkey(_key1, _key2, _key3);
00018 }
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 bool WvTripleDESEncoder::_reset()
00031 {
00032 memset(ivec, 0, sizeof(ivec));
00033 ivecoff = 0;
00034 return true;
00035 }
00036
00037
00038 void WvTripleDESEncoder::setkey(const void *_key1, const void *_key2,
00039 const void *_key3)
00040 {
00041 memcpy(key, _key1, DES_KEY_SZ);
00042 DES_set_key(&key, &deskey1);
00043
00044 memcpy(key, _key2, DES_KEY_SZ);
00045 DES_set_key(&key, &deskey2);
00046
00047 memcpy(key, _key3, DES_KEY_SZ);
00048 DES_set_key(&key, &deskey3);
00049
00050 memset(ivec, 0, sizeof(ivec));
00051 ivecoff = 0;
00052 }
00053
00054
00055 void WvTripleDESEncoder::setiv(const void *_iv)
00056 {
00057 memcpy(ivec, _iv, sizeof(ivec));
00058 ivecoff = 0;
00059 }
00060
00061 bool WvTripleDESEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
00062 {
00063 size_t len = in.used();
00064 bool success = true;
00065 switch (mode) {
00066 case ECBEncrypt:
00067 case ECBDecrypt:
00068 case CBCEncrypt:
00069 case CBCDecrypt:
00070 {
00071 size_t remainder = len & 7;
00072 len -= remainder;
00073 if (remainder != 0 && flush)
00074 {
00075 if (mode == ECBEncrypt || mode == CBCEncrypt)
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
00092 if (len == 0)
00093 return success;
00094
00095 const unsigned char *data = in.get(len);
00096 unsigned char *crypt = out.alloc(len);
00097
00098 switch (mode)
00099 {
00100 case ECBEncrypt:
00101 case ECBDecrypt:
00102
00103 while (len >= 8)
00104 {
00105 #if OPENSSL_VERSION_NUMBER >= 0x0090705FL
00106 DES_ecb3_encrypt(data, crypt,
00107 &deskey1, &deskey2, &deskey3,
00108 mode == ECBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
00109 #else
00110 DES_ecb3_encrypt(reinterpret_cast<const_DES_cblock*>(&data),
00111 reinterpret_cast<DES_cblock*>(&crypt),
00112 &deskey1, &deskey2, &deskey3,
00113 mode == ECBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
00114 #endif
00115 len -= 8;
00116 data += 8;
00117 crypt += 8;
00118 }
00119 break;
00120
00121 case CFBEncrypt:
00122 case CFBDecrypt:
00123
00124 DES_ede3_cfb64_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
00125 &ivec, &ivecoff,
00126 mode == CFBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
00127 break;
00128 case CBCEncrypt:
00129 DES_ede3_cbc_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
00130 &ivec, DES_ENCRYPT);
00131 break;
00132 case CBCDecrypt:
00133 DES_ede3_cbc_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
00134 &ivec, DES_DECRYPT);
00135 break;
00136 }
00137 return success;
00138 }
00139
00140
00141
00142
00143 WvTripleDESStream::WvTripleDESStream(WvStream *_cloned, const void *_key1,
00144 const void *_key2, const void *_key3,
00145 WvTripleDESEncoder::Mode readmode,
00146 WvTripleDESEncoder::Mode writemode) :
00147 WvEncoderStream(_cloned)
00148 {
00149 readchain.append(new WvTripleDESEncoder(readmode,
00150 _key1, _key2, _key3), true);
00151 writechain.append(new WvTripleDESEncoder(writemode,
00152 _key1, _key2, _key3), true);
00153 }