00001
00002
00003
00004
00005
00006
00007 #include "wvtripledes.h"
00008 #include <assert.h>
00009 #include <openssl/rand.h>
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 WvTripleDESEncoder::WvTripleDESEncoder(Mode _mode, const void *_key1,
00020 const void *_key2, const void *_key3) :
00021 mode(_mode)
00022 {
00023 setkey(_key1, _key2, _key3);
00024 }
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 bool WvTripleDESEncoder::_reset()
00037 {
00038 memset(ivec, 0, sizeof(ivec));
00039 ivecoff = 0;
00040 return true;
00041 }
00042
00043
00044 void WvTripleDESEncoder::setkey(const void *_key1, const void *_key2,
00045 const void *_key3)
00046 {
00047 memcpy(key, _key1, DES_KEY_SZ);
00048 des_set_key(&key, deskey1);
00049
00050 memcpy(key, _key2, DES_KEY_SZ);
00051 des_set_key(&key, deskey2);
00052
00053 memcpy(key, _key3, DES_KEY_SZ);
00054 des_set_key(&key, deskey3);
00055
00056 memset(ivec, 0, sizeof(ivec));
00057 ivecoff = 0;
00058 }
00059
00060
00061 void WvTripleDESEncoder::setiv(const void *_iv)
00062 {
00063 memcpy(ivec, _iv, sizeof(ivec));
00064 ivecoff = 0;
00065 }
00066
00067 bool WvTripleDESEncoder::_encode(WvBuf &in, WvBuf &out, bool flush)
00068 {
00069 size_t len = in.used();
00070 bool success = true;
00071 switch (mode) {
00072 case ECBEncrypt:
00073 case ECBDecrypt:
00074 case CBCEncrypt:
00075 case CBCDecrypt:
00076 {
00077 size_t remainder = len & 7;
00078 len -= remainder;
00079 if (remainder != 0 && flush)
00080 {
00081 if (mode == ECBEncrypt || mode == CBCEncrypt)
00082 {
00083
00084 size_t padlen = 8 - remainder;
00085 unsigned char *pad = in.alloc(padlen);
00086 RAND_pseudo_bytes(pad, padlen);
00087 len += 8;
00088 }
00089 else
00090 success = false;
00091 }
00092 }
00093
00094 default:
00095 break;
00096 }
00097
00098 if (len == 0)
00099 return success;
00100
00101 const unsigned char *data = in.get(len);
00102 unsigned char *crypt = out.alloc(len);
00103
00104 switch (mode)
00105 {
00106 case ECBEncrypt:
00107 case ECBDecrypt:
00108
00109 while (len >= 8)
00110 {
00111
00112 des_ecb3_encrypt((const_des_cblock*)&data, (des_cblock*)&crypt,
00113 deskey1, deskey2, deskey3,
00114 mode == ECBEncrypt ? DES_ENCRYPT : DES_DECRYPT);
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 }