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 }