WvStreams
wvcountermode.cc
00001 /*
00002  * Worldvisions Tunnel Vision Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  * 
00005  * A 'counter mode' cryptography engine abstraction.
00006  */
00007 #include "wvcountermode.h"
00008 
00009 
00010 WvCounterModeEncoder::WvCounterModeEncoder(WvEncoder *_keycrypt,
00011     const void *_counter, size_t _countersize) :
00012     keycrypt(_keycrypt), counter(NULL)
00013 {
00014     setcounter(_counter, _countersize);
00015 }
00016 
00017 
00018 WvCounterModeEncoder::~WvCounterModeEncoder()
00019 {
00020     delete keycrypt;
00021     deletev counter;
00022 }
00023 
00024 
00025 void WvCounterModeEncoder::setcounter(const void *_counter, size_t _countersize)
00026 {
00027     deletev counter;
00028     counter = new unsigned char[_countersize];
00029     countersize = _countersize;
00030     memcpy(counter, _counter, countersize);
00031 }
00032 
00033 
00034 void WvCounterModeEncoder::getcounter(void *_counter) const
00035 {
00036     memcpy(_counter, counter, countersize);
00037 }
00038 
00039 
00040 void WvCounterModeEncoder::incrcounter()
00041 {
00042     for (size_t i = 0; i < countersize && ! ++counter[i]; ++i);
00043 }
00044 
00045 
00046 bool WvCounterModeEncoder::_encode(WvBuf &inbuf, WvBuf &outbuf,
00047     bool flush)
00048 {
00049     bool success = true;
00050     size_t avail = inbuf.used();
00051     size_t offset = outbuf.used();
00052     
00053     // generate a key stream
00054     size_t len;
00055     for (len = avail; len >= countersize; len -= countersize)
00056     {
00057         counterbuf.reset(counter, countersize);
00058         success = keycrypt->encode(counterbuf, outbuf, true);
00059         if (! success) break;
00060         incrcounter();
00061     }
00062     if (flush && len != 0 && success)
00063     {
00064         counterbuf.reset(counter, countersize);
00065         success = keycrypt->encode(counterbuf, outbuf, true);
00066         if (success)
00067         {
00068             outbuf.unalloc(countersize - len);
00069             len = 0;
00070             incrcounter();
00071         }
00072         else
00073             outbuf.unalloc(outbuf.used() - offset - avail);
00074     }
00075     avail -= len;
00076     
00077     // XOR in the data
00078     while (avail > 0)
00079     {
00080         len = outbuf.optpeekable(offset);
00081         unsigned char *dataout = outbuf.mutablepeek(offset, len);
00082         size_t lenopt = inbuf.optgettable();
00083         if (len > lenopt)
00084             len = lenopt;
00085         const unsigned char *datain = inbuf.get(len);
00086         
00087         if (len >= avail)
00088         {
00089             len = avail;
00090             avail = 0;
00091         }
00092         else
00093         {
00094             avail -= len;
00095             offset += len;
00096         }
00097         while (len-- > 0)
00098             *(dataout++) ^= *(datain++);
00099     }
00100     return success;
00101 }