00001
00002
00003
00004
00005
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 delete[] counter;
00022 }
00023
00024
00025 void WvCounterModeEncoder::setcounter(const void *_counter, size_t _countersize)
00026 {
00027 delete[] 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
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
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 }