WvStreams
|
00001 /* 00002 * Worldvisions Tunnel Vision Software: 00003 * Copyright (C) 1997-2003 Net Integration Technologies, Inc. 00004 * 00005 * TripleDES cryptography abstractions. 00006 */ 00007 #include "wvtripledes.h" 00008 #include <assert.h> 00009 #include <openssl/rand.h> 00010 00011 /***** WvTripleDESEncoder ****/ 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 // WvTripleDESEncoder::~WvTripleDESEncoder() 00022 // { 00023 // delete[] key; 00024 // delete deskey1; 00025 // delete deskey2; 00026 // delete deskey3; 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: // The caller should ensure the padding is correct or 00069 case CBCDecrypt: // we do it for them, in probably the wrong way. 00070 { 00071 size_t remainder = len & 7; // conviently this is the same as len % 8 00072 len -= remainder; 00073 if (remainder != 0 && flush) 00074 { 00075 if (mode == ECBEncrypt || mode == CBCEncrypt) 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 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 // ECB works 64bits at a time 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 // CFB simulates a stream 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 /***** WvTripleDESStream *****/ 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 }