Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvtripledes.cc

Go to the documentation of this file.
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 /* As of openssl 0.9.7 the des_* functions have been renamed to DES_* .
00012    Don't as me why, but they have, so eventually, when resonance is upgraded
00013    to sarge, about the GNU Hurd 1.0 is released, these functions should be
00014    changed.
00015 */
00016 
00017 /***** WvTripleDESEncoder ****/
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 // WvTripleDESEncoder::~WvTripleDESEncoder()
00028 // {
00029 //     delete[] key;
00030 //     delete deskey1;
00031 //     delete deskey2;
00032 //     delete deskey3;
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: // The caller should ensure the padding is correct or
00075     case CBCDecrypt: // we do it for them, in probably the wrong way.
00076     {
00077         size_t remainder = len & 7; // conviently this is the same as len % 8
00078         len -= remainder;
00079         if (remainder != 0 && flush)
00080         {
00081             if (mode == ECBEncrypt || mode == CBCEncrypt)
00082             {
00083                 // if flushing on encryption, add some randomized padding
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 // nothing we can do here, flushing does not make sense!
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         // ECB works 64bits at a time
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         // CFB simulates a stream
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 /***** WvTripleDESStream *****/
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 }

Generated on Sat Feb 21 21:05:34 2004 for WvStreams by doxygen 1.3.5