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 && OPENSSL_VERSION_NUMBER < 0x0090800fL
00107 DES_ecb3_encrypt(data, crypt,
00108 &deskey1, &deskey2, &deskey3,
00109 mode == ECBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
00110 #else
00111 DES_ecb3_encrypt(reinterpret_cast<const_DES_cblock*>(&data),
00112 reinterpret_cast<DES_cblock*>(&crypt),
00113 &deskey1, &deskey2, &deskey3,
00114 mode == ECBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
00115 #endif
00116 len -= 8;
00117 data += 8;
00118 crypt += 8;
00119 }
00120 break;
00121
00122 case CFBEncrypt:
00123 case CFBDecrypt:
00124
00125 DES_ede3_cfb64_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
00126 &ivec, &ivecoff,
00127 mode == CFBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
00128 break;
00129 case CBCEncrypt:
00130 DES_ede3_cbc_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
00131 &ivec, DES_ENCRYPT);
00132 break;
00133 case CBCDecrypt:
00134 DES_ede3_cbc_encrypt(data, crypt, len, &deskey1, &deskey2, &deskey3,
00135 &ivec, DES_DECRYPT);
00136 break;
00137 }
00138 return success;
00139 }
00140
00141
00142
00143
00144 WvTripleDESStream::WvTripleDESStream(WvStream *_cloned, const void *_key1,
00145 const void *_key2, const void *_key3,
00146 WvTripleDESEncoder::Mode readmode,
00147 WvTripleDESEncoder::Mode writemode) :
00148 WvEncoderStream(_cloned)
00149 {
00150 readchain.append(new WvTripleDESEncoder(readmode,
00151 _key1, _key2, _key3), true);
00152 writechain.append(new WvTripleDESEncoder(writemode,
00153 _key1, _key2, _key3), true);
00154 }